diff options
257 files changed, 2267 insertions, 1831 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 88c9e1a8a0..fe5631cefd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ability to convert visual shaders to text-based shaders. - See the [complete list of new functions](https://github.com/godotengine/godot/pull/26164). - Improved visual scripting. - - Visual scripting now uses an unified graph where all functions are represented. + - Visual scripting now uses a unified graph where all functions are represented. - Nodes can now be edited directly in the graph. - Support for fuzzy searching. - The `tool` mode can now be enabled in visual scripts. @@ -900,7 +900,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Removed many debugging prints in the console. - Export templates now display an error dialog if no project was found when starting. - DynamicFont oversampling is now enabled by default. -- Nodes' internal logic now consistently use internal physics processing. +- Nodes' internal logic now consistently uses internal physics processing. - Allow attaching and clearing scripts on multiple nodes at once. - Default values are no longer saved in scene and resource files. - The selection rectangle of 2D nodes is now hidden when not pertinent (no more rectangle for collision shapes). diff --git a/SConstruct b/SConstruct index 28257e1fde..65a8d9e302 100644 --- a/SConstruct +++ b/SConstruct @@ -61,14 +61,15 @@ elif platform_arg == "javascript": # Use generic POSIX build toolchain for Emscripten. custom_tools = ["cc", "c++", "ar", "link", "textfile", "zip"] -env_base = Environment( - ENV={ - "PATH": os.getenv("PATH"), - "PKG_CONFIG_PATH": os.getenv("PKG_CONFIG_PATH"), - "TERM": os.getenv("TERM"), - }, - tools=custom_tools, -) +# We let SCons build its default ENV as it includes OS-specific things which we don't +# want to have to pull in manually. +# Then we prepend PATH to make it take precedence, while preserving SCons' own entries. +env_base = Environment(tools=custom_tools) +env_base.PrependENVPath("PATH", os.getenv("PATH")) +env_base.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) +if "TERM" in os.environ: # Used for colored output. + env_base["ENV"]["TERM"] = os.environ["TERM"] + env_base.disabled_modules = [] env_base.module_version_string = "" env_base.msvc = False @@ -384,7 +385,7 @@ if selected_platform in platform_list: if not (f[0] in ARGUMENTS): # allow command line to override platform flags env[f[0]] = f[1] - # Must happen after the flags definition, so that they can be used by platform detect + # Must happen after the flags' definition, so that they can be used by platform detect detect.configure(env) # Set our C and C++ standard requirements. diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 02effc2001..f7a6a8ece0 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -393,7 +393,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b if (exec_path != "") { // We do several tests sequentially until one succeeds to find a PCK, - // and if so we attempt loading it at the end. + // and if so, we attempt loading it at the end. // Attempt with PCK bundled into executable. bool found = _load_resource_pack(exec_path); diff --git a/core/core_bind.cpp b/core/core_bind.cpp index e7a77384da..c3d547c2c7 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -373,6 +373,9 @@ Dictionary _OS::get_time(bool utc) const { * @return epoch calculated */ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { + // if datetime is an empty Dictionary throws an error + ERR_FAIL_COND_V_MSG(datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty"); + // Bunch of conversion constants static const unsigned int SECONDS_PER_MINUTE = 60; static const unsigned int MINUTES_PER_HOUR = 60; @@ -1374,9 +1377,9 @@ Vector<String> _File::get_csv_line(const String &p_delim) const { return f->get_csv_line(p_delim); } -/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) +/**< use this for files WRITTEN in _big_ endian machines (i.e. amiga/mac) * It's not about the current CPU type but file formats. - * this flags get reset to false (little endian) on each open + * These flags get reset to false (little endian) on each open */ void _File::set_endian_swap(bool p_swap) { diff --git a/core/core_constants.cpp b/core/core_constants.cpp index f9edff1899..a99df93638 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -521,8 +521,10 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_NAVIGATION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_NAVIGATION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DIR); diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index f43f3e3290..6b3953f588 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -100,7 +100,7 @@ void Crypto::load_default_certificates(String p_path) { PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg) { Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create()); - ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available witout mbedtls module."); + ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available without mbedtls module."); Error err = ctx->start(p_hash_type, p_key); ERR_FAIL_COND_V(err != OK, PackedByteArray()); err = ctx->update(p_msg); @@ -108,7 +108,7 @@ PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, Packed return ctx->finish(); } -// Compares two HMACS for equality without leaking timing information in order to prevent timing attakcs. +// Compares two HMACS for equality without leaking timing information in order to prevent timing attacks. // @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy bool Crypto::constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received) { const uint8_t *t = p_trusted.ptr(); diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 895b8c23a9..e5dba029c9 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -192,7 +192,7 @@ void EngineDebugger::deinitialize() { singleton = nullptr; } - // Clear profilers/captuers/protocol handlers. + // Clear profilers/captures/protocol handlers. profilers.clear(); captures.clear(); protocols.clear(); diff --git a/core/input/input.cpp b/core/input/input.cpp index f928ae7654..3a8c1c1628 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -723,7 +723,7 @@ void Input::warp_mouse_position(const Vector2 &p_to) { Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { // The relative distance reported for the next event after a warp is in the boundaries of the - // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod() + // size of the rect on that axis, but it may be greater, in which case there's no problem as fmod() // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation // and the subsequent event, the reported relative distance will be less than the size of the rect // and thus fmod() will be disabled for handling the situation. @@ -779,7 +779,7 @@ bool Input::is_emulating_touch_from_mouse() const { return emulate_touch_from_mouse; } -// Calling this whenever the game window is focused helps unstucking the "touch mouse" +// Calling this whenever the game window is focused helps unsticking the "touch mouse" // if the OS or its abstraction class hasn't properly reported that touch pointers raised void Input::ensure_touch_mouse_raised() { if (mouse_from_touch_index != -1) { diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index e0b25fa092..7d85fd6492 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -567,6 +567,7 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() { inputs.push_back(InputEventKey::create_reference(KEY_E | KEY_MASK_CTRL)); inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD)); default_builtin_cache.insert("ui_text_caret_line_end.OSX", inputs); + // Text Caret Movement Page Up/Down inputs = List<Ref<InputEvent>>(); diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 456023e2a6..980234cbfc 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -181,8 +181,8 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p } /** - This will handle both Gzip and Deflat streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector. - This is required for compressed data who's final uncompressed size is unknown, as is the case for HTTP response bodies. + This will handle both Gzip and Deflate streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector. + This is required for compressed data whose final uncompressed size is unknown, as is the case for HTTP response bodies. This is much slower however than using Compression::decompress because it may result in multiple full copies of the output buffer. */ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode) { @@ -248,7 +248,7 @@ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_s out_mark += gzip_chunk; - // Encorce max output size + // Enforce max output size if (p_max_dst_size > -1 && strm.total_out > (uint64_t)p_max_dst_size) { (void)inflateEnd(&strm); p_dst_vect->resize(0); diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 6b550e69c8..94060cfe0b 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -50,7 +50,7 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas // Do nothing. } break; case MultiplayerAPI::RPC_MODE_REMOTE: { - // Do nothing also. Remote cannot produce a local call. + // Do nothing. Remote cannot produce a local call. } break; case MultiplayerAPI::RPC_MODE_MASTERSYNC: { if (is_master) { @@ -675,7 +675,7 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin return err; } if (r_buffer) { - // The first byte is not used by the marshaling, so store the type + // The first byte is not used by the marshalling, so store the type // so we know how to decompress and decode this variant. r_buffer[0] = p_variant.get_type(); } @@ -791,7 +791,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p packet_cache.resize(m_amount); // Encode meta. - // The meta is composed by a single byte that contains (starting from the least segnificant bit): + // The meta is composed by a single byte that contains (starting from the least significant bit): // - `NetworkCommands` in the first three bits. // - `NetworkNodeIdCompression` in the next 2 bits. // - `NetworkNameIdCompression` in the next 1 bit. @@ -830,7 +830,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p ofs += 4; } } else { - // The targets doesn't know the node yet, so we need to use 32 bits int. + // The targets don't know the node yet, so we need to use 32 bits int. node_id_compression = NETWORK_NODE_ID_COMPRESSION_32; MAKE_ROOM(ofs + 4); encode_uint32(psc->id, &(packet_cache.write[ofs])); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index d8d63d976f..3f46f2706e 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -224,7 +224,7 @@ Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) { // I see no reason why we should get ERR_BUSY (wouldblock/eagain) here. // This is UDP, so connect is only used to tell the OS to which socket - // it shuold deliver packets when multiple are bound on the same address/port. + // it should deliver packets when multiple are bound on the same address/port. if (err != OK) { close(); ERR_FAIL_V_MSG(FAILED, "Unable to connect"); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index fb6ad7d65e..c4eb2a20bb 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1245,7 +1245,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - return ""; //could not rwead + return ""; //could not read } ResourceLoaderBinary loader; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 8275dd0ad4..dcf71bb4a9 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -215,7 +215,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { load_task.loader_id = Thread::get_caller_id(); if (load_task.semaphore) { - //this is an actual thread, so wait for Ok fom semaphore + //this is an actual thread, so wait for Ok from semaphore thread_load_semaphore->wait(); //wait until its ok to start loading } load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress); @@ -443,7 +443,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { ThreadLoadTask &load_task = thread_load_tasks[local_path]; - //semaphore still exists, meaning its still loading, request poll + //semaphore still exists, meaning it's still loading, request poll Semaphore *semaphore = load_task.semaphore; if (semaphore) { load_task.poll_requests++; @@ -452,7 +452,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { // As we got a semaphore, this means we are going to have to wait // until the sub-resource is done loading // - // As this thread will become 'blocked' we should "echange" its + // As this thread will become 'blocked' we should "exchange" its // active status with a waiting one, to ensure load continues. // // This ensures loading is never blocked and that is also within diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index 0e11ff514a..9adf912224 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -194,7 +194,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { l = l.substr(1, l.length()); // Find final quote, ignoring escaped ones (\"). // The escape_next logic is necessary to properly parse things like \\" - // where the blackslash is the one being escaped, not the quote. + // where the backslash is the one being escaped, not the quote. int end_pos = -1; bool escape_next = false; for (int i = 0; i < l.length(); i++) { diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 1574634aad..d5eb32513b 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -344,7 +344,7 @@ void XMLParser::_bind_methods() { } Error XMLParser::read() { - // if not end reached, parse the node + // if end not reached, parse the node if (P && (P - data) < (int64_t)length - 1 && *P != 0) { _parse_current_node(); return OK; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index cbdd8a8c9f..cc2b7c6611 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -132,7 +132,7 @@ bool Basis::is_symmetric() const { Basis Basis::diagonalize() { //NOTE: only implemented for symmetric matrices -//with the Jacobi iterative method method +//with the Jacobi iterative method #ifdef MATH_CHECKS ERR_FAIL_COND_V(!is_symmetric(), Basis()); #endif @@ -317,7 +317,7 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const { // Multiplies the matrix from left by the rotation matrix: M -> R.M // Note that this does *not* rotate the matrix itself. // -// The main use of Basis is as Transform.basis, which is used a the transformation matrix +// The main use of Basis is as Transform.basis, which is used by the transformation matrix // of 3D object. Rotate here refers to rotation of the object (which is R * (*this)), // not the matrix itself (which is R * (*this) * R.transposed()). Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const { @@ -881,7 +881,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { if ((Math::abs(elements[1][0] - elements[0][1]) < epsilon) && (Math::abs(elements[2][0] - elements[0][2]) < epsilon) && (Math::abs(elements[2][1] - elements[1][2]) < epsilon)) { // singularity found // first check for identity matrix which must have +1 for all terms - // in leading diagonaland zero in other terms + // in leading diagonal and zero in other terms if ((Math::abs(elements[1][0] + elements[0][1]) < epsilon2) && (Math::abs(elements[2][0] + elements[0][2]) < epsilon2) && (Math::abs(elements[2][1] + elements[1][2]) < epsilon2) && (Math::abs(elements[0][0] + elements[1][1] + elements[2][2] - 3) < epsilon2)) { // this singularity is identity matrix so angle = 0 r_axis = Vector3(0, 1, 0); diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 636ea601c7..f7ac44d321 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -978,7 +978,7 @@ Expression::ENode *Expression::_parse_expression() { } } - /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ + /* Reduce the set of expressions and place them in an operator tree, respecting precedence */ while (expression.size() > 1) { int next_op = -1; diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp index d67be14d33..feb1fb2fb8 100644 --- a/core/math/geometry_2d.cpp +++ b/core/math/geometry_2d.cpp @@ -87,9 +87,9 @@ struct _AtlasWorkRectResult { void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) { // Super simple, almost brute force scanline stacking fitter. // It's pretty basic for now, but it tries to make sure that the aspect ratio of the - // resulting atlas is somehow square. This is necessary because video cards have limits. - // On texture size (usually 2048 or 4096), so the more square a texture, the more chances. - // It will work in every hardware. + // resulting atlas is somehow square. This is necessary because video cards have limits + // on texture size (usually 2048 or 4096), so the squarer a texture, the more the chances + // that it will work in every hardware. // For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a // 256x8192 atlas (won't work anywhere). diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index ad28967d7a..fe18cc3d41 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -268,7 +268,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) { FaceConnect &fc = E->get(); if (fc.left && fc.right) { - continue; //edge is uninteresting, not on horizont + continue; //edge is uninteresting, not on horizon } //create new face! diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index 0047c0705d..fa1588dbc5 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -97,7 +97,7 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in // It can happen that the triangulation ends up with three aligned vertices to deal with. // In this scenario, making the check below strict may reject the possibility of - // forming a last triangle with these aligned vertices, preventing the triangulatiom + // forming a last triangle with these aligned vertices, preventing the triangulation // from completing. // To avoid that we allow zero-area triangles if all else failed. float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON; diff --git a/core/object/object.cpp b/core/object/object.cpp index 1a9cce49d8..413f917518 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -596,7 +596,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons _get_property_listv(p_list, p_reversed); - if (!is_class("Script")) { // can still be set, but this is for userfriendlyness + if (!is_class("Script")) { // can still be set, but this is for user-friendliness p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } if (!metadata.is_empty()) { @@ -1671,7 +1671,7 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> for (int i = 1; i < p_path.size(); i++) { if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) { - // We cannot be sure about the type of properties this types can have + // We cannot be sure about the type of properties this type can have if (r_valid) { *r_valid = false; } @@ -1719,10 +1719,10 @@ void *Object::get_script_instance_binding(int p_script_language_index) { ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, nullptr); #endif - //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of syncro + //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of sync //just return the same pointer. //if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it - //as it should not really affect performance much (won't be called too often), as in far most caes the condition below will be false afterwards + //as it should not really affect performance much (won't be called too often), as in far most cases the condition below will be false afterwards if (!_script_instance_bindings[p_script_language_index]) { void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this); diff --git a/core/object/object.h b/core/object/object.h index 029478873d..448a33d3bc 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -66,8 +66,10 @@ enum PropertyHint { PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, PROPERTY_HINT_LAYERS_2D_PHYSICS, + PROPERTY_HINT_LAYERS_2D_NAVIGATION, PROPERTY_HINT_LAYERS_3D_RENDER, PROPERTY_HINT_LAYERS_3D_PHYSICS, + PROPERTY_HINT_LAYERS_3D_NAVIGATION, PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," PROPERTY_HINT_DIR, ///< a directory path must be passed PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp index b538ca0c96..9be3a62e2f 100644 --- a/core/os/pool_allocator.cpp +++ b/core/os/pool_allocator.cpp @@ -136,7 +136,7 @@ void PoolAllocator::compact_up(int p_from) { for (int i = entry_count - 1; i >= p_from; i--) { Entry &entry = entry_array[entry_indices[i]]; - /* determine hole size to nextious entry */ + /* determine hole size for next entry */ int hole_size = next_entry_end_pos - (entry.pos + aligned(entry.len)); diff --git a/core/os/thread.cpp b/core/os/thread.cpp index f1fcfdf7e1..73e31bdb3d 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -47,7 +47,7 @@ uint64_t Thread::_thread_id_hash(const std::thread::id &p_t) { } Thread::ID Thread::main_thread_id = _thread_id_hash(std::this_thread::get_id()); -thread_local Thread::ID Thread::caller_id = _thread_id_hash(std::this_thread::get_id()); +thread_local Thread::ID Thread::caller_id = 0; void Thread::_set_platform_funcs( Error (*p_set_name_func)(const String &), @@ -112,6 +112,10 @@ Error Thread::set_name(const String &p_name) { return ERR_UNAVAILABLE; } +Thread::Thread() { + caller_id = _thread_id_hash(std::this_thread::get_id()); +} + Thread::~Thread() { if (id != _thread_id_hash(std::thread::id())) { #ifdef DEBUG_ENABLED diff --git a/core/os/thread.h b/core/os/thread.h index 599585051f..17ac82c650 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -98,6 +98,7 @@ public: ///< waits until thread is finished, and deallocates it. void wait_to_finish(); + Thread(); ~Thread(); #else _FORCE_INLINE_ ID get_id() const { return 0; } diff --git a/core/string/compressed_translation.cpp b/core/string/compressed_translation.cpp index ad90924293..15abf63f7e 100644 --- a/core/string/compressed_translation.cpp +++ b/core/string/compressed_translation.cpp @@ -44,7 +44,7 @@ struct _PHashTranslationCmp { void PHashTranslation::generate(const Ref<Translation> &p_from) { // This method compresses a Translation instance. - // Right now it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed. + // Right now, it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed. #ifdef TOOLS_ENABLED List<StringName> keys; p_from->get_message_list(&keys); diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 846afe761b..42ba30fbe5 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -158,7 +158,7 @@ int TranslationPO::_get_plural_index(int p_n) const { void TranslationPO::_cache_plural_tests(const String &p_plural_rule) { // Some examples of p_plural_rule passed in can have the form: // "n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5" (Arabic) - // "n >= 2" (French) // When evaluating the last, esp careful with this one. + // "n >= 2" (French) // When evaluating the last, especially careful with this one. // "n != 1" (English) int first_ques_mark = p_plural_rule.find("?"); if (first_ques_mark == -1) { diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index a57c7b2504..28228e4a83 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1764,7 +1764,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { if (skip) { _UNICERROR("no space left"); - return true; //not enough spac + return true; //not enough space } } @@ -4394,6 +4394,18 @@ String String::property_name_encode() const { return *this; } +// Changes made to the set of invalid characters must also be reflected in the String documentation. +const String String::invalid_node_name_characters = ". : @ / \""; + +String String::validate_node_name() const { + Vector<String> chars = String::invalid_node_name_characters.split(" "); + String name = this->replace(chars[0], ""); + for (int i = 1; i < chars.size(); i++) { + name = name.replace(chars[i], ""); + } + return name; +} + String String::get_basename() const { int pos = rfind("."); if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) { @@ -4468,7 +4480,7 @@ String String::sprintf(const Array &values, bool *error) const { for (; *self; self++) { const char32_t c = *self; - if (in_format) { // We have % - lets see what else we get. + if (in_format) { // We have % - let's see what else we get. switch (c) { case '%': { // Replace %% with % formatted += chr(c); diff --git a/core/string/ustring.h b/core/string/ustring.h index 821941036f..1e362d7683 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -419,6 +419,10 @@ public: String property_name_encode() const; + // node functions + static const String invalid_node_name_characters; + String validate_node_name() const; + bool is_valid_identifier() const; bool is_valid_integer() const; bool is_valid_float() const; diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 9a2922a777..347c6cd82e 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -141,7 +141,7 @@ uint32_t Array::hash() const { void Array::_assign(const Array &p_array) { if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { - //same type or untyped, just reference, shuold be fine + //same type or untyped, just reference, should be fine _ref(p_array); } else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway _p->array = p_array._p->array; diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index bd51e2dd1e..a1d9c5ed2f 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -126,7 +126,7 @@ bool Callable::operator==(const Callable &p_callable) const { if (custom_a == custom_b) { if (custom_a) { if (custom == p_callable.custom) { - return true; //same pointer, dont even compare + return true; //same pointer, don't even compare } CallableCustom::CompareEqualFunc eq_a = custom->get_compare_equal_func(); @@ -155,7 +155,7 @@ bool Callable::operator<(const Callable &p_callable) const { if (custom_a == custom_b) { if (custom_a) { if (custom == p_callable.custom) { - return false; //same pointer, dont even compare + return false; //same pointer, don't even compare } CallableCustom::CompareLessFunc less_a = custom->get_compare_less_func(); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 54ca1a911d..90272ad5b4 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -956,6 +956,8 @@ static void _register_variant_builtin_methods() { bind_method(String, c_unescape, sarray(), varray()); bind_method(String, json_escape, sarray(), varray()); + bind_method(String, validate_node_name, sarray(), varray()); + bind_method(String, is_valid_identifier, sarray(), varray()); bind_method(String, is_valid_integer, sarray(), varray()); bind_method(String, is_valid_float, sarray(), varray()); diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index ea8263402a..f9cc7c4ff4 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -2198,7 +2198,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case STRING: { - //this is pretty funny and bizarre, but artists like to use it for typewritter effects + //this is pretty funny and bizarre, but artists like to use it for typewriter effects String sa = *reinterpret_cast<const String *>(a._data._mem); String sb = *reinterpret_cast<const String *>(b._data._mem); String dst; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 3ca7e0716b..d57d241b53 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1280,6 +1280,10 @@ <constant name="HORIZONTAL" value="0" enum="Orientation"> General horizontal alignment, usually used for [Separator], [ScrollBar], [Slider], etc. </constant> + <constant name="CLOCKWISE" value="0" enum="ClockDirection"> + </constant> + <constant name="COUNTERCLOCKWISE" value="1" enum="ClockDirection"> + </constant> <constant name="HALIGN_LEFT" value="0" enum="HAlign"> Horizontal left alignment, usually for text-derived classes. </constant> @@ -2405,43 +2409,49 @@ <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="9" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D physics layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="10" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="10" enum="PropertyHint"> + Hints that an integer property is a bitmask using the optionally named 2D navigation layers. + </constant> + <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="11" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D render layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="11" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="12" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D physics layers. </constant> - <constant name="PROPERTY_HINT_FILE" value="12" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="13" enum="PropertyHint"> + Hints that an integer property is a bitmask using the optionally named 2D navigation layers. + </constant> + <constant name="PROPERTY_HINT_FILE" value="14" enum="PropertyHint"> Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_DIR" value="13" enum="PropertyHint"> + <constant name="PROPERTY_HINT_DIR" value="15" enum="PropertyHint"> Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_GLOBAL_FILE" value="14" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_FILE" value="16" enum="PropertyHint"> Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_GLOBAL_DIR" value="15" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_DIR" value="17" enum="PropertyHint"> Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="16" enum="PropertyHint"> + <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="18" enum="PropertyHint"> Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate. </constant> - <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="17" enum="PropertyHint"> + <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="19" enum="PropertyHint"> Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed. </constant> - <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="18" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint"> Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use. </constant> - <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="19" enum="PropertyHint"> + <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint"> Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="20" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint"> Hints that an image is compressed using lossy compression. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="21" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint"> Hints that an image is compressed using lossless compression. </constant> - <constant name="PROPERTY_HINT_TYPE_STRING" value="23" enum="PropertyHint"> + <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint"> Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance: [codeblock] hint_string = "%s:" % [TYPE_INT] # Array of inteters. diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fa6cf372ce..fa0c3b167a 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -93,7 +93,7 @@ <member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold"> Threshold at which the alpha scissor will discard values. </member> - <member name="anisotropy" type="float" setter="set_anisotropy" getter="get_anisotropy"> + <member name="anisotropy" type="float" setter="set_anisotropy" getter="get_anisotropy" default="0.0"> The strength of the anisotropy effect. </member> <member name="anisotropy_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> @@ -105,19 +105,19 @@ <member name="ao_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], ambient occlusion is enabled. Ambient occlusion darkens areas based on the [member ao_texture]. </member> - <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect"> + <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect" default="0.0"> Amount that ambient occlusion affects lighting from lights. If [code]0[/code], ambient occlusion only affects ambient light. If [code]1[/code], ambient occlusion affects lights just as much as it affects ambient light. This can be used to impact the strength of the ambient occlusion effect, but typically looks unrealistic. </member> - <member name="ao_on_uv2" type="bool" setter="set_flag" getter="get_flag"> + <member name="ao_on_uv2" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], use [code]UV2[/code] coordinates to look up from the [member ao_texture]. </member> <member name="ao_texture" type="Texture2D" setter="set_texture" getter="get_texture"> Texture that defines the amount of ambient occlusion for a given point on the object. </member> - <member name="ao_texture_channel" type="int" setter="set_ao_texture_channel" getter="get_ao_texture_channel" enum="BaseMaterial3D.TextureChannel"> + <member name="ao_texture_channel" type="int" setter="set_ao_texture_channel" getter="get_ao_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0"> Specifies the channel of the [member ao_texture] in which the ambient occlusion information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use. </member> - <member name="backlight" type="Color" setter="set_backlight" getter="get_backlight"> + <member name="backlight" type="Color" setter="set_backlight" getter="get_backlight" default="Color( 0, 0, 0, 1 )"> The color used by the backlight effect. Represents the light passing through an object. </member> <member name="backlight_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> @@ -137,13 +137,13 @@ The material's blend mode. [b]Note:[/b] Values other than [code]Mix[/code] force the object into the transparent pipeline. See [enum BlendMode]. </member> - <member name="clearcoat" type="float" setter="set_clearcoat" getter="get_clearcoat"> + <member name="clearcoat" type="float" setter="set_clearcoat" getter="get_clearcoat" default="1.0"> Sets the strength of the clearcoat effect. Setting to [code]0[/code] looks the same as disabling the clearcoat effect. </member> <member name="clearcoat_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], clearcoat rendering is enabled. Adds a secondary transparent pass to the lighting calculation resulting in an added specular blob. This makes materials appear as if they have a clear layer on them that can be either glossy or rough. </member> - <member name="clearcoat_gloss" type="float" setter="set_clearcoat_gloss" getter="get_clearcoat_gloss"> + <member name="clearcoat_gloss" type="float" setter="set_clearcoat_gloss" getter="get_clearcoat_gloss" default="0.5"> Sets the roughness of the clearcoat pass. A higher value results in a smoother clearcoat while a lower value results in a rougher clearcoat. </member> <member name="clearcoat_texture" type="Texture2D" setter="set_texture" getter="get_texture"> @@ -158,7 +158,7 @@ <member name="detail_albedo" type="Texture2D" setter="set_texture" getter="get_texture"> Texture that specifies the color of the detail overlay. </member> - <member name="detail_blend_mode" type="int" setter="set_detail_blend_mode" getter="get_detail_blend_mode" enum="BaseMaterial3D.BlendMode"> + <member name="detail_blend_mode" type="int" setter="set_detail_blend_mode" getter="get_detail_blend_mode" enum="BaseMaterial3D.BlendMode" default="0"> Specifies how the [member detail_albedo] should blend with the current [code]ALBEDO[/code]. See [enum BlendMode] for options. </member> <member name="detail_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> @@ -171,7 +171,7 @@ Texture that specifies the per-pixel normal of the detail overlay. [b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines. </member> - <member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="BaseMaterial3D.DetailUV"> + <member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="BaseMaterial3D.DetailUV" default="0"> Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options. </member> <member name="diffuse_mode" type="int" setter="set_diffuse_mode" getter="get_diffuse_mode" enum="BaseMaterial3D.DiffuseMode" default="0"> @@ -183,30 +183,30 @@ <member name="disable_receive_shadows" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], the object receives no shadow that would otherwise be cast onto it. </member> - <member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance"> + <member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance" default="10.0"> Distance at which the object appears fully opaque. [b]Note:[/b] If [code]distance_fade_max_distance[/code] is less than [code]distance_fade_min_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code]. </member> - <member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance"> + <member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance" default="0.0"> Distance at which the object starts to become visible. If the object is less than this distance away, it will be invisible. [b]Note:[/b] If [code]distance_fade_min_distance[/code] is greater than [code]distance_fade_max_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code]. </member> <member name="distance_fade_mode" type="int" setter="set_distance_fade" getter="get_distance_fade" enum="BaseMaterial3D.DistanceFadeMode" default="0"> Specifies which type of fade to use. Can be any of the [enum DistanceFadeMode]s. </member> - <member name="emission" type="Color" setter="set_emission" getter="get_emission"> + <member name="emission" type="Color" setter="set_emission" getter="get_emission" default="Color( 0, 0, 0, 1 )"> The emitted light's color. See [member emission_enabled]. </member> <member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [GIProbe] is used and this object is used in baked lighting. </member> - <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy"> + <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0"> The emitted light's strength. See [member emission_enabled]. </member> - <member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag"> + <member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag" default="false"> Use [code]UV2[/code] to read from the [member emission_texture]. </member> - <member name="emission_operator" type="int" setter="set_emission_operator" getter="get_emission_operator" enum="BaseMaterial3D.EmissionOperator"> + <member name="emission_operator" type="int" setter="set_emission_operator" getter="get_emission_operator" enum="BaseMaterial3D.EmissionOperator" default="0"> Sets how [member emission] interacts with [member emission_texture]. Can either add or multiply. See [enum EmissionOperator] for options. </member> <member name="emission_texture" type="Texture2D" setter="set_texture" getter="get_texture"> @@ -221,23 +221,23 @@ <member name="grow_amount" type="float" setter="set_grow" getter="get_grow" default="0.0"> Grows object vertices in the direction of their normals. </member> - <member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled"> + <member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled" default="false"> </member> <member name="heightmap_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled]. [b]Note:[/b] Height mapping is not supported if triplanar mapping is used on the same material. The value of [member heightmap_enabled] will be ignored if [member uv1_triplanar] is enabled. </member> - <member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal"> + <member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal" default="false"> </member> - <member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent"> + <member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent" default="false"> </member> - <member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag"> + <member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag" default="false"> </member> <member name="heightmap_max_layers" type="int" setter="set_heightmap_deep_parallax_max_layers" getter="get_heightmap_deep_parallax_max_layers"> </member> <member name="heightmap_min_layers" type="int" setter="set_heightmap_deep_parallax_min_layers" getter="get_heightmap_deep_parallax_min_layers"> </member> - <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale"> + <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="0.05"> </member> <member name="heightmap_texture" type="Texture2D" setter="set_texture" getter="get_texture"> </member> @@ -260,7 +260,7 @@ <member name="normal_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], normal mapping is enabled. </member> - <member name="normal_scale" type="float" setter="set_normal_scale" getter="get_normal_scale"> + <member name="normal_scale" type="float" setter="set_normal_scale" getter="get_normal_scale" default="1.0"> The strength of the normal map's effect. </member> <member name="normal_texture" type="Texture2D" setter="set_texture" getter="get_texture"> @@ -281,7 +281,7 @@ <member name="point_size" type="float" setter="set_point_size" getter="get_point_size" default="1.0"> The point size in pixels. See [member use_point_size]. </member> - <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance"> + <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance" default="1.0"> Distance over which the fade effect takes place. The larger the distance the longer it takes for an object to fade. </member> <member name="proximity_fade_enable" type="bool" setter="set_proximity_fade" getter="is_proximity_fade_enabled" default="false"> @@ -290,16 +290,16 @@ <member name="refraction_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> If [code]true[/code], the refraction effect is enabled. Distorts transparency based on light from behind the object. </member> - <member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction"> + <member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction" default="0.05"> The strength of the refraction effect. </member> <member name="refraction_texture" type="Texture2D" setter="set_texture" getter="get_texture"> Texture that controls the strength of the refraction per-pixel. Multiplied by [member refraction_scale]. </member> - <member name="refraction_texture_channel" type="int" setter="set_refraction_texture_channel" getter="get_refraction_texture_channel" enum="BaseMaterial3D.TextureChannel"> + <member name="refraction_texture_channel" type="int" setter="set_refraction_texture_channel" getter="get_refraction_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0"> Specifies the channel of the [member ao_texture] in which the ambient occlusion information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use. </member> - <member name="rim" type="float" setter="set_rim" getter="get_rim"> + <member name="rim" type="float" setter="set_rim" getter="get_rim" default="1.0"> Sets the strength of the rim lighting effect. </member> <member name="rim_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> @@ -308,7 +308,7 @@ <member name="rim_texture" type="Texture2D" setter="set_texture" getter="get_texture"> Texture used to set the strength of the rim lighting effect per-pixel. Multiplied by [member rim]. </member> - <member name="rim_tint" type="float" setter="set_rim_tint" getter="get_rim_tint"> + <member name="rim_tint" type="float" setter="set_rim_tint" getter="get_rim_tint" default="0.5"> 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" default="1.0"> @@ -332,24 +332,24 @@ <member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> 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_skin_mode" type="bool" setter="set_flag" getter="get_flag"> + <member name="subsurf_scatter_skin_mode" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], subsurface scattering will use a special mode optimized for the color and density of human skin. </member> - <member name="subsurf_scatter_strength" type="float" setter="set_subsurface_scattering_strength" getter="get_subsurface_scattering_strength"> + <member name="subsurf_scatter_strength" type="float" setter="set_subsurface_scattering_strength" getter="get_subsurface_scattering_strength" default="0.0"> The strength of the subsurface scattering effect. </member> <member name="subsurf_scatter_texture" type="Texture2D" setter="set_texture" getter="get_texture"> Texture used to control the subsurface scattering strength. Stored in the red texture channel. Multiplied by [member subsurf_scatter_strength]. </member> - <member name="subsurf_scatter_transmittance_boost" type="float" setter="set_transmittance_boost" getter="get_transmittance_boost"> + <member name="subsurf_scatter_transmittance_boost" type="float" setter="set_transmittance_boost" getter="get_transmittance_boost" default="0.0"> </member> - <member name="subsurf_scatter_transmittance_color" type="Color" setter="set_transmittance_color" getter="get_transmittance_color"> + <member name="subsurf_scatter_transmittance_color" type="Color" setter="set_transmittance_color" getter="get_transmittance_color" default="Color( 1, 1, 1, 1 )"> </member> - <member name="subsurf_scatter_transmittance_curve" type="float" setter="set_transmittance_curve" getter="get_transmittance_curve"> + <member name="subsurf_scatter_transmittance_curve" type="float" setter="set_transmittance_curve" getter="get_transmittance_curve" default="1.0"> </member> - <member name="subsurf_scatter_transmittance_depth" type="float" setter="set_transmittance_depth" getter="get_transmittance_depth"> + <member name="subsurf_scatter_transmittance_depth" type="float" setter="set_transmittance_depth" getter="get_transmittance_depth" default="0.1"> </member> - <member name="subsurf_scatter_transmittance_enabled" type="bool" setter="set_feature" getter="get_feature"> + <member name="subsurf_scatter_transmittance_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> </member> <member name="subsurf_scatter_transmittance_texture" type="Texture2D" setter="set_texture" getter="get_texture"> </member> diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml index aea3542867..2fc4313e47 100644 --- a/doc/classes/ColorPicker.xml +++ b/doc/classes/ColorPicker.xml @@ -91,6 +91,9 @@ <theme_item name="add_preset" type="Texture2D"> The icon for the "Add Preset" button. </theme_item> + <theme_item name="bar_arrow" type="Texture2D"> + The texture for the arrow grabber. + </theme_item> <theme_item name="color_hue" type="Texture2D"> Custom texture for the hue selection slider on the right. </theme_item> diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index 322cff4e43..1e9d089962 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -98,6 +98,13 @@ Creates an unshaded material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_mesh] and [method EditorNode3DGizmo.add_lines]. Should not be overridden. </description> </method> + <method name="get_gizmo_name" qualifiers="virtual"> + <return type="String"> + </return> + <description> + Override this method to provide the name that will appear in the gizmo visibility menu. + </description> + </method> <method name="get_handle_name" qualifiers="virtual"> <return type="String"> </return> @@ -131,13 +138,6 @@ Gets material from the internal list of materials. If an [EditorNode3DGizmo] is provided, it will try to get the corresponding variant (selected and/or editable). </description> </method> - <method name="get_name" qualifiers="virtual"> - <return type="String"> - </return> - <description> - Override this method to provide the name that will appear in the gizmo visibility menu. - </description> - </method> <method name="get_priority" qualifiers="virtual"> <return type="int"> </return> diff --git a/doc/classes/GLTFState.xml b/doc/classes/GLTFState.xml index a8e96ec8a9..8255cd73d0 100644 --- a/doc/classes/GLTFState.xml +++ b/doc/classes/GLTFState.xml @@ -109,6 +109,12 @@ <description> </description> </method> + <method name="get_unique_animation_names"> + <return type="Array"> + </return> + <description> + </description> + </method> <method name="get_unique_names"> <return type="Array"> </return> @@ -219,6 +225,14 @@ <description> </description> </method> + <method name="set_unique_animation_names"> + <return type="void"> + </return> + <argument index="0" name="unique_animation_names" type="Array"> + </argument> + <description> + </description> + </method> <method name="set_unique_names"> <return type="void"> </return> diff --git a/doc/classes/GLTFTexture.xml b/doc/classes/GLTFTexture.xml index c7f94ab0da..be2210331f 100644 --- a/doc/classes/GLTFTexture.xml +++ b/doc/classes/GLTFTexture.xml @@ -9,7 +9,7 @@ <methods> </methods> <members> - <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="4"> + <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="195773152"> </member> </members> <constants> diff --git a/doc/classes/Navigation2D.xml b/doc/classes/Navigation2D.xml deleted file mode 100644 index abac29bdb7..0000000000 --- a/doc/classes/Navigation2D.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="Navigation2D" inherits="Node2D" version="4.0"> - <brief_description> - 2D navigation and pathfinding node. - </brief_description> - <description> - Navigation2D provides navigation and pathfinding within a 2D area, specified as a collection of [NavigationPolygon] resources. These are automatically collected from child [NavigationRegion2D] nodes. - </description> - <tutorials> - <link title="2D Navigation Demo">https://godotengine.org/asset-library/asset/117</link> - </tutorials> - <methods> - <method name="get_closest_point" qualifiers="const"> - <return type="Vector2"> - </return> - <argument index="0" name="to_point" type="Vector2"> - </argument> - <description> - Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface. - </description> - </method> - <method name="get_closest_point_owner" qualifiers="const"> - <return type="RID"> - </return> - <argument index="0" name="to_point" type="Vector2"> - </argument> - <description> - Returns the owner region RID for the point returned by [method get_closest_point]. - </description> - </method> - <method name="get_rid" qualifiers="const"> - <return type="RID"> - </return> - <description> - </description> - </method> - <method name="get_simple_path" qualifiers="const"> - <return type="PackedVector2Array"> - </return> - <argument index="0" name="start" type="Vector2"> - </argument> - <argument index="1" name="end" type="Vector2"> - </argument> - <argument index="2" name="optimize" type="bool" default="true"> - </argument> - <description> - Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the path is smoothed by merging path segments where possible. - </description> - </method> - </methods> - <members> - <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="10.0"> - </member> - <member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="100.0"> - </member> - </members> - <constants> - </constants> -</class> diff --git a/doc/classes/Navigation3D.xml b/doc/classes/Navigation3D.xml deleted file mode 100644 index e7a4fe3c43..0000000000 --- a/doc/classes/Navigation3D.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="Navigation3D" inherits="Node3D" version="4.0"> - <brief_description> - Mesh-based navigation and pathfinding node. - </brief_description> - <description> - Provides navigation and pathfinding within a collection of [NavigationMesh]es. These will be automatically collected from child [NavigationRegion3D] nodes. In addition to basic pathfinding, this class also assists with aligning navigation agents with the meshes they are navigating on. - </description> - <tutorials> - <link title="3D Navmesh Demo">https://godotengine.org/asset-library/asset/124</link> - </tutorials> - <methods> - <method name="get_closest_point" qualifiers="const"> - <return type="Vector3"> - </return> - <argument index="0" name="to_point" type="Vector3"> - </argument> - <description> - Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface. - </description> - </method> - <method name="get_closest_point_normal" qualifiers="const"> - <return type="Vector3"> - </return> - <argument index="0" name="to_point" type="Vector3"> - </argument> - <description> - Returns the normal for the point returned by [method get_closest_point]. - </description> - </method> - <method name="get_closest_point_owner" qualifiers="const"> - <return type="RID"> - </return> - <argument index="0" name="to_point" type="Vector3"> - </argument> - <description> - Returns the owner region RID for the point returned by [method get_closest_point]. - </description> - </method> - <method name="get_closest_point_to_segment" qualifiers="const"> - <return type="Vector3"> - </return> - <argument index="0" name="start" type="Vector3"> - </argument> - <argument index="1" name="end" type="Vector3"> - </argument> - <argument index="2" name="use_collision" type="bool" default="false"> - </argument> - <description> - Returns the closest point between the navigation surface and the segment. - </description> - </method> - <method name="get_rid" qualifiers="const"> - <return type="RID"> - </return> - <description> - </description> - </method> - <method name="get_simple_path" qualifiers="const"> - <return type="PackedVector3Array"> - </return> - <argument index="0" name="start" type="Vector3"> - </argument> - <argument index="1" name="end" type="Vector3"> - </argument> - <argument index="2" name="optimize" type="bool" default="true"> - </argument> - <description> - Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (radius, height, etc.) are considered in the path calculation, otherwise they are ignored. - </description> - </method> - </methods> - <members> - <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="0.3"> - </member> - <member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="5.0"> - </member> - <member name="up_vector" type="Vector3" setter="set_up_vector" getter="get_up_vector" default="Vector3( 0, 1, 0 )"> - Defines which direction is up. By default, this is [code](0, 1, 0)[/code], which is the world's "up" direction. - </member> - </members> - <constants> - </constants> -</class> diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 5a9c31ef67..59bf06eaf2 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -4,7 +4,7 @@ 2D Agent used in navigation for collision avoidance. </brief_description> <description> - 2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationAgent2D] is physics safe. + 2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent2D] is physics safe. </description> <tutorials> </tutorials> @@ -37,13 +37,6 @@ Returns which index the agent is currently on in the navigation path's [PackedVector2Array]. </description> </method> - <method name="get_navigation" qualifiers="const"> - <return type="Node"> - </return> - <description> - Returns the [Navigation2D] node that the agent is using for its navigation system. - </description> - </method> <method name="get_next_location"> <return type="Vector2"> </return> @@ -79,15 +72,6 @@ Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location]. </description> </method> - <method name="set_navigation"> - <return type="void"> - </return> - <argument index="0" name="navigation" type="Node"> - </argument> - <description> - Sets the [Navigation2D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation2D] node. - </description> - </method> <method name="set_target_location"> <return type="void"> </return> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index f9df1d390b..7a130e9591 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -4,7 +4,7 @@ 3D Agent used in navigation for collision avoidance. </brief_description> <description> - 3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationAgent3D] is physics safe. + 3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent3D] is physics safe. </description> <tutorials> </tutorials> @@ -37,13 +37,6 @@ Returns which index the agent is currently on in the navigation path's [PackedVector3Array]. </description> </method> - <method name="get_navigation" qualifiers="const"> - <return type="Node"> - </return> - <description> - Returns the [Navigation3D] node that the agent is using for its navigation system. - </description> - </method> <method name="get_next_location"> <return type="Vector3"> </return> @@ -79,15 +72,6 @@ Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location]. </description> </method> - <method name="set_navigation"> - <return type="void"> - </return> - <argument index="0" name="navigation" type="Node"> - </argument> - <description> - Sets the [Navigation3D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation3D] node. - </description> - </method> <method name="set_target_location"> <return type="void"> </return> diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml index ddd96975f1..2e94eb0bba 100644 --- a/doc/classes/NavigationObstacle2D.xml +++ b/doc/classes/NavigationObstacle2D.xml @@ -4,27 +4,11 @@ 2D Obstacle used in navigation for collision avoidance. </brief_description> <description> - 2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationObstacle2D] is physics safe. + 2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle2D] is physics safe. </description> <tutorials> </tutorials> <methods> - <method name="get_navigation" qualifiers="const"> - <return type="Node"> - </return> - <description> - Returns the [Navigation2D] node that the obstacle is using for its navigation system. - </description> - </method> - <method name="set_navigation"> - <return type="void"> - </return> - <argument index="0" name="navigation" type="Node"> - </argument> - <description> - Sets the [Navigation2D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation2D] node. - </description> - </method> </methods> <constants> </constants> diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml index e01a40ed73..d7454a7bea 100644 --- a/doc/classes/NavigationObstacle3D.xml +++ b/doc/classes/NavigationObstacle3D.xml @@ -4,27 +4,11 @@ 3D Obstacle used in navigation for collision avoidance. </brief_description> <description> - 3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationObstacle3D] is physics safe. + 3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle3D] is physics safe. </description> <tutorials> </tutorials> <methods> - <method name="get_navigation" qualifiers="const"> - <return type="Node"> - </return> - <description> - Returns the [Navigation3D] node that the obstacle is using for its navigation system. - </description> - </method> - <method name="set_navigation"> - <return type="void"> - </return> - <argument index="0" name="navigation" type="Node"> - </argument> - <description> - Sets the [Navigation3D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation3D] node. - </description> - </method> </methods> <constants> </constants> diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml index aef114e1db..33a3f04c3d 100644 --- a/doc/classes/NavigationRegion2D.xml +++ b/doc/classes/NavigationRegion2D.xml @@ -1,8 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="NavigationRegion2D" inherits="Node2D" version="4.0"> <brief_description> + A region of the 2D navigation map. </brief_description> <description> + A region of the navigation map. It tells the [NavigationServer2D] what can be navigated and what cannot, based on its [NavigationPolygon] resource. + Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer2D.map_set_edge_connection_margin]. + [b]Note:[/b] Overlapping two regions' polygons is not enough for connecting two regions. They must share a similar edge. </description> <tutorials> </tutorials> @@ -10,8 +14,13 @@ </methods> <members> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> + Determines if the [NavigationRegion2D] is enabled or disabled. + </member> + <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1"> + A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. </member> <member name="navpoly" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon"> + The [NavigationPolygon] resource to use. </member> </members> <constants> diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml index b70bfb6596..2904ba4200 100644 --- a/doc/classes/NavigationRegion3D.xml +++ b/doc/classes/NavigationRegion3D.xml @@ -4,7 +4,8 @@ A region of the navigation map. </brief_description> <description> - A region of the navigation map. It tells the [Navigation3D] node what can be navigated and what cannot, based on the [NavigationMesh] resource. This should be a child of a [Navigation3D] node (even not a direct child). + A region of the navigation map. It tells the [NavigationServer3D] what can be navigated and what cannot, based on its [NavigationMesh] resource. + Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer3D.map_set_edge_connection_margin]. </description> <tutorials> </tutorials> @@ -21,6 +22,9 @@ <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> Determines if the [NavigationRegion3D] is enabled or disabled. </member> + <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1"> + A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. + </member> <member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh"> The [NavigationMesh] resource to use. </member> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 5f0b04487e..4f34a8a424 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -4,7 +4,12 @@ Server interface for low-level 2D navigation access </brief_description> <description> - NavigationServer2D is the server responsible for all 2D navigation. It creates the agents, maps, and regions for navigation to work as expected. This keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. + NavigationServer2D is the server responsible for all 2D navigation. It handles several objects, namely maps, regions and agents. + Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects. + To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. + [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. + This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. </description> <tutorials> <link title="2D Navigation Demo">https://godotengine.org/asset-library/asset/117</link> @@ -207,8 +212,10 @@ </argument> <argument index="3" name="optimize" type="bool"> </argument> + <argument index="4" name="layers" type="int" default="1"> + </argument> <description> - Returns the navigation path to reach the destination from the origin, while avoiding static obstacles. + Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. </description> </method> <method name="map_is_active" qualifiers="const"> @@ -260,6 +267,26 @@ Creates a new region. </description> </method> + <method name="region_get_layers" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="region" type="RID"> + </argument> + <description> + Returns the region's layers. + </description> + </method> + <method name="region_set_layers" qualifiers="const"> + <return type="void"> + </return> + <argument index="0" name="region" type="RID"> + </argument> + <argument index="1" name="layers" type="int"> + </argument> + <description> + Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]). + </description> + </method> <method name="region_set_map" qualifiers="const"> <return type="void"> </return> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 95890c4b4c..0653c0d27d 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -4,7 +4,12 @@ Server interface for low-level 3D navigation access </brief_description> <description> - NavigationServer3D is the server responsible for all 3D navigation. It creates the agents, maps, and regions for navigation to work as expected. This keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. + NavigationServer3D is the server responsible for all 3D navigation. It handles several objects, namely maps, regions and agents. + Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects. + To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. + [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. + This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying. </description> <tutorials> <link title="3D Navmesh Demo">https://godotengine.org/asset-library/asset/124</link> @@ -219,7 +224,7 @@ <argument index="0" name="map" type="RID"> </argument> <description> - Returns the edge connection margin of the map. + Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions. </description> </method> <method name="map_get_path" qualifiers="const"> @@ -233,8 +238,10 @@ </argument> <argument index="3" name="optimize" type="bool"> </argument> + <argument index="4" name="layers" type="int" default="1"> + </argument> <description> - Returns the navigation path to reach the destination from the origin. + Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. </description> </method> <method name="map_get_up" qualifiers="const"> @@ -285,7 +292,7 @@ <argument index="1" name="margin" type="float"> </argument> <description> - Set the map edge connection margein used to weld the compatible region edges. + Set the map edge connection margin used to weld the compatible region edges. </description> </method> <method name="map_set_up" qualifiers="const"> @@ -328,6 +335,26 @@ Creates a new region. </description> </method> + <method name="region_get_layers" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="region" type="RID"> + </argument> + <description> + Returns the region's layers. + </description> + </method> + <method name="region_set_layers" qualifiers="const"> + <return type="void"> + </return> + <argument index="0" name="region" type="RID"> + </argument> + <argument index="1" name="layers" type="int"> + </argument> + <description> + Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]). + </description> + </method> <method name="region_set_map" qualifiers="const"> <return type="void"> </return> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 057a2b8d1a..548147beab 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -367,6 +367,7 @@ <description> Gets an epoch time value from a dictionary of time values. [code]datetime[/code] must be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], [code]second[/code]. + If the dictionary is empty [code]0[/code] is returned. You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight Savings Time ([code]dst[/code]), if present, is ignored. </description> </method> diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 1fa82adb7a..701a430538 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -58,7 +58,7 @@ <return type="RID"> </return> <description> - Creates an [Area2D]. + Creates an [Area2D]. After creating an [Area2D] with this method, assign it to a space using [method area_set_space] to use the created [Area2D] in the physics world. </description> </method> <method name="area_get_canvas_instance_id" qualifiers="const"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 03a88fd86c..ac63c5da79 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -469,7 +469,7 @@ <member name="debug/shapes/collision/max_contacts_displayed" type="int" setter="" getter="" default="10000"> Maximum number of contact points between collision shapes to display when "Visible Collision Shapes" is enabled in the Debug menu. </member> - <member name="debug/shapes/collision/shape_color" type="Color" setter="" getter="" default="Color( 0, 0.6, 0.7, 0.5 )"> + <member name="debug/shapes/collision/shape_color" type="Color" setter="" getter="" default="Color( 0, 0.6, 0.7, 0.42 )"> Color of the collision shapes, visible when "Visible Collision Shapes" is enabled in the Debug menu. </member> <member name="debug/shapes/navigation/disabled_geometry_color" type="Color" setter="" getter="" default="Color( 1, 0.7, 0.1, 0.4 )"> @@ -488,7 +488,7 @@ Position offset for tooltips, relative to the mouse cursor's hotspot. </member> <member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="" default="false"> - If [code]true[/code], allows HiDPI display on Windows and macOS. This setting has no effect on desktop Linux, as DPI-awareness fallbacks are not supported there. + If [code]true[/code], allows HiDPI display on Windows, macOS, and the HTML5 platform. This setting has no effect on desktop Linux, as DPI-awareness fallbacks are not supported there. </member> <member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true"> If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms. @@ -758,6 +758,66 @@ <member name="internationalization/rendering/text_driver" type="String" setter="" getter="" default=""""> Specifies the [TextServer] to use. If left empty, the default will be used. </member> + <member name="layer_names/2d_navigation/layer_0" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 0. If left empty, the layer will display as "Layer 0". + </member> + <member name="layer_names/2d_navigation/layer_1" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 1. If left empty, the layer will display as "Layer 1". + </member> + <member name="layer_names/2d_navigation/layer_10" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 10. If left empty, the layer will display as "Layer 10". + </member> + <member name="layer_names/2d_navigation/layer_11" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 11. If left empty, the layer will display as "Layer 11". + </member> + <member name="layer_names/2d_navigation/layer_12" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 12. If left empty, the layer will display as "Layer 12". + </member> + <member name="layer_names/2d_navigation/layer_13" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 13. If left empty, the layer will display as "Layer 13". + </member> + <member name="layer_names/2d_navigation/layer_14" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 14. If left empty, the layer will display as "Layer 14". + </member> + <member name="layer_names/2d_navigation/layer_15" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 15. If left empty, the layer will display as "Layer 15". + </member> + <member name="layer_names/2d_navigation/layer_16" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 16. If left empty, the layer will display as "Layer 16". + </member> + <member name="layer_names/2d_navigation/layer_17" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 17. If left empty, the layer will display as "Layer 17". + </member> + <member name="layer_names/2d_navigation/layer_18" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 18. If left empty, the layer will display as "Layer 18". + </member> + <member name="layer_names/2d_navigation/layer_19" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 19. If left empty, the layer will display as "Layer 19". + </member> + <member name="layer_names/2d_navigation/layer_2" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 2. If left empty, the layer will display as "Layer 2". + </member> + <member name="layer_names/2d_navigation/layer_3" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 3. If left empty, the layer will display as "Layer 3". + </member> + <member name="layer_names/2d_navigation/layer_4" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 4. If left empty, the layer will display as "Layer 4". + </member> + <member name="layer_names/2d_navigation/layer_5" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 5. If left empty, the layer will display as "Layer 5". + </member> + <member name="layer_names/2d_navigation/layer_6" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 6. If left empty, the layer will display as "Layer 6". + </member> + <member name="layer_names/2d_navigation/layer_7" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 7. If left empty, the layer will display as "Layer 7". + </member> + <member name="layer_names/2d_navigation/layer_8" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 8. If left empty, the layer will display as "Layer 8". + </member> + <member name="layer_names/2d_navigation/layer_9" type="String" setter="" getter="" default=""""> + Optional name for the 2D navigation layer 9. If left empty, the layer will display as "Layer 9". + </member> <member name="layer_names/2d_physics/layer_0" type="String" setter="" getter="" default=""""> Optional name for the 2D physics layer 0. If left empty, the layer will display as "Layer 0". </member> @@ -878,6 +938,66 @@ <member name="layer_names/2d_render/layer_9" type="String" setter="" getter="" default=""""> Optional name for the 2D render layer 9. If left empty, the layer will display as "Layer 9". </member> + <member name="layer_names/3d_navigation/layer_0" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 0. If left empty, the layer will display as "Layer 0". + </member> + <member name="layer_names/3d_navigation/layer_1" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 1. If left empty, the layer will display as "Layer 1". + </member> + <member name="layer_names/3d_navigation/layer_10" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 10. If left empty, the layer will display as "Layer 10". + </member> + <member name="layer_names/3d_navigation/layer_11" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 11. If left empty, the layer will display as "Layer 11". + </member> + <member name="layer_names/3d_navigation/layer_12" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 12. If left empty, the layer will display as "Layer 12". + </member> + <member name="layer_names/3d_navigation/layer_13" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 13. If left empty, the layer will display as "Layer 13". + </member> + <member name="layer_names/3d_navigation/layer_14" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 14. If left empty, the layer will display as "Layer 14". + </member> + <member name="layer_names/3d_navigation/layer_15" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 15. If left empty, the layer will display as "Layer 15". + </member> + <member name="layer_names/3d_navigation/layer_16" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 16. If left empty, the layer will display as "Layer 16". + </member> + <member name="layer_names/3d_navigation/layer_17" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 17. If left empty, the layer will display as "Layer 17". + </member> + <member name="layer_names/3d_navigation/layer_18" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 18. If left empty, the layer will display as "Layer 18". + </member> + <member name="layer_names/3d_navigation/layer_19" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 19. If left empty, the layer will display as "Layer 19". + </member> + <member name="layer_names/3d_navigation/layer_2" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 2. If left empty, the layer will display as "Layer 2". + </member> + <member name="layer_names/3d_navigation/layer_3" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 3. If left empty, the layer will display as "Layer 3". + </member> + <member name="layer_names/3d_navigation/layer_4" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 4. If left empty, the layer will display as "Layer 4". + </member> + <member name="layer_names/3d_navigation/layer_5" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 5. If left empty, the layer will display as "Layer 5". + </member> + <member name="layer_names/3d_navigation/layer_6" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 6. If left empty, the layer will display as "Layer 6". + </member> + <member name="layer_names/3d_navigation/layer_7" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 7. If left empty, the layer will display as "Layer 7". + </member> + <member name="layer_names/3d_navigation/layer_8" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 8. If left empty, the layer will display as "Layer 8". + </member> + <member name="layer_names/3d_navigation/layer_9" type="String" setter="" getter="" default=""""> + Optional name for the 3D navigation layer 9. If left empty, the layer will display as "Layer 9". + </member> <member name="layer_names/3d_physics/layer_0" type="String" setter="" getter="" default=""""> Optional name for the 3D physics layer 0. If left empty, the layer will display as "Layer 0". </member> @@ -1020,6 +1140,18 @@ </member> <member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0"> </member> + <member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10"> + Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size]. + </member> + <member name="navigation/2d/default_edge_connection_margin" type="int" setter="" getter="" default="100"> + Default edge connection margin for 2D navigation maps. See [method NavigationServer2D.map_set_edge_connection_margin]. + </member> + <member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.3"> + Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size]. + </member> + <member name="navigation/3d/default_edge_connection_margin" type="float" setter="" getter="" default="5.0"> + Default edge connection margin for 3D navigation maps. See [method NavigationServer3D.map_set_edge_connection_margin]. + </member> <member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768"> Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection. </member> diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml index 681cfcd4ce..443890438f 100644 --- a/doc/classes/RayCast3D.xml +++ b/doc/classes/RayCast3D.xml @@ -136,11 +136,11 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> - <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape__custom_color" getter="get_debug_shape_custom_color" default="Color( 0.0, 0.0, 0.0 )"> + <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color( 0, 0, 0, 1 )"> The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast3D] is colliding with something. If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used. </member> - <member name="debug_shape_thickness" type="int" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="1"> + <member name="debug_shape_thickness" type="float" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2.0"> If set to [code]1[/code], a line is used as the debug shape. Otherwise, a truncated pyramid is drawn to represent the [RayCast3D]. Requires [b]Visible Collision Shapes[/b] to be enabled in the [b]Debug[/b] menu for the debug shape to be visible at run-time. </member> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 72a42202c7..e1f6830eb2 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -88,6 +88,14 @@ The timer will be automatically freed after its time elapses. </description> </method> + <method name="get_first_node_in_group"> + <return type="Node"> + </return> + <argument index="0" name="group" type="StringName"> + </argument> + <description> + </description> + </method> <method name="get_frame" qualifiers="const"> <return type="int"> </return> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index a90bcd9eb7..475b17d395 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -909,6 +909,13 @@ [/codeblocks] </description> </method> + <method name="validate_node_name"> + <return type="String"> + </return> + <description> + Removes any characters from the string that are prohibited in [Node] names ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code]). + </description> + </method> <method name="xml_escape"> <return type="String"> </return> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 6232a4e146..088bcd1c3c 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -412,7 +412,7 @@ [/gdscript] [csharp] int[] result = Search("print", (uint)TextEdit.SearchFlags.WholeWords, 0, 0); - if (result.Length > 0) + if (result.Length > 0) { // Result found. int lineNumber = result[(int)TextEdit.SearchResult.Line]; diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index c0ee004ca6..7ed8ad6d4a 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -272,6 +272,9 @@ </method> </methods> <members> + <member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false"> + If [code]true[/code], this TileMap bakes a navigation region. + </member> <member name="cell_clip_uv" type="bool" setter="set_clip_uv" getter="get_clip_uv" default="false"> If [code]true[/code], the cell's UVs will be clipped. </member> diff --git a/doc/classes/World2D.xml b/doc/classes/World2D.xml index 25033cdb09..20b3afbd0b 100644 --- a/doc/classes/World2D.xml +++ b/doc/classes/World2D.xml @@ -18,6 +18,9 @@ <member name="direct_space_state" type="PhysicsDirectSpaceState2D" setter="" getter="get_direct_space_state"> Direct access to the world's physics 2D space state. Used for querying current and potential collisions. When using multi-threaded physics, access is limited to [code]_physics_process(delta)[/code] in the main thread. </member> + <member name="navigation_map" type="RID" setter="" getter="get_navigation_map"> + The [RID] of this world's navigation map. Used by the [NavigationServer2D]. + </member> <member name="space" type="RID" setter="" getter="get_space"> The [RID] of this world's physics space resource. Used by the [PhysicsServer2D] for 2D physics, treating it as both a space and an area. </member> diff --git a/doc/classes/World3D.xml b/doc/classes/World3D.xml index fe92077432..610ecacff4 100644 --- a/doc/classes/World3D.xml +++ b/doc/classes/World3D.xml @@ -23,6 +23,9 @@ <member name="fallback_environment" type="Environment" setter="set_fallback_environment" getter="get_fallback_environment"> The World3D's fallback_environment will be used if the World3D's [Environment] fails or is missing. </member> + <member name="navigation_map" type="RID" setter="" getter="get_navigation_map"> + The [RID] of this world's navigation map. Used by the [NavigationServer3D]. + </member> <member name="scenario" type="RID" setter="" getter="get_scenario"> The World3D's visual scenario. </member> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index baa60f5526..f40036d628 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -506,7 +506,8 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) { UInt32 size = 0; AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, nullptr, &size); - AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size); + AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size); + ERR_FAIL_NULL_V_MSG(audioDevices, list, "Out of memory."); AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, nullptr, &size, audioDevices); UInt32 deviceCount = size / sizeof(AudioDeviceID); @@ -515,14 +516,15 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) { prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); - AudioBufferList *bufferList = (AudioBufferList *)malloc(size); + AudioBufferList *bufferList = (AudioBufferList *)memalloc(size); + ERR_FAIL_NULL_V_MSG(bufferList, list, "Out of memory."); AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList); UInt32 channelCount = 0; for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++) channelCount += bufferList->mBuffers[j].mNumberChannels; - free(bufferList); + memfree(bufferList); if (channelCount >= 1) { CFStringRef cfname; @@ -534,17 +536,18 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) { CFIndex length = CFStringGetLength(cfname); CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; - char *buffer = (char *)malloc(maxSize); + char *buffer = (char *)memalloc(maxSize); + ERR_FAIL_NULL_V_MSG(buffer, list, "Out of memory."); if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) { // Append the ID to the name in case we have devices with duplicate name list.push_back(String(buffer) + " (" + itos(audioDevices[i]) + ")"); } - free(buffer); + memfree(buffer); } } - free(audioDevices); + memfree(audioDevices); return list; } @@ -561,7 +564,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { UInt32 size = 0; AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, nullptr, &size); - AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size); + AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size); + ERR_FAIL_NULL_MSG(audioDevices, "Out of memory."); AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, nullptr, &size, audioDevices); UInt32 deviceCount = size / sizeof(AudioDeviceID); @@ -570,14 +574,15 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); - AudioBufferList *bufferList = (AudioBufferList *)malloc(size); + AudioBufferList *bufferList = (AudioBufferList *)memalloc(size); + ERR_FAIL_NULL_MSG(bufferList, "Out of memory."); AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList); UInt32 channelCount = 0; for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++) channelCount += bufferList->mBuffers[j].mNumberChannels; - free(bufferList); + memfree(bufferList); if (channelCount >= 1) { CFStringRef cfname; @@ -589,7 +594,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { CFIndex length = CFStringGetLength(cfname); CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; - char *buffer = (char *)malloc(maxSize); + char *buffer = (char *)memalloc(maxSize); + ERR_FAIL_NULL_MSG(buffer, "Out of memory."); if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) { String name = String(buffer) + " (" + itos(audioDevices[i]) + ")"; if (name == device) { @@ -598,11 +604,11 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } } - free(buffer); + memfree(buffer); } } - free(audioDevices); + memfree(audioDevices); } if (!found) { diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 9584dd3f67..469d80368d 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -119,7 +119,7 @@ static void update_external_dependency_for_store(VkSubpassDependency &dependency } if (is_depth) { - // Depth resources have addtional stages that may be interested in them + // Depth resources have additional stages that may be interested in them dependency.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; dependency.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; } @@ -3108,7 +3108,7 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, VkImageLayout clear_layout = (src_tex->layout == VK_IMAGE_LAYOUT_GENERAL) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - // NOTE: Perhaps the valid stages/accesses for a given onwner should be a property of the owner. (Here and places like _get_buffer_from_owner) + // NOTE: Perhaps the valid stages/accesses for a given owner should be a property of the owner. (Here and places like _get_buffer_from_owner) const VkPipelineStageFlags valid_texture_stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; constexpr VkAccessFlags read_access = VK_ACCESS_SHADER_READ_BIT; constexpr VkAccessFlags read_write_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; @@ -3250,7 +3250,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF Vector<VkAttachmentReference> depth_stencil_references; Vector<VkAttachmentReference> resolve_references; - // Set up a dependencies from/to external equivalent to the default (implicit) one, and then amend them + // Set up dependencies from/to external equivalent to the default (implicit) one, and then amend them const VkPipelineStageFlags default_access_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | @@ -3279,7 +3279,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF bool is_storage = p_format[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT; // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write - // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution syncronization vs. + // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs. // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that // stage switch (is_depth_stencil ? p_initial_depth_action : p_initial_color_action) { @@ -3424,12 +3424,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF // NOTE: Big Mallet Approach -- any layout transition causes a full barrier if (reference.layout != description.initialLayout) { - // NOTE: this should be smarter based on the textures knowledge of it's previous role + // NOTE: this should be smarter based on the texture's knowledge of its previous role dependency_from_external.srcStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; dependency_from_external.srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; } if (reference.layout != description.finalLayout) { - // NOTE: this should be smarter based on the textures knowledge of it's subsequent role + // NOTE: this should be smarter based on the texture's knowledge of its subsequent role dependency_to_external.dstStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; dependency_to_external.dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; } @@ -5151,7 +5151,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid."); - //if 0, then its sized on link time + //if 0, then it's sized on link time ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ")."); @@ -5336,7 +5336,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) { ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving."); } - // Make sure no one is using the buffer -- the "false" gets us to the same command buffer as below. + // Make sure no one is using the buffer -- the "false" gets us to the same command buffer as below. _buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, src_access_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, false); VkCommandBuffer command_buffer = frames[frame].setup_command_buffer; @@ -5729,7 +5729,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma #endif //create ID to associate with this pipeline RID id = render_pipeline_owner.make_rid(pipeline); - //now add aall the dependencies + //now add all the dependencies _add_dependency(id, p_shader); return id; } @@ -5780,7 +5780,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) { //create ID to associate with this pipeline RID id = compute_pipeline_owner.make_rid(pipeline); - //now add aall the dependencies + //now add all the dependencies _add_dependency(id, p_shader); return id; } @@ -6817,7 +6817,7 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) { // To ensure proper synchronization, we must make sure rendering is done before: // * Some buffer is copied - // * Another render pass happens (since we may be done + // * Another render pass happens (since we may be done) #ifdef FORCE_FULL_BARRIER _full_barrier(true); @@ -7780,7 +7780,7 @@ uint64_t RenderingDeviceVulkan::get_memory_usage() const { void RenderingDeviceVulkan::_flush(bool p_current_frame) { if (local_device.is_valid() && !p_current_frame) { - return; //flushign previous frames has no effect with local device + return; //flushing previous frames has no effect with local device } //not doing this crashes RADV (undefined behavior) if (p_current_frame) { diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index ad740efec4..69517b17ba 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -1313,13 +1313,13 @@ Error VulkanContext::swap_buffers() { DemoUpdateTargetIPD(demo); // Note: a real application would position its geometry to that it's in - // the correct locatoin for when the next image is presented. It might + // the correct location for when the next image is presented. It might // also wait, so that there's less latency between any input and when // the next image is rendered/presented. This demo program is so // simple that it doesn't do either of those. } #endif - // Wait for the image acquired semaphore to be signaled to ensure + // Wait for the image acquired semaphore to be signalled to ensure // that the image won't be rendered to until the presentation // engine has fully released ownership to the application, and it is // okay to render to the image. @@ -1385,7 +1385,7 @@ Error VulkanContext::swap_buffers() { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); } - // If we are using separate queues we have to wait for image ownership, + // If we are using separate queues, we have to wait for image ownership, // otherwise wait for draw complete VkPresentInfoKHR present = { /*sType*/ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 4f60258d95..7f5f51cf70 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -301,6 +301,8 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags) } Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { + ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); + PackData *pd = (PackData *)p_userdata; SavedData sd; @@ -368,6 +370,8 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa } Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { + ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); + String path = p_path.replace_first("res://", ""); ZipData *zd = (ZipData *)p_userdata; @@ -824,17 +828,25 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } + Error err = OK; Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { export_plugins.write[i]->set_export_preset(p_preset); if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { - p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + if (err != OK) { + return err; + } } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } export_plugins.write[i]->_clear(); @@ -856,7 +868,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & //file is imported, replace by what it imports Ref<ConfigFile> config; config.instance(); - Error err = config->load(path + ".import"); + err = config->load(path + ".import"); if (err != OK) { ERR_PRINT("Could not parse: '" + path + "', not exported."); continue; @@ -920,12 +932,18 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { - p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + if (err != OK) { + return err; + } } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } if (export_plugins[i]->extra_files[j].remap) { do_export = false; //if remap, do not path_remaps.push_back(path); @@ -945,7 +963,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & //just store it as it comes if (do_export) { Vector<uint8_t> array = FileAccess::get_file_as_array(path); - p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } } @@ -981,7 +1002,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & new_file.write[j] = utf8[j]; } - p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } } else { //old remap mode, will still work, but it's unused because it's not multiple pck export friendly @@ -994,11 +1018,17 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & String splash = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (icon != String() && FileAccess::exists(icon)) { Vector<uint8_t> array = FileAccess::get_file_as_array(icon); - p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } if (splash != String() && FileAccess::exists(splash) && icon != splash) { Vector<uint8_t> array = FileAccess::get_file_as_array(splash); - p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } // Store text server data if exists. @@ -1006,7 +1036,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & String ts_data = "res://" + TS->get_support_data_filename(); if (FileAccess::exists(ts_data)) { Vector<uint8_t> array = FileAccess::get_file_as_array(ts_data); - p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } } } @@ -1016,9 +1049,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb); DirAccess::remove_file_or_error(engine_cfb); - p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key); - - return OK; + return p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key); } Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) { @@ -1052,6 +1083,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c if (err != OK) { DirAccess::remove_file_or_error(tmppath); + ERR_PRINT("Failed to export project files"); return err; } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 6d694358bf..f78da9569f 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1076,9 +1076,9 @@ EditorFileDialog::Access EditorFileDialog::get_access() const { } void EditorFileDialog::_make_dir_confirm() { - Error err = dir_access->make_dir(makedirname->get_text()); + Error err = dir_access->make_dir(makedirname->get_text().strip_edges()); if (err == OK) { - dir_access->change_dir(makedirname->get_text()); + dir_access->change_dir(makedirname->get_text().strip_edges()); invalidate(); update_filters(); update_dir(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f0e53e7ef5..4c23ada5e9 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2387,11 +2387,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { _scene_tab_changed(tab_closing); if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { - String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename(); - save_confirmation->get_ok_button()->set_text(TTR("Save & Close")); - save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); - save_confirmation->popup_centered(); - break; + Node *scene_root = editor_data.get_edited_scene_root(tab_closing); + if (scene_root) { + String scene_filename = scene_root->get_filename(); + save_confirmation->get_ok_button()->set_text(TTR("Save & Close")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); + save_confirmation->popup_centered(); + break; + } } } else if (p_option == FILE_CLOSE) { tab_closing = editor_data.get_edited_scene(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 6bfc16ccd7..2d7235038a 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -716,12 +716,18 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) { case LAYER_PHYSICS_2D: basename = "layer_names/2d_physics"; break; + case LAYER_NAVIGATION_2D: + basename = "layer_names/2d_navigation"; + break; case LAYER_RENDER_3D: basename = "layer_names/3d_render"; break; case LAYER_PHYSICS_3D: basename = "layer_names/3d_physics"; break; + case LAYER_NAVIGATION_3D: + basename = "layer_names/3d_navigation"; + break; } Vector<String> names; @@ -2909,7 +2915,7 @@ void EditorPropertyResource::update_property() { sub_inspector->set_use_doc_hints(true); sub_inspector->set_sub_inspector(true); - sub_inspector->set_enable_capitalize_paths(true); + sub_inspector->set_enable_capitalize_paths(bool(EDITOR_GET("interface/inspector/capitalize_properties"))); sub_inspector->connect("property_keyed", callable_mp(this, &EditorPropertyResource::_sub_inspector_property_keyed)); sub_inspector->connect("resource_selected", callable_mp(this, &EditorPropertyResource::_sub_inspector_resource_selected)); @@ -3300,7 +3306,12 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ editor->setup(options); add_property_editor(p_path, editor); - } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || + p_hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + p_hint == PROPERTY_HINT_LAYERS_3D_RENDER || + p_hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { EditorPropertyLayers::LayerType lt = EditorPropertyLayers::LAYER_RENDER_2D; switch (p_hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: @@ -3309,12 +3320,18 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ case PROPERTY_HINT_LAYERS_2D_PHYSICS: lt = EditorPropertyLayers::LAYER_PHYSICS_2D; break; + case PROPERTY_HINT_LAYERS_2D_NAVIGATION: + lt = EditorPropertyLayers::LAYER_NAVIGATION_2D; + break; case PROPERTY_HINT_LAYERS_3D_RENDER: lt = EditorPropertyLayers::LAYER_RENDER_3D; break; case PROPERTY_HINT_LAYERS_3D_PHYSICS: lt = EditorPropertyLayers::LAYER_PHYSICS_3D; break; + case PROPERTY_HINT_LAYERS_3D_NAVIGATION: + lt = EditorPropertyLayers::LAYER_NAVIGATION_3D; + break; default: { } //compiler could be smarter here and realize this can't happen } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 6f097fb5df..07a1e72319 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -239,8 +239,10 @@ public: enum LayerType { LAYER_PHYSICS_2D, LAYER_RENDER_2D, + LAYER_NAVIGATION_2D, LAYER_PHYSICS_3D, LAYER_RENDER_3D, + LAYER_NAVIGATION_3D, }; private: diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 3d40c145f2..030d36ff78 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -852,7 +852,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxFlat> style_tree_cursor = style_default->duplicate(); style_tree_cursor->set_draw_center(false); - style_tree_cursor->set_border_width_all(border_width); + style_tree_cursor->set_border_width_all(MAX(1, border_width)); style_tree_cursor->set_border_color(contrast_color_1); Ref<StyleBoxFlat> style_tree_title = style_default->duplicate(); @@ -1283,6 +1283,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("add_preset", "ColorPicker", theme->get_icon("Add", "EditorIcons")); theme->set_icon("preset_bg", "ColorPicker", theme->get_icon("GuiMiniCheckerboard", "EditorIcons")); theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon("OverbrightIndicator", "EditorIcons")); + theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon("ColorPickerBarArrow", "EditorIcons")); theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons")); diff --git a/editor/icons/ColorPickerBarArrow.svg b/editor/icons/ColorPickerBarArrow.svg new file mode 100644 index 0000000000..9d034106ee --- /dev/null +++ b/editor/icons/ColorPickerBarArrow.svg @@ -0,0 +1 @@ +<svg height="20" viewBox="0 0 16 20" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 16h12l-6-6z" fill="#e0e0e0" stroke-width="2"/></svg> diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index d0e5798045..14ecccc13e 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -35,7 +35,7 @@ #include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/mesh_instance_3d.h" -#include "scene/3d/navigation_3d.h" +#include "scene/3d/navigation_region_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/vehicle_body_3d.h" #include "scene/animation/animation_player.h" diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 16eefb1ad3..64cf9a7bb7 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -2073,7 +2073,13 @@ void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref<TriangleMesh> tm = soft_body->get_mesh()->generate_triangle_mesh(); Vector<Vector3> points; - soft_body->get_mesh()->generate_debug_mesh_indices(points); + for (int i = 0; i < soft_body->get_mesh()->get_surface_count(); i++) { + Array arrays = soft_body->get_mesh()->surface_get_arrays(i); + ERR_CONTINUE(arrays.is_empty()); + + const Vector<Vector3> &vertices = arrays[Mesh::ARRAY_VERTEX]; + points.append_array(vertices); + } Ref<Material> material = get_material("shape_material", p_gizmo); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 19c9662162..f496811e0a 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -86,7 +86,7 @@ void PluginConfigDialog::_on_confirmed() { // Hard-coded GDScript template to keep usability until we use script templates. Ref<Script> gdscript = memnew(GDScript); gdscript->set_source_code( - "tool\n" + "@tool\n" "extends EditorPlugin\n" "\n" "\n" @@ -112,7 +112,7 @@ void PluginConfigDialog::_on_confirmed() { } #endif - emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? subfolder_edit->get_text() : ""); + emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? _to_absolute_plugin_path(subfolder_edit->get_text()) : ""); } else { EditorNode::get_singleton()->get_project_settings()->update_plugins(); } @@ -129,6 +129,10 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { get_ok_button()->set_disabled(script_edit->get_text().get_basename().is_empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().is_empty()); } +String PluginConfigDialog::_to_absolute_plugin_path(const String &p_plugin_name) { + return "res://addons/" + p_plugin_name + "/plugin.cfg"; +} + void PluginConfigDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h index 50ca417d81..f49f14c881 100644 --- a/editor/plugin_config_dialog.h +++ b/editor/plugin_config_dialog.h @@ -56,6 +56,8 @@ class PluginConfigDialog : public ConfirmationDialog { void _on_cancelled(); void _on_required_text_changed(const String &p_text); + static String _to_absolute_plugin_path(const String &p_plugin_name); + protected: virtual void _notification(int p_what); static void _bind_methods(); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 876b67fa77..c90f87de56 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -585,11 +585,11 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { edited_point = PosVertex(); hover_point = Vertex(); selected_point = Vertex(); - - canvas_item_editor->update_viewport(); } else { _set_node(nullptr); } + + canvas_item_editor->update_viewport(); } void AbstractPolygon2DEditor::_bind_methods() { diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 030ce4655d..b7484aa748 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -584,6 +584,24 @@ void EditorAssetLibrary::_notification(int p_what) { filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + _update_repository_options(); + } break; + } +} + +void EditorAssetLibrary::_update_repository_options() { + Dictionary default_urls; + default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api"; + default_urls["localhost"] = "http://127.0.0.1/asset-library/api"; + Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true); + repository->clear(); + Array keys = available_urls.keys(); + for (int i = 0; i < available_urls.size(); i++) { + String key = keys[i]; + repository->add_item(key); + repository->set_item_metadata(i, available_urls[key]); } } @@ -1373,18 +1391,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { search_hb2->add_child(memnew(Label(TTR("Site:") + " "))); repository = memnew(OptionButton); - { - Dictionary default_urls; - default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api"; - default_urls["localhost"] = "http://127.0.0.1/asset-library/api"; - Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true); - Array keys = available_urls.keys(); - for (int i = 0; i < available_urls.size(); i++) { - String key = keys[i]; - repository->add_item(key); - repository->set_item_metadata(i, available_urls[key]); - } - } + _update_repository_options(); repository->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_repository_changed)); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 0509145673..11eae9e041 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -176,6 +176,7 @@ class EditorAssetLibrary : public PanelContainer { void _asset_open(); void _asset_file_selected(const String &p_file); + void _update_repository_options(); PanelContainer *library_scroll_bg; ScrollContainer *library_scroll; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 82ebf48242..bac6f3cd79 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -955,9 +955,11 @@ void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_it for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - canvas_item->_edit_set_state(se->undo_state); - if (restore_bones) { - _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state)); + if (se) { + canvas_item->_edit_set_state(se->undo_state); + if (restore_bones) { + _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state)); + } } } } @@ -982,13 +984,15 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite for (List<CanvasItem *>::Element *E = modified_canvas_items.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); - undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state); - if (commit_bones) { - for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) { - canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); - undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); - undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get()); + if (se) { + undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); + undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state); + if (commit_bones) { + for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) { + canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); + undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); + undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get()); + } } } } @@ -2238,17 +2242,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - - Node2D *node2d = Object::cast_to<Node2D>(canvas_item); - if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) { - real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); - _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); - real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); - node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); - _solve_IK(node2d, new_pos); - } else { - canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + if (se) { + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); + + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); + _solve_IK(node2d, new_pos); + } else { + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + } } index++; } @@ -2372,17 +2378,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - - Node2D *node2d = Object::cast_to<Node2D>(canvas_item); - if (node2d && se->pre_drag_bones_undo_state.size() > 0) { - real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); - _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); - real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); - node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); - _solve_IK(node2d, new_pos); - } else { - canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + if (se) { + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); + + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); + _solve_IK(node2d, new_pos); + } else { + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + } } index++; } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 9643881f96..1d08a7821d 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1841,9 +1841,8 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) { + const int mod = _get_key_modifier(m); if (nav_scheme == NAVIGATION_GODOT) { - const int mod = _get_key_modifier(m); - if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) { @@ -1854,7 +1853,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } else if (nav_scheme == NAVIGATION_MAYA) { - if (m->get_alt()) { + if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } } diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 0547f99079..a6949c873e 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -219,7 +219,8 @@ void SpriteFramesEditor::_sheet_zoom_out() { } void SpriteFramesEditor::_sheet_zoom_reset() { - sheet_zoom = 1.f; + // Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad. + sheet_zoom = MAX(1.0, EDSCALE); Size2 texture_size = split_sheet_preview->get_texture()->get_size(); split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom); } @@ -732,7 +733,7 @@ void SpriteFramesEditor::_zoom_out() { } void SpriteFramesEditor::_zoom_reset() { - thumbnail_zoom = 1.0f; + thumbnail_zoom = MAX(1.0, EDSCALE); tree->set_fixed_column_width(thumbnail_default_size * 3 / 2); tree->set_fixed_icon_size(Size2(thumbnail_default_size, thumbnail_default_size)); } @@ -1229,13 +1230,14 @@ SpriteFramesEditor::SpriteFramesEditor() { // Config scale. scale_ratio = 1.2f; - thumbnail_default_size = 96; - thumbnail_zoom = 1.0f; - max_thumbnail_zoom = 8.0f; - min_thumbnail_zoom = 0.1f; - sheet_zoom = 1.0f; - max_sheet_zoom = 16.0f; - min_sheet_zoom = 0.01f; + thumbnail_default_size = 96 * MAX(1.0, EDSCALE); + thumbnail_zoom = MAX(1.0, EDSCALE); + max_thumbnail_zoom = 8.0f * MAX(1.0, EDSCALE); + min_thumbnail_zoom = 0.1f * MAX(1.0, EDSCALE); + // Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad. + sheet_zoom = MAX(1.0, EDSCALE); + max_sheet_zoom = 16.0f * MAX(1.0, EDSCALE); + min_sheet_zoom = 0.01f * MAX(1.0, EDSCALE); _zoom_reset(); } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 07312e42b4..8ce7153355 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -417,7 +417,12 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: updating = false; return false; - } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_2D_RENDER || + hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_3D_RENDER || + hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { String basename; switch (hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: @@ -426,12 +431,18 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: case PROPERTY_HINT_LAYERS_2D_PHYSICS: basename = "layer_names/2d_physics"; break; + case PROPERTY_HINT_LAYERS_2D_NAVIGATION: + basename = "layer_names/2d_navigation"; + break; case PROPERTY_HINT_LAYERS_3D_RENDER: basename = "layer_names/3d_render"; break; case PROPERTY_HINT_LAYERS_3D_PHYSICS: basename = "layer_names/3d_physics"; break; + case PROPERTY_HINT_LAYERS_3D_NAVIGATION: + basename = "layer_names/3d_navigation"; + break; } checks20gc->show(); @@ -1153,7 +1164,12 @@ void CustomPropertyEditor::_action_pressed(int p_which) { emit_signal("variant_changed"); } break; case Variant::INT: { - if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) { + if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_2D_RENDER || + hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || + hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || + hint == PROPERTY_HINT_LAYERS_3D_RENDER || + hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { uint32_t f = v; if (checks20[p_which]->is_pressed()) { f |= (1 << p_which); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 16a0576af4..2cdab83d90 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -685,7 +685,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_do_method(editor_selection, "clear"); Node *dupsingle = nullptr; - List<Node *> editable_children; selection.sort_custom<Node::Comparator>(); @@ -701,10 +700,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Map<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap); - if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node)) { - editable_children.push_back(dup); - } - ERR_CONTINUE(!dup); if (selection.size() == 1) { @@ -739,11 +734,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (dupsingle) { editor->push_item(dupsingle); } - - for (List<Node *>::Element *E = editable_children.back(); E; E = E->prev()) { - _toggle_editable_children(E->get()); - } - } break; case TOOL_REPARENT: { if (!profile_allow_editing) { diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index b6347d3b46..2d739202fb 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -776,9 +776,11 @@ void SceneTreeEditor::_renamed() { return; } - String new_name = which->get_text(0); - if (!Node::_validate_node_name(new_name)) { - error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + Node::invalid_character); + String raw_new_name = which->get_text(0); + String new_name = raw_new_name.validate_node_name(); + + if (new_name != raw_new_name) { + error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + String::invalid_node_name_characters); error->popup_centered(); if (new_name.is_empty()) { diff --git a/main/main.cpp b/main/main.cpp index 9c8909f8fb..67152bb52a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -529,7 +529,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph input_map = memnew(InputMap); globals = memnew(ProjectSettings); - register_core_settings(); //here globals is present + register_core_settings(); //here globals are present translation_server = memnew(TranslationServer); performance = memnew(Performance); @@ -1517,7 +1517,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { input = memnew(Input); - /* Iniitalize Display Server */ + /* Initialize Display Server */ { String rendering_driver; // temp broken @@ -1547,7 +1547,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { display_server->screen_set_orientation(window_orientation); } - /* Initialize Pen Table Driver */ + /* Initialize Pen Tablet Driver */ { GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver", ""); @@ -1796,7 +1796,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { if (!project_manager) { // If not running the project manager, and now that the engine is // able to load resources, load the global shader variables. - // If running on editor, dont load the textures because the editor + // If running on editor, don't load the textures because the editor // may want to import them first. Editor will reload those later. rendering_server->global_variables_load_settings(!editor); } @@ -1804,7 +1804,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { _start_success = true; locale = String(); - ClassDB::set_current_api(ClassDB::API_NONE); //no more api is registered at this point + ClassDB::set_current_api(ClassDB::API_NONE); //no more APIs are registered at this point print_verbose("CORE API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_CORE))); print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR))); @@ -2606,7 +2606,7 @@ void Main::cleanup(bool p_force) { // Sync pending commands that may have been queued from a different thread during ScriptServer finalization RenderingServer::get_singleton()->sync(); - //clear global shader variables before scene and other graphics stuff is deinitialized. + //clear global shader variables before scene and other graphics stuff are deinitialized. rendering_server->global_variables_clear(); #ifdef TOOLS_ENABLED diff --git a/methods.py b/methods.py index 9b29eadc16..725fb36caa 100644 --- a/methods.py +++ b/methods.py @@ -334,7 +334,7 @@ def use_windows_spawn_fix(self, platform=None): # On Windows, due to the limited command line length, when creating a static library # from a very high number of objects SCons will invoke "ar" once per object file; # that makes object files with same names to be overwritten so the last wins and - # the library looses symbols defined by overwritten objects. + # the library loses symbols defined by overwritten objects. # By enabling quick append instead of the default mode (replacing), libraries will # got built correctly regardless the invocation strategy. # Furthermore, since SCons will rebuild the library from scratch when an object file @@ -478,7 +478,7 @@ def detect_visual_c_compiler_version(tools_env): # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect # the proper vc version that will be called - # There is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc) + # There is no flag to give to visual c compilers to set the architecture, i.e. scons bits argument (32,64,ARM etc) # There are many different cl.exe files that are run, and each one compiles & links to a different architecture # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program() # is to check the PATH variable and figure out which one will be called first. Code below does that and returns: @@ -633,7 +633,7 @@ def generate_vs_project(env, num_jobs): 'call "' + batch_file + '" !plat!', ] - # windows allows us to have spaces in paths, so we need + # Windows allows us to have spaces in paths, so we need # to double quote off the directory. However, the path ends # in a backslash, so we need to remove this, lest it escape the # last double quote off, confusing MSBuild diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 3bf87f3506..99ac2379ce 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -502,7 +502,7 @@ showTab('loader'); setLoaderEnabled(true); }; - editor.start({'args': args}); + editor.start({'args': args, 'persistentDrops': is_project_manager}); }); }, 0); OnEditorExit = null; @@ -563,7 +563,7 @@ //selectVideoMode(); showTab('editor'); setLoaderEnabled(false); - editor.start({'args': ['--video-driver', video_driver]}).then(function() { + editor.start({'args': ['--project-manager', '--video-driver', video_driver], 'persistentDrops': true}).then(function() { setStatusMode('hidden'); initializing = false; }); diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format index 1cbc576565..7c6e5fcb42 100755 --- a/misc/hooks/pre-commit-clang-format +++ b/misc/hooks/pre-commit-clang-format @@ -103,7 +103,7 @@ CLANG_FORMAT_VERSION="$(clang-format --version | cut -d' ' -f3)" CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d'.' -f1)" if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then - echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $CLANG_FORMAT_MAJOR.x.x)." + echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)." echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly." fi diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 26e9f5a044..7c27292e59 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -461,7 +461,7 @@ void BulletPhysicsServer3D::body_set_space(RID p_body, RID p_space) { } if (body->get_space() == space) { - return; //pointles + return; //pointless } body->set_space(space); @@ -617,11 +617,11 @@ uint32_t BulletPhysicsServer3D::body_get_collision_mask(RID p_body) const { } void BulletPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) { - // This function si not currently supported + // This function is not currently supported } uint32_t BulletPhysicsServer3D::body_get_user_flags(RID p_body) const { - // This function si not currently supported + // This function is not currently supported return 0; } @@ -898,7 +898,7 @@ void BulletPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) { } if (body->get_space() == space) { - return; //pointles + return; //pointless } body->set_space(space); diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp index 7b21e4e4b2..19d4816372 100644 --- a/modules/bullet/bullet_types_converter.cpp +++ b/modules/bullet/bullet_types_converter.cpp @@ -116,7 +116,7 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) { } } else { // Column 1 scale not fuzzy zero. if (column2.fuzzyZero()) { - // Create two vectors othogonal to column 1. + // Create two vectors orthogonal to column 1. // Ensure that a default basis is created if column 1 = <0, 1, 0> column0 = btVector3(column1[1], -column1[0], 0); column2 = column0.cross(column1); diff --git a/modules/bullet/godot_collision_dispatcher.cpp b/modules/bullet/godot_collision_dispatcher.cpp index 5d1e4d34d8..423166c408 100644 --- a/modules/bullet/godot_collision_dispatcher.cpp +++ b/modules/bullet/godot_collision_dispatcher.cpp @@ -43,7 +43,7 @@ GodotCollisionDispatcher::GodotCollisionDispatcher(btCollisionConfiguration *col bool GodotCollisionDispatcher::needsCollision(const btCollisionObject *body0, const btCollisionObject *body1) { if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) { - // Avoide area narrow phase + // Avoid area narrow phase return false; } return btCollisionDispatcher::needsCollision(body0, body1); @@ -51,7 +51,7 @@ bool GodotCollisionDispatcher::needsCollision(const btCollisionObject *body0, co bool GodotCollisionDispatcher::needsResponse(const btCollisionObject *body0, const btCollisionObject *body1) { if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) { - // Avoide area narrow phase + // Avoid area narrow phase return false; } return btCollisionDispatcher::needsResponse(body0, body1); diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 15d625afeb..e92b6c189c 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -113,7 +113,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo PhysicsDirectSpaceState3D::ShapeResult &result = m_results[count]; - result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID result.rid = gObj->get_self(); result.collider_id = gObj->get_instance_id(); result.collider = result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(result.collider_id); @@ -176,7 +176,7 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) { if (convexResult.m_localShapeInfo) { - m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID } else { m_shapeId = 0; } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index a5093afe9d..433bff8c38 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -515,7 +515,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer3D::BodyParameter p_param) const } void RigidBodyBullet::set_mode(PhysicsServer3D::BodyMode p_mode) { - // This is necessary to block force_integration untile next move + // This is necessary to block force_integration until next move can_integrate_forces = false; destroy_kinematic_utilities(); // The mode change is relevant to its mass @@ -725,7 +725,7 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) { // 1 meter in one simulation frame btBody->setCcdMotionThreshold(1e-7); - /// Calculate using the rule writte below the CCD swept sphere radius + /// Calculate using the rule write below the CCD swept sphere radius /// CCD works on an embedded sphere of radius, make sure this radius /// is embedded inside the convex objects, preferably smaller: /// for an object of dimensions 1 meter, try 0.2 diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index 91a1934e07..a8980984a7 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -336,7 +336,7 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector<int> p_indices, Vector<Vector Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]); int vertex_id; if (e) { - // Already rxisting + // Already existing vertex_id = e->value(); } else { // Create new one diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 7d337bc4d0..ceae3be8bc 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -81,7 +81,7 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape btResult.m_collisionFilterMask = p_collision_mask; space->dynamicsWorld->contactTest(&collision_object_point, btResult); - // The results is already populated by GodotAllConvexResultCallback + // The results are already populated by GodotAllConvexResultCallback return btResult.m_count; } diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index f0a2f17ba9..8b46447f04 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -970,7 +970,7 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ continue; } - // Check if point is on an each edge. + // Check if point is on each edge. for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { Vector2 edge_points[2] = { face_points[face_edge_idx], @@ -1076,7 +1076,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s break; } - // If opposite point is on the segemnt, add its index to segment indices too. + // If opposite point is on the segment, add its index to segment indices too. Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points); if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) { _add_vertex_idx_sorted(r_segment_indices, opposite_vertex_idx); @@ -1137,7 +1137,7 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { } } - // Check if point is on an each edge. + // Check if point is on each edge. bool on_edge = false; for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { Vector2 edge_points[2] = { @@ -1400,7 +1400,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face under_count++; } } - // If all points under or over the plane, there is no intesection. + // If all points under or over the plane, there is no intersection. if (over_count == 3 || under_count == 3) { return; } @@ -1421,7 +1421,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face under_count++; } } - // If all points under or over the plane, there is no intesection. + // If all points under or over the plane, there is no intersection. if (over_count == 3 || under_count == 3) { return; } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 40ba457e43..b97ee6ce4c 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1160,7 +1160,7 @@ CSGBrush *CSGBox3D::_build_brush() { materialsw[face] = material; face++; - //face 1 + //face 2 facesw[face * 3 + 0] = face_points[2] * vertex_mul; facesw[face * 3 + 1] = face_points[3] * vertex_mul; facesw[face * 3 + 2] = face_points[0] * vertex_mul; diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 276f13e553..25b87145b6 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -248,7 +248,7 @@ void NetworkedMultiplayerENet::poll() { int *new_id = memnew(int); *new_id = event.data; - if (*new_id == 0) { // Data zero is sent by server (enet won't let you configure this). Server is always 1. + if (*new_id == 0) { // Data zero is sent by server (ENet won't let you configure this). Server is always 1. *new_id = 1; } diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index a4ed7ebb8c..9af9226a79 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -53,7 +53,9 @@ extern "C" { #endif // This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!! -#ifdef _WIN32 +#ifdef __GNUC__ +#define GDN_EXPORT __attribute__((visibility("default"))) +#elif defined(_WIN32) #define GDN_EXPORT __declspec(dllexport) #else #define GDN_EXPORT diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 73b1738b03..c97f5f0389 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -58,8 +58,10 @@ typedef enum { GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) GODOT_PROPERTY_HINT_LAYERS_2D_RENDER, GODOT_PROPERTY_HINT_LAYERS_2D_PHYSICS, + GODOT_PROPERTY_HINT_LAYERS_2D_NAVIGATION, GODOT_PROPERTY_HINT_LAYERS_3D_RENDER, GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS, + GODOT_PROPERTY_HINT_LAYERS_3D_NAVIGATION, GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," GODOT_PROPERTY_HINT_DIR, ///< a directory path must be passed GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 1bdbb0b03b..0025f4bb06 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -173,7 +173,7 @@ bool NativeScript::can_instance() const { #ifdef TOOLS_ENABLED // Only valid if this is either a tool script or a "regular" script. - // (so an environment whre scripting is disabled (and not the editor) would not + // (so, an environment where scripting is disabled (and not the editor) would not // create objects). return script_data && (is_tool() || ScriptServer::is_scripting_enabled()); #else diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 31f4fecb19..d08bde9e23 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -142,7 +142,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty } } - // Add symbols for staticaly linked libraries on iOS + // Add symbols for statically linked libraries on iOS if (p_features.has("iOS")) { bool should_fake_dynamic = false; diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index 4f61ad5040..af76d9a4cc 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -200,11 +200,11 @@ real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const { return map->get_edge_connection_margin(); } -Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { +Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const { const NavMap *map = map_owner.getornull(p_map); ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>()); - return map->get_path(p_origin, p_destination, p_optimize); + return map->get_path(p_origin, p_destination, p_optimize, p_layers); } Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { @@ -273,6 +273,20 @@ COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform) { region->set_transform(p_transform); } +COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) { + NavRegion *region = region_owner.getornull(p_region); + ERR_FAIL_COND(region == nullptr); + + region->set_layers(p_layers); +} + +uint32_t GdNavigationServer::region_get_layers(RID p_region) const { + NavRegion *region = region_owner.getornull(p_region); + ERR_FAIL_COND_V(region == nullptr, 0); + + return region->get_layers(); +} + COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) { NavRegion *region = region_owner.getornull(p_region); ERR_FAIL_COND(region == nullptr); diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h index 92f4ccfdd5..8bc65eccab 100644 --- a/modules/gdnavigation/gd_navigation_server.h +++ b/modules/gdnavigation/gd_navigation_server.h @@ -100,7 +100,7 @@ public: COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin); virtual real_t map_get_edge_connection_margin(RID p_map) const; - virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const; + virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const; virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const; virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const; @@ -109,6 +109,8 @@ public: virtual RID region_create() const; COMMAND_2(region_set_map, RID, p_region, RID, p_map); + COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers); + virtual uint32_t region_get_layers(RID p_region) const; COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform); COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh); virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const; diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 2646a4cc0c..5289975e4b 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -70,7 +70,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { return p; } -Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { +Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const { const gd::Polygon *begin_poly = nullptr; const gd::Polygon *end_poly = nullptr; Vector3 begin_point; @@ -82,6 +82,11 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p for (size_t i(0); i < polygons.size(); i++) { const gd::Polygon &p = polygons[i]; + // Only consider the polygon if it in a region with compatible layers. + if ((p_layers & p.owner->get_layers()) == 0) { + continue; + } + // For each point cast a face and check the distance between the origin/destination for (size_t point_id = 2; point_id < p.points.size(); point_id++) { Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); @@ -144,6 +149,11 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) { gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id]; + // Only consider the polygon if it in a region with compatible layers. + if ((p_layers & least_cost_poly->poly->owner->get_layers()) == 0) { + continue; + } + const gd::Edge &edge = least_cost_poly->poly->edges[i]; if (!edge.other_polygon) { continue; @@ -629,7 +639,7 @@ void NavMap::sync() { connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge; } else { // The edge is already connected with another edge, skip. - ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation3D's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); + ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the current `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); } } } diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h index bffc1fbc1a..6b7cfae324 100644 --- a/modules/gdnavigation/nav_map.h +++ b/modules/gdnavigation/nav_map.h @@ -102,7 +102,7 @@ public: gd::PointKey get_point_key(const Vector3 &p_pos) const; - Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) const; + Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const; Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const; Vector3 get_closest_point(const Vector3 &p_point) const; Vector3 get_closest_point_normal(const Vector3 &p_point) const; diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp index 383b0f15a6..a07995bc11 100644 --- a/modules/gdnavigation/nav_region.cpp +++ b/modules/gdnavigation/nav_region.cpp @@ -41,6 +41,14 @@ void NavRegion::set_map(NavMap *p_map) { polygons_dirty = true; } +void NavRegion::set_layers(uint32_t p_layers) { + layers = p_layers; +} + +uint32_t NavRegion::get_layers() const { + return layers; +} + void NavRegion::set_transform(Transform p_transform) { transform = p_transform; polygons_dirty = true; diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h index 954780033b..fff7843fde 100644 --- a/modules/gdnavigation/nav_region.h +++ b/modules/gdnavigation/nav_region.h @@ -31,10 +31,10 @@ #ifndef NAV_REGION_H #define NAV_REGION_H -#include "nav_rid.h" +#include "scene/resources/navigation_mesh.h" +#include "nav_rid.h" #include "nav_utils.h" -#include "scene/3d/navigation_3d.h" #include <vector> /** @@ -48,6 +48,7 @@ class NavRegion : public NavRid { NavMap *map = nullptr; Transform transform; Ref<NavigationMesh> mesh; + uint32_t layers = 1; bool polygons_dirty = true; @@ -66,6 +67,9 @@ public: return map; } + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_transform(Transform transform); const Transform &get_transform() const { return transform; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 06d628d23f..76b7522f41 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2419,7 +2419,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa p_script->initializer->call(instance, nullptr, 0, ce); if (ce.error != Callable::CallError::CALL_OK) { - //well, tough luck, not goinna do anything here + //well, tough luck, not gonna do anything here } } #endif diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index c6c9a439df..7b37aa40a2 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -244,7 +244,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { bool completed = true; // If the return value is a GDScriptFunctionState reference, - // then the function did awaited again after resuming. + // then the function did await again after resuming. if (ret.is_ref()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); if (gdfs && gdfs->function == function) { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 08645d371c..7f3dd6b2e5 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -130,8 +130,10 @@ GDScriptParser::GDScriptParser() { register_annotation(MethodInfo("@export_flags", { Variant::STRING, "names" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true); register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>); register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>); + register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>); register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_RENDER, Variant::INT>); register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>); + register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>); // Networking. register_annotation(MethodInfo("@remote"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_REMOTE>); register_annotation(MethodInfo("@master"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTER>); @@ -3016,7 +3018,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty // Avoid desync. static_assert(sizeof(rules) / sizeof(rules[0]) == GDScriptTokenizer::Token::TK_MAX, "Amount of parse rules don't match the amount of token types."); - // Let's assume this this never invalid, since nothing generates a TK_MAX. + // Let's assume this is never invalid, since nothing generates a TK_MAX. return &rules[p_token_type]; } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 315b8ee3b4..319778daab 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -1169,7 +1169,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() { if (pending_newline) { pending_newline = false; if (!multiline_mode) { - // Don't return newline tokens on multine mode. + // Don't return newline tokens on multiline mode. return last_newline; } } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 4e098d7a6d..2216fcab2d 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -649,7 +649,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (scr_B) { //if B is a script, the only valid condition is that A has an instance which inherits from the script - //in other situation, this shoul return false. + //in other situation, this should return false. if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index e90475a60e..93b709a613 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -85,7 +85,7 @@ public: return; } - // TODO: Readd compiled GDScript on export. + // TODO: Re-add compiled GDScript on export. return; } }; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 4868347a74..0a4d4055b4 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -72,6 +72,7 @@ #include "scene/3d/node_3d.h" #include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" +#include "scene/main/node.h" #include "scene/resources/surface_tool.h" #include <limits> @@ -449,14 +450,8 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { return OK; } -String GLTFDocument::_sanitize_scene_name(const String &name) { - RegEx regex("([^a-zA-Z0-9_ -]+)"); - String p_name = regex.sub(name, "", true); - return p_name; -} - String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) { - const String s_name = _sanitize_scene_name(p_name); + const String s_name = p_name.validate_node_name(); String name; int index = 1; @@ -464,7 +459,7 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name name = s_name; if (index > 1) { - name += " " + itos(index); + name += itos(index); } if (!state->unique_names.has(name)) { break; @@ -477,6 +472,39 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name return name; } +String GLTFDocument::_sanitize_animation_name(const String &p_name) { + // Animations disallow the normal node invalid characters as well as "," and "[" + // (See animation/animation_player.cpp::add_animation) + + // TODO: Consider adding invalid_characters or a validate_animation_name to animation_player to mirror Node. + String name = p_name.validate_node_name(); + name = name.replace(",", ""); + name = name.replace("[", ""); + return name; +} + +String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const String &p_name) { + const String s_name = _sanitize_animation_name(p_name); + + String name; + int index = 1; + while (true) { + name = s_name; + + if (index > 1) { + name += itos(index); + } + if (!state->unique_animation_names.has(name)) { + break; + } + index++; + } + + state->unique_animation_names.insert(name); + + return name; +} + String GLTFDocument::_sanitize_bone_name(const String &name) { String p_name = name.camelcase_to_underscore(true); @@ -4729,7 +4757,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { animation->set_loop(true); } - animation->set_name(_sanitize_scene_name(name)); + animation->set_name(_gen_unique_animation_name(state, name)); } for (int j = 0; j < channels.size(); j++) { diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index ddf307e6a7..bda1ce87d6 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -162,8 +162,9 @@ private: Error _parse_nodes(Ref<GLTFState> state); String _get_type_name(const GLTFType p_component); String _get_accessor_type_name(const GLTFDocument::GLTFType p_type); - String _sanitize_scene_name(const String &name); String _gen_unique_name(Ref<GLTFState> state, const String &p_name); + String _sanitize_animation_name(const String &name); + String _gen_unique_animation_name(Ref<GLTFState> state, const String &p_name); String _sanitize_bone_name(const String &name); String _gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 86f8f44612..ff9778e7d8 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -71,6 +71,8 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lights", "lights"), &GLTFState::set_lights); ClassDB::bind_method(D_METHOD("get_unique_names"), &GLTFState::get_unique_names); ClassDB::bind_method(D_METHOD("set_unique_names", "unique_names"), &GLTFState::set_unique_names); + ClassDB::bind_method(D_METHOD("get_unique_animation_names"), &GLTFState::get_unique_animation_names); + ClassDB::bind_method(D_METHOD("set_unique_animation_names", "unique_animation_names"), &GLTFState::set_unique_animation_names); ClassDB::bind_method(D_METHOD("get_skeletons"), &GLTFState::get_skeletons); ClassDB::bind_method(D_METHOD("set_skeletons", "skeletons"), &GLTFState::set_skeletons); ClassDB::bind_method(D_METHOD("get_skeleton_to_node"), &GLTFState::get_skeleton_to_node); @@ -98,6 +100,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lights", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_lights", "get_lights"); // Vector<Ref<GLTFLight>> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String> + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>> ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // Map<GLTFSkeletonIndex, ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>> @@ -255,6 +258,14 @@ void GLTFState::set_unique_names(Array p_unique_names) { GLTFDocument::set_from_array(unique_names, p_unique_names); } +Array GLTFState::get_unique_animation_names() { + return GLTFDocument::to_array(unique_animation_names); +} + +void GLTFState::set_unique_animation_names(Array p_unique_animation_names) { + GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names); +} + Array GLTFState::get_skeletons() { return GLTFDocument::to_array(skeletons); } diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 4ce5aa9491..9030962b03 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -80,6 +80,7 @@ class GLTFState : public Resource { Vector<Ref<GLTFCamera>> cameras; Vector<Ref<GLTFLight>> lights; Set<String> unique_names; + Set<String> unique_animation_names; Vector<Ref<GLTFSkeleton>> skeletons; Map<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node; @@ -147,6 +148,9 @@ public: Array get_unique_names(); void set_unique_names(Array p_unique_names); + Array get_unique_animation_names(); + void set_unique_animation_names(Array p_unique_names); + Array get_skeletons(); void set_skeletons(Array p_skeletons); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index e28cc57f9b..25776b1f6d 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -184,6 +184,9 @@ </method> </methods> <members> + <member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false"> + If [code]true[/code], this GridMap bakes a navigation region. + </member> <member name="cell_center_x" type="bool" setter="set_center_x" getter="get_center_x" default="true"> If [code]true[/code], grid items are centered on the X axis. </member> @@ -211,6 +214,9 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this GridMap detects collisions in. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> + <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1"> + The navigation layers the GridMap generates its navigable regions in. + </member> <member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library"> The assigned [MeshLibrary]. </member> diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index e7c252dc53..4e4f88ed6a 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -179,6 +179,24 @@ bool GridMap::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } +void GridMap::set_bake_navigation(bool p_bake_navigation) { + bake_navigation = p_bake_navigation; + _recreate_octant_data(); +} + +bool GridMap::is_baking_navigation() { + return bake_navigation; +} + +void GridMap::set_navigation_layers(uint32_t p_layers) { + navigation_layers = p_layers; + _recreate_octant_data(); +} + +uint32_t GridMap::get_navigation_layers() { + return navigation_layers; +} + void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) { if (!mesh_library.is_null()) { mesh_library->unregister_owner(this); @@ -474,13 +492,15 @@ bool GridMap::_octant_update(const OctantKey &p_key) { Octant::NavMesh nm; nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item); - if (navigation) { + if (bake_navigation) { RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers); NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh); - NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform); - NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * mesh_library->get_item_navmesh_transform(c.item)); + NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); nm.region = region; } + g.navmesh_ids[E->get()] = nm; } } @@ -564,15 +584,17 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); } - if (navigation && mesh_library.is_valid()) { + if (bake_navigation && mesh_library.is_valid()) { for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) { if (cell_map.has(F->key()) && F->get().region.is_valid() == false) { Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F->key()].item); if (nm.is_valid()) { RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers); NavigationServer3D::get_singleton()->region_set_navmesh(region, nm); - NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform); - NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F->get().xform); + NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); + F->get().region = region; } } @@ -594,12 +616,10 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) { RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID()); } - if (navigation) { - for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) { - if (F->get().region.is_valid()) { - NavigationServer3D::get_singleton()->free(F->get().region); - F->get().region = RID(); - } + for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) { + if (F->get().region.is_valid()) { + NavigationServer3D::get_singleton()->free(F->get().region); + F->get().region = RID(); } } } @@ -635,16 +655,6 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) { void GridMap::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { - Node3D *c = this; - while (c) { - navigation = Object::cast_to<Navigation3D>(c); - if (navigation) { - break; - } - - c = Object::cast_to<Node3D>(c->get_parent()); - } - last_transform = get_global_transform(); for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { @@ -679,8 +689,6 @@ void GridMap::_notification(int p_what) { _octant_exit_world(E->key()); } - navigation = nullptr; - //_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS); //_update_octants_callback(); //_update_area_instances(); @@ -707,6 +715,10 @@ void GridMap::_update_visibility() { RS::get_singleton()->instance_set_visible(mi.instance, is_visible_in_tree()); } } + + for (int i = 0; i < baked_meshes.size(); i++) { + RS::get_singleton()->instance_set_visible(baked_meshes[i].instance, is_visible_in_tree()); + } } void GridMap::_queue_octants_dirty() { @@ -785,6 +797,12 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &GridMap::set_collision_layer_bit); ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &GridMap::get_collision_layer_bit); + ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation); + ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation); + + ClassDB::bind_method(D_METHOD("set_navigation_layers", "layers"), &GridMap::set_navigation_layers); + ClassDB::bind_method(D_METHOD("get_navigation_layers"), &GridMap::get_navigation_layers); + ClassDB::bind_method(D_METHOD("set_mesh_library", "mesh_library"), &GridMap::set_mesh_library); ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library); @@ -838,6 +856,9 @@ void GridMap::_bind_methods() { ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_GROUP("Navigation", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); BIND_CONSTANT(INVALID_CELL_ITEM); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index e5ec4bb602..4c04d492f7 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -31,7 +31,6 @@ #ifndef GRID_MAP_H #define GRID_MAP_H -#include "scene/3d/navigation_3d.h" #include "scene/3d/node_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/multimesh.h" @@ -135,6 +134,8 @@ class GridMap : public Node3D { uint32_t collision_layer = 1; uint32_t collision_mask = 1; + bool bake_navigation = false; + uint32_t navigation_layers = 1; Transform last_transform; @@ -145,7 +146,6 @@ class GridMap : public Node3D { bool center_y = true; bool center_z = true; float cell_scale = 1.0; - Navigation3D *navigation = nullptr; bool clip = false; bool clip_above = true; @@ -223,6 +223,12 @@ public: void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; + void set_bake_navigation(bool p_bake_navigation); + bool is_baking_navigation(); + + void set_navigation_layers(uint32_t p_layers); + uint32_t get_navigation_layers(); + void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library); Ref<MeshLibrary> get_mesh_library() const; diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp index d7597aa435..b39a6ecc2f 100644 --- a/modules/mbedtls/stream_peer_mbedtls.cpp +++ b/modules/mbedtls/stream_peer_mbedtls.cpp @@ -242,7 +242,7 @@ void StreamPeerMbedTLS::poll() { return; } - // We could pass NULL as second parameter, but some behaviour sanitizers doesn't seem to like that. + // We could pass NULL as second parameter, but some behaviour sanitizers don't seem to like that. // Passing a 1 byte buffer to workaround it. uint8_t byte; int ret = mbedtls_ssl_read(ssl_ctx->get_context(), &byte, 0); diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 25b110dc62..5140cfbbaf 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -153,8 +153,8 @@ void MobileVRInterface::set_position_from_sensors() { last_magnetometer_data = magneto; if (grav.length() < 0.1) { - // not ideal but use our accelerometer, this will contain shakey shakey user behaviour - // maybe look into some math but I'm guessing that if this isn't available, its because we lack the gyro sensor to actually work out + // not ideal but use our accelerometer, this will contain shaky user behaviour + // maybe look into some math but I'm guessing that if this isn't available, it's because we lack the gyro sensor to actually work out // what a stable gravity vector is grav = acc; if (grav.length() > 0.1) { @@ -181,8 +181,8 @@ void MobileVRInterface::set_position_from_sensors() { tracking_state = XRInterface::XR_NORMAL_TRACKING; }; - ///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part) - // if you have a gyro + accelerometer that combo tends to be better then combining all three but without a gyro you need the magnetometer.. + ///@TODO improve this, the magnetometer is very fidgety sometimes flipping the axis for no apparent reason (probably a bug on my part) + // if you have a gyro + accelerometer that combo tends to be better than combining all three but without a gyro you need the magnetometer.. if (has_magneto && has_grav && !has_gyro) { // convert to quaternions, easier to smooth those out Quat transform_quat(orientation); @@ -372,7 +372,7 @@ Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, cons if (initialized) { float world_scale = xr_server->get_world_scale(); - // we don't need to check for the existence of our HMD, doesn't effect our values... + // we don't need to check for the existence of our HMD, doesn't affect our values... // note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction... if (p_eye == XRInterface::EYE_LEFT) { transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale); @@ -402,7 +402,7 @@ CameraMatrix MobileVRInterface::get_projection_for_eye(XRInterface::Eyes p_eye, CameraMatrix eye; if (p_eye == XRInterface::EYE_MONO) { - ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties + ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real camera's properties // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example. // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface // to position a stock standard Godot camera and have control over this. diff --git a/modules/mono/SdkPackageVersions.props b/modules/mono/SdkPackageVersions.props index 396443f30e..df3ebe581c 100644 --- a/modules/mono/SdkPackageVersions.props +++ b/modules/mono/SdkPackageVersions.props @@ -1,6 +1,6 @@ <Project> <PropertyGroup> - <PackageVersion_Godot_NET_Sdk>4.0.0-dev4</PackageVersion_Godot_NET_Sdk> - <PackageVersion_Godot_SourceGenerators>4.0.0-dev1</PackageVersion_Godot_SourceGenerators> + <PackageVersion_Godot_NET_Sdk>4.0.0-dev5</PackageVersion_Godot_NET_Sdk> + <PackageVersion_Godot_SourceGenerators>4.0.0-dev2</PackageVersion_Godot_SourceGenerators> </PropertyGroup> </Project> diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 4fca80fca0..610cecae7c 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -328,7 +328,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin String script_template = "using " BINDINGS_NAMESPACE ";\n" "using System;\n" "\n" - "public class %CLASS% : %BASE%\n" + "public partial class %CLASS% : %BASE%\n" "{\n" " // Declare member variables here. Examples:\n" " // private int a = 2;\n" diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj index ef8add0ba8..4e9e7184da 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj @@ -23,11 +23,12 @@ <ItemGroup> <!-- Package Sdk\Sdk.props and Sdk\Sdk.targets file --> - <None Include="Sdk\Sdk.props" Pack="true" PackagePath="Sdk" Visible="false" /> - <None Include="Sdk\Sdk.targets" Pack="true" PackagePath="Sdk" Visible="false" /> + <None Include="Sdk\Sdk.props" Pack="true" PackagePath="Sdk" /> + <None Include="Sdk\Sdk.targets" Pack="true" PackagePath="Sdk" /> <!-- SdkPackageVersions.props --> - - <None Include="..\..\..\SdkPackageVersions.props" Pack="true" PackagePath="Sdk" Visible="false" /> + <None Include="..\..\..\SdkPackageVersions.props" Pack="true" PackagePath="Sdk"> + <Link>Sdk\SdkPackageVersions.props</Link> + </None> </ItemGroup> <Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack"> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs index c3e74822d5..e16f72f43a 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs @@ -82,5 +82,8 @@ namespace Godot.SourceGenerators public static string FullQualifiedName(this INamedTypeSymbol symbol) => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal); + + public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol) + => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal); } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs index 150e59e414..a51728e221 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs @@ -69,7 +69,7 @@ namespace Godot.SourceGenerators IEnumerable<ClassDeclarationSyntax> classDeclarations ) { - var attributesBuilder = new StringBuilder(); + var attributes = new StringBuilder(); // Remember syntax trees for which we already added an attribute, to prevent unnecessary duplicates. var attributedTrees = new List<SyntaxTree>(); @@ -81,28 +81,54 @@ namespace Godot.SourceGenerators attributedTrees.Add(cds.SyntaxTree); - if (attributesBuilder.Length != 0) - attributesBuilder.Append("\n "); + if (attributes.Length != 0) + attributes.Append("\n"); - attributesBuilder.Append(@"[ScriptPathAttribute(""res://"); - attributesBuilder.Append(RelativeToDir(cds.SyntaxTree.FilePath, godotProjectDir)); - attributesBuilder.Append(@""")]"); + attributes.Append(@"[ScriptPathAttribute(""res://"); + attributes.Append(RelativeToDir(cds.SyntaxTree.FilePath, godotProjectDir)); + attributes.Append(@""")]"); } - string classNs = symbol.ContainingNamespace.Name; string className = symbol.Name; - var source = $@"using Godot; -namespace {classNs} -{{ - {attributesBuilder} - partial class {className} - {{ - }} -}} -"; - context.AddSource(classNs + "." + className + "_ScriptPath_Generated", - SourceText.From(source, Encoding.UTF8)); + INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; + string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? + namespaceSymbol.FullQualifiedName() : + string.Empty; + bool hasNamespace = classNs.Length != 0; + + string uniqueName = hasNamespace ? + classNs + "." + className + "_ScriptPath_Generated" : + className + "_ScriptPath_Generated"; + + var source = new StringBuilder(); + + // using Godot; + // namespace {classNs} { + // {attributesBuilder} + // partial class {className} { } + // } + + source.Append("using Godot;\n"); + + if (hasNamespace) + { + source.Append("namespace "); + source.Append(classNs); + source.Append(" {\n\n"); + } + + source.Append(attributes); + source.Append("\n partial class "); + source.Append(className); + source.Append("\n{\n}\n"); + + if (hasNamespace) + { + source.Append("\n}\n"); + } + + context.AddSource(uniqueName, SourceText.From(source.ToString(), Encoding.UTF8)); } private static void AddScriptTypesAssemblyAttr(GeneratorExecutionContext context, diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b1875aec3f..b48e5df9eb 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -3631,11 +3631,44 @@ void BindingsGenerator::_initialize() { initialized = true; } +static String generate_all_glue_option = "--generate-mono-glue"; +static String generate_cs_glue_option = "--generate-mono-cs-glue"; +static String generate_cpp_glue_option = "--generate-mono-cpp-glue"; + +static void handle_cmdline_options(String glue_dir_path, String cs_dir_path, String cpp_dir_path) { + BindingsGenerator bindings_generator; + bindings_generator.set_log_print_enabled(true); + + if (!bindings_generator.is_initialized()) { + ERR_PRINT("Failed to initialize the bindings generator"); + return; + } + + if (glue_dir_path.length()) { + if (bindings_generator.generate_glue(glue_dir_path) != OK) { + ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue."); + } + + if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) { + ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API."); + } + } + + if (cs_dir_path.length()) { + if (bindings_generator.generate_cs_api(cs_dir_path) != OK) { + ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API."); + } + } + + if (cpp_dir_path.length()) { + if (bindings_generator.generate_glue(cpp_dir_path) != OK) { + ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue."); + } + } +} + void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { const int NUM_OPTIONS = 2; - String generate_all_glue_option = "--generate-mono-glue"; - String generate_cs_glue_option = "--generate-mono-cs-glue"; - String generate_cpp_glue_option = "--generate-mono-cpp-glue"; String glue_dir_path; String cs_dir_path; @@ -3643,6 +3676,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) int options_left = NUM_OPTIONS; + bool exit_godot = false; + const List<String>::Element *elem = p_cmdline_args.front(); while (elem && options_left) { @@ -3654,6 +3689,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) elem = elem->next(); } else { ERR_PRINT(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue')."); + exit_godot = true; } --options_left; @@ -3665,6 +3701,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) elem = elem->next(); } else { ERR_PRINT(generate_cs_glue_option + ": No output directory specified."); + exit_godot = true; } --options_left; @@ -3676,6 +3713,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) elem = elem->next(); } else { ERR_PRINT(generate_cpp_glue_option + ": No output directory specified."); + exit_godot = true; } --options_left; @@ -3685,37 +3723,11 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) } if (glue_dir_path.length() || cs_dir_path.length() || cpp_dir_path.length()) { - BindingsGenerator bindings_generator; - bindings_generator.set_log_print_enabled(true); - - if (!bindings_generator.initialized) { - ERR_PRINT("Failed to initialize the bindings generator"); - Main::cleanup(true); - ::exit(0); - } - - if (glue_dir_path.length()) { - if (bindings_generator.generate_glue(glue_dir_path) != OK) { - ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue."); - } - - if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) { - ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API."); - } - } - - if (cs_dir_path.length()) { - if (bindings_generator.generate_cs_api(cs_dir_path) != OK) { - ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API."); - } - } - - if (cpp_dir_path.length()) { - if (bindings_generator.generate_glue(cpp_dir_path) != OK) { - ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue."); - } - } + handle_cmdline_options(glue_dir_path, cs_dir_path, cpp_dir_path); + exit_godot = true; + } + if (exit_godot) { // Exit once done Main::cleanup(true); ::exit(0); diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp index cba29d63cd..5dd33b036a 100644 --- a/modules/mono/mono_gd/support/android_support.cpp +++ b/modules/mono/mono_gd/support/android_support.cpp @@ -415,8 +415,7 @@ GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char if (r_value) { if (len >= 0) { *r_value = (char *)malloc(len + 1); - if (!*r_value) - return -1; + ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory."); memcpy(*r_value, prop_value_str, len); (*r_value)[len] = '\0'; } else { @@ -637,6 +636,7 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array) if (dns_servers_count > 0) { size_t ret_size = sizeof(char *) * (size_t)dns_servers_count; *r_dns_servers_array = malloc(ret_size); // freed by the BCL + ERR_FAIL_NULL_MSG(*r_dns_servers_array, "Out of memory."); memcpy(*r_dns_servers_array, dns_servers, ret_size); } diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp index b60b9ddaec..2521e68dda 100644 --- a/modules/text_server_adv/dynamic_font_adv.cpp +++ b/modules/text_server_adv/dynamic_font_adv.cpp @@ -129,7 +129,7 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size( fds->underline_position = (-FT_MulFix(fds->face->underline_position, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font; fds->underline_thickness = (FT_MulFix(fds->face->underline_thickness, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font; - //Load os2 TTF pable + //Load os2 TTF table fds->os2 = (TT_OS2 *)FT_Get_Sfnt_Table(fds->face, FT_SFNT_OS2); fds->hb_handle = hb_ft_font_create(fds->face, nullptr); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 2e3c2d1cab..43b8f18101 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -166,7 +166,7 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) { #ifdef ICU_STATIC_DATA if (icu_data == nullptr) { UErrorCode err = U_ZERO_ERROR; - u_init(&err); // Do not check for errors, since we only load part the of data. + u_init(&err); // Do not check for errors, since we only load part of the data. icu_data = (uint8_t *)&U_ICUDATA_ENTRY_POINT; } #else @@ -244,7 +244,7 @@ struct FeatureInfo { }; static FeatureInfo feature_set[] = { - // Registred OpenType feature tags. + // Registered OpenType feature tags. { HB_TAG('a', 'a', 'l', 't'), "access_all_alternates" }, { HB_TAG('a', 'b', 'v', 'f'), "above_base_forms" }, { HB_TAG('a', 'b', 'v', 'm'), "above_base_mark_positioning" }, @@ -484,7 +484,7 @@ static FeatureInfo feature_set[] = { { HB_TAG('v', 'r', 't', '2'), "vertical_alternates_and_rotation" }, { HB_TAG('v', 'r', 't', 'r'), "vertical_alternates_for_rotation" }, { HB_TAG('z', 'e', 'r', 'o'), "slashed_zero" }, - // Registred OpenType variation tags. + // Registered OpenType variation tags. { HB_TAG('i', 't', 'a', 'l'), "italic" }, { HB_TAG('o', 'p', 's', 'z'), "optical_size" }, { HB_TAG('s', 'l', 'n', 't'), "slant" }, @@ -1660,7 +1660,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { } if (sd->line_breaks_valid) { - return true; // Noting to do. + return true; // Nothing to do. } const UChar *data = sd->utf16.ptr(); @@ -1845,7 +1845,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { } if (sd->justification_ops_valid) { - return true; // Noting to do. + return true; // Nothing to do. } const UChar *data = sd->utf16.ptr(); diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 60ab14738a..f46f96d30d 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -1091,7 +1091,7 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) { } if (sd->line_breaks_valid) { - return true; // Noting to do. + return true; // Nothing to do. } int sd_size = sd->glyphs.size(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 2517b17168..e91ae46a57 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1369,7 +1369,7 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int // Is a default value (unassigned input port). input_args[i] = &default_values[index]; } else { - // Rregular temporary in stack. + // Regular temporary in stack. input_args[i] = &variant_stack[index]; } } @@ -1391,7 +1391,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p ERR_FAIL_COND_V(!F, Variant()); Function *f = &F->get(); - // This call goes separate, so it can e yielded and suspended. + // This call goes separate, so it can be yielded and suspended. Variant *variant_stack = (Variant *)p_stack; bool *sequence_bits = (bool *)(variant_stack + f->max_stack); const Variant **input_args = (const Variant **)(sequence_bits + f->node_count); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index fcd55b3049..3b2cd50544 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3958,7 +3958,7 @@ void VisualScriptEditor::_menu_option(int p_what) { if (start_node == -1) { // If we still don't have a start node then, // run through the nodes and select the first tree node, - // ie node without any input sequence but output sequence. + // i.e. node without any input sequence but output sequence. for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) { if (!nodes_to.has(E->get())) { start_node = E->get(); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index f673cbb06d..cb4230bea9 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -1054,7 +1054,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } } - /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ + /* Reduce the set of expressions and place them in an operator tree, respecting precedence */ while (expression.size() > 1) { int next_op = -1; diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index e2a8323509..e977f9c96b 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -800,7 +800,7 @@ public: } if (!ResourceCache::has(script)) { - //if the script is not in use by anyone, we can safely assume whathever we got is not casting to it. + //if the script is not in use by anyone, we can safely assume whatever we got is not casting to it. return 1; } Ref<Script> cast_script = Ref<Resource>(ResourceCache::get(script)); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index b5aacb0506..9310b86627 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -547,7 +547,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } else { Node *bnode = _get_base_node(); if (bnode) { - property.hint_string = bnode->get_path(); //convert to loong string + property.hint_string = bnode->get_path(); //convert to long string } } } @@ -1292,7 +1292,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } else { Node *bnode = _get_base_node(); if (bnode) { - property.hint_string = bnode->get_path(); //convert to loong string + property.hint_string = bnode->get_path(); //convert to long string } } } @@ -1970,7 +1970,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } else { Node *bnode = _get_base_node(); if (bnode) { - property.hint_string = bnode->get_path(); //convert to loong string + property.hint_string = bnode->get_path(); //convert to long string } } } diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index 25fabd7b87..52fe659983 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -425,7 +425,7 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { } else { Node *bnode = _get_base_node(); if (bnode) { - property.hint_string = bnode->get_path(); //convert to loong string + property.hint_string = bnode->get_path(); //convert to long string } } } diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp index 011cb86535..758ed66c80 100644 --- a/modules/websocket/websocket_multiplayer_peer.cpp +++ b/modules/websocket/websocket_multiplayer_peer.cpp @@ -53,7 +53,7 @@ int WebSocketMultiplayerPeer::_gen_unique_id() const { (uint32_t)((uint64_t)this), hash); //rely on aslr heap hash = hash_djb2_one_32( (uint32_t)((uint64_t)&hash), hash); //rely on aslr stack - hash = hash & 0x7FFFFFFF; // make it compatible with unsigned, since negatie id is used for exclusion + hash = hash & 0x7FFFFFFF; // make it compatible with unsigned, since negative id is used for exclusion } return hash; @@ -186,7 +186,7 @@ void WebSocketMultiplayerPeer::_send_add(int32_t p_peer_id) { for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { int32_t id = E->key(); if (p_peer_id == id) { - continue; // Skip the newwly added peer (already confirmed) + continue; // Skip the newly added peer (already confirmed) } // Send new peer to others @@ -314,7 +314,7 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u _peer_map.erase(id); emit_signal("peer_disconnected", id); break; - case SYS_ID: // Helo, server assigned ID + case SYS_ID: // Hello, server assigned ID _peer_id = id; break; default: diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp index fb4df10904..e1f9521a48 100644 --- a/modules/xatlas_unwrap/register_types.cpp +++ b/modules/xatlas_unwrap/register_types.cpp @@ -161,8 +161,11 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver const xatlas::Mesh &output = atlas->meshes[0]; *r_vertices = (int *)malloc(sizeof(int) * output.vertexCount); + ERR_FAIL_NULL_V_MSG(*r_vertices, false, "Out of memory."); *r_uvs = (float *)malloc(sizeof(float) * output.vertexCount * 2); + ERR_FAIL_NULL_V_MSG(*r_uvs, false, "Out of memory."); *r_indices = (int *)malloc(sizeof(int) * output.indexCount); + ERR_FAIL_NULL_V_MSG(*r_indices, false, "Out of memory."); float max_x = 0.0; float max_y = 0.0; diff --git a/platform/android/java/nativeSrcsConfigs/README.md b/platform/android/java/nativeSrcsConfigs/README.md index e48505ccda..9d884415cc 100644 --- a/platform/android/java/nativeSrcsConfigs/README.md +++ b/platform/android/java/nativeSrcsConfigs/README.md @@ -1,4 +1,4 @@ ## Native sources configs -This is a non functional Android library used to provide Android Studio editor support to the Godot project native files. +This is a non-functional Android library used to provide Android Studio editor support to the Godot project native files. Nothing else should be added to this library. diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index bb22162879..ae88c2c1be 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -127,9 +127,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc if (p_cmdline) { cmdlen = env->GetArrayLength(p_cmdline); if (cmdlen) { - cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *)); + cmdline = (const char **)memalloc((cmdlen + 1) * sizeof(const char *)); + ERR_FAIL_NULL_MSG(cmdline, "Out of memory."); cmdline[cmdlen] = nullptr; - j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring)); + j_cmdline = (jstring *)memalloc(cmdlen * sizeof(jstring)); + ERR_FAIL_NULL_MSG(j_cmdline, "Out of memory."); for (int i = 0; i < cmdlen; i++) { jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i); @@ -147,9 +149,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc for (int i = 0; i < cmdlen; ++i) { env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]); } - free(j_cmdline); + memfree(j_cmdline); } - free(cmdline); + memfree(cmdline); } if (err != OK) { diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index a605f22e16..e2c0a3d763 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -536,6 +536,43 @@ bool DisplayServerJavaScript::screen_is_touchscreen(int p_screen) const { return godot_js_display_touchscreen_is_available(); } +// Virtual Keybaord +void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_cursor) { + DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton(); + if (!ds || ds->input_text_callback.is_null()) { + return; + } + // Call input_text + Variant event = String(p_text); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + ds->input_text_callback.call((const Variant **)&eventp, 1, ret, ce); + // Insert key right to reach position. + Input *input = Input::get_singleton(); + Ref<InputEventKey> k; + for (int i = 0; i < p_cursor; i++) { + k.instance(); + k->set_pressed(true); + k->set_echo(false); + k->set_keycode(KEY_RIGHT); + input->parse_input_event(k); + k.instance(); + k->set_pressed(false); + k->set_echo(false); + k->set_keycode(KEY_RIGHT); + input->parse_input_event(k); + } +} + +void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_multiline, p_cursor_start, p_cursor_end); +} + +void DisplayServerJavaScript::virtual_keyboard_hide() { + godot_js_display_vk_hide(); +} + // Gamepad void DisplayServerJavaScript::gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid) { Input *input = Input::get_singleton(); @@ -683,7 +720,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive godot_js_config_canvas_id_get(canvas_id, 256); // Handle contextmenu, webglcontextlost - godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_mode == WINDOW_MODE_FULLSCREEN); + godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_mode == WINDOW_MODE_FULLSCREEN, OS::get_singleton()->is_hidpi_allowed() ? 1 : 0); // Check if it's windows. swap_cancel_ok = godot_js_display_is_swap_ok_cancel() == 1; @@ -764,6 +801,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive godot_js_display_paste_cb(update_clipboard_callback); godot_js_display_drop_files_cb(drop_files_js_callback); godot_js_display_gamepad_cb(&DisplayServerJavaScript::gamepad_callback); + godot_js_display_vk_cb(&vk_input_text_callback); Input::get_singleton()->set_event_dispatch_function(_dispatch_input_event); } @@ -793,7 +831,8 @@ bool DisplayServerJavaScript::has_feature(Feature p_feature) const { //case FEATURE_WINDOW_TRANSPARENCY: //case FEATURE_KEEP_SCREEN_ON: //case FEATURE_ORIENTATION: - //case FEATURE_VIRTUAL_KEYBOARD: + case FEATURE_VIRTUAL_KEYBOARD: + return godot_js_display_vk_available() != 0; default: return false; } @@ -866,7 +905,7 @@ void DisplayServerJavaScript::window_set_input_event_callback(const Callable &p_ } void DisplayServerJavaScript::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { - input_text_callback = p_callable; // TODO unused... do I need this? + input_text_callback = p_callable; } void DisplayServerJavaScript::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 47e25ab2a0..ece38f1a95 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -75,6 +75,8 @@ private: static EM_BOOL keypress_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data); static EM_BOOL keyup_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data); + static void vk_input_text_callback(const char *p_text, int p_cursor); + static EM_BOOL mousemove_callback(int p_event_type, const EmscriptenMouseEvent *p_event, void *p_user_data); static EM_BOOL mouse_button_callback(int p_event_type, const EmscriptenMouseEvent *p_event, void *p_user_data); @@ -135,6 +137,9 @@ public: int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; + void virtual_keyboard_hide() override; + // windows Vector<DisplayServer::WindowID> get_window_list() const override; WindowID get_window_at_screen_position(const Point2i &p_position) const override; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 46d0458ca1..1e89e144cc 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -297,6 +297,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re } Dictionary config; config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy"); + config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard"); config["gdnativeLibs"] = libs; config["executable"] = p_name; config["args"] = args; @@ -352,6 +353,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false)); } String EditorExportPlatformJavaScript::get_name() const { diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h index 5aa8677a54..4448a35670 100644 --- a/platform/javascript/godot_js.h +++ b/platform/javascript/godot_js.h @@ -92,7 +92,14 @@ extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int3 extern void godot_js_display_notification_cb(void (*p_callback)(int p_notification), int p_enter, int p_exit, int p_in, int p_out); extern void godot_js_display_paste_cb(void (*p_callback)(const char *p_text)); extern void godot_js_display_drop_files_cb(void (*p_callback)(char **p_filev, int p_filec)); -extern void godot_js_display_setup_canvas(int p_width, int p_height, int p_fullscreen); +extern void godot_js_display_setup_canvas(int p_width, int p_height, int p_fullscreen, int p_hidpi); + +// Display Virtual Keyboard +extern int godot_js_display_vk_available(); +extern void godot_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor)); +extern void godot_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end); +extern void godot_js_display_vk_hide(); + #ifdef __cplusplus } #endif diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js index 82ff273ecf..6072782875 100644 --- a/platform/javascript/js/engine/config.js +++ b/platform/javascript/js/engine/config.js @@ -91,12 +91,25 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- */ args: [], /** + * When enabled, this will turn on experimental virtual keyboard support on mobile. + * + * @memberof EngineConfig + * @type {boolean} + * @default + */ + experimentalVK: false, + /** * @ignore * @type {Array.<string>} */ persistentPaths: ['/userfs'], /** * @ignore + * @type {boolean} + */ + persistentDrops: false, + /** + * @ignore * @type {Array.<string>} */ gdnativeLibs: [], @@ -223,6 +236,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- this.locale = parse('locale', this.locale); this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy); this.persistentPaths = parse('persistentPaths', this.persistentPaths); + this.persistentDrops = parse('persistentDrops', this.persistentDrops); + this.experimentalVK = parse('experimentalVK', this.experimentalVK); this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs); this.fileSizes = parse('fileSizes', this.fileSizes); this.args = parse('args', this.args); @@ -307,6 +322,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- 'canvas': this.canvas, 'canvasResizePolicy': this.canvasResizePolicy, 'locale': locale, + 'persistentDrops': this.persistentDrops, + 'virtualKeyboard': this.experimentalVK, 'onExecute': this.onExecute, 'onExit': function (p_code) { cleanup(); // We always need to call the cleanup callback to free memory. diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index c72b6b3691..99aa4793d9 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -192,33 +192,45 @@ const GodotDisplayDragDrop = { GodotDisplayDragDrop.promises = []; GodotDisplayDragDrop.pending_files = []; callback(drops); - const dirs = [DROP.substr(0, DROP.length - 1)]; - // Remove temporary files - files.forEach(function (file) { - FS.unlink(file); - let dir = file.replace(DROP, ''); - let idx = dir.lastIndexOf('/'); - while (idx > 0) { - dir = dir.substr(0, idx); - if (dirs.indexOf(DROP + dir) === -1) { - dirs.push(DROP + dir); - } - idx = dir.lastIndexOf('/'); - } - }); - // Remove dirs. - dirs.sort(function (a, b) { - const al = (a.match(/\//g) || []).length; - const bl = (b.match(/\//g) || []).length; - if (al > bl) { - return -1; - } else if (al < bl) { - return 1; + if (GodotConfig.persistent_drops) { + // Delay removal at exit. + GodotOS.atexit(function (resolve, reject) { + GodotDisplayDragDrop.remove_drop(files, DROP); + resolve(); + }); + } else { + GodotDisplayDragDrop.remove_drop(files, DROP); + } + }); + }, + + remove_drop: function (files, drop_path) { + const dirs = [drop_path.substr(0, drop_path.length - 1)]; + // Remove temporary files + files.forEach(function (file) { + FS.unlink(file); + let dir = file.replace(drop_path, ''); + let idx = dir.lastIndexOf('/'); + while (idx > 0) { + dir = dir.substr(0, idx); + if (dirs.indexOf(drop_path + dir) === -1) { + dirs.push(drop_path + dir); } - return 0; - }).forEach(function (dir) { - FS.rmdir(dir); - }); + idx = dir.lastIndexOf('/'); + } + }); + // Remove dirs. + dirs.sort(function (a, b) { + const al = (a.match(/\//g) || []).length; + const bl = (b.match(/\//g) || []).length; + if (al > bl) { + return -1; + } else if (al < bl) { + return 1; + } + return 0; + }).forEach(function (dir) { + FS.rmdir(dir); }); }, @@ -231,6 +243,105 @@ const GodotDisplayDragDrop = { }; mergeInto(LibraryManager.library, GodotDisplayDragDrop); +const GodotDisplayVK = { + + $GodotDisplayVK__deps: ['$GodotRuntime', '$GodotConfig', '$GodotDisplayListeners'], + $GodotDisplayVK__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayVK.clear(); resolve(); });', + $GodotDisplayVK: { + textinput: null, + textarea: null, + + available: function () { + return GodotConfig.virtual_keyboard && 'ontouchstart' in window; + }, + + init: function (input_cb) { + function create(what) { + const elem = document.createElement(what); + elem.style.display = 'none'; + elem.style.position = 'absolute'; + elem.style.zIndex = '-1'; + elem.style.background = 'transparent'; + elem.style.padding = '0px'; + elem.style.margin = '0px'; + elem.style.overflow = 'hidden'; + elem.style.width = '0px'; + elem.style.height = '0px'; + elem.style.border = '0px'; + elem.style.outline = 'none'; + elem.readonly = true; + elem.disabled = true; + GodotDisplayListeners.add(elem, 'input', function (evt) { + const c_str = GodotRuntime.allocString(elem.value); + input_cb(c_str, elem.selectionEnd); + GodotRuntime.free(c_str); + }, false); + GodotDisplayListeners.add(elem, 'blur', function (evt) { + elem.style.display = 'none'; + elem.readonly = true; + elem.disabled = true; + }, false); + GodotConfig.canvas.insertAdjacentElement('beforebegin', elem); + return elem; + } + GodotDisplayVK.textinput = create('input'); + GodotDisplayVK.textarea = create('textarea'); + GodotDisplayVK.updateSize(); + }, + show: function (text, multiline, start, end) { + if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) { + return; + } + if (GodotDisplayVK.textinput.style.display !== '' || GodotDisplayVK.textarea.style.display !== '') { + GodotDisplayVK.hide(); + } + GodotDisplayVK.updateSize(); + const elem = multiline ? GodotDisplayVK.textarea : GodotDisplayVK.textinput; + elem.readonly = false; + elem.disabled = false; + elem.value = text; + elem.style.display = 'block'; + elem.focus(); + elem.setSelectionRange(start, end); + }, + hide: function () { + if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) { + return; + } + [GodotDisplayVK.textinput, GodotDisplayVK.textarea].forEach(function (elem) { + elem.blur(); + elem.style.display = 'none'; + elem.value = ''; + }); + }, + updateSize: function () { + if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) { + return; + } + const rect = GodotConfig.canvas.getBoundingClientRect(); + function update(elem) { + elem.style.left = `${rect.left}px`; + elem.style.top = `${rect.top}px`; + elem.style.width = `${rect.width}px`; + elem.style.height = `${rect.height}px`; + } + update(GodotDisplayVK.textinput); + update(GodotDisplayVK.textarea); + }, + clear: function () { + if (GodotDisplayVK.textinput) { + GodotDisplayVK.textinput.remove(); + GodotDisplayVK.textinput = null; + } + if (GodotDisplayVK.textarea) { + GodotDisplayVK.textarea.remove(); + GodotDisplayVK.textarea = null; + } + }, + }, +}; +mergeInto(LibraryManager.library, GodotDisplayVK); + /* * Display server cursor helper. * Keeps track of cursor status and custom shapes. @@ -400,6 +511,10 @@ const GodotDisplayScreen = { $GodotDisplayScreen__deps: ['$GodotConfig', '$GodotOS', '$GL', 'emscripten_webgl_get_current_context'], $GodotDisplayScreen: { desired_size: [0, 0], + hidpi: true, + getPixelRatio: function () { + return GodotDisplayScreen.hidpi ? window.devicePixelRatio || 1 : 1; + }, isFullscreen: function () { const elem = document.fullscreenElement || document.mozFullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement; @@ -477,7 +592,7 @@ const GodotDisplayScreen = { } return 0; } - const scale = window.devicePixelRatio || 1; + const scale = GodotDisplayScreen.getPixelRatio(); if (isFullscreen || wantsFullWindow) { // We need to match screen size. width = window.innerWidth * scale; @@ -507,7 +622,7 @@ mergeInto(LibraryManager.library, GodotDisplayScreen); * Exposes all the functions needed by DisplayServer implementation. */ const GodotDisplay = { - $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads', '$GodotDisplayScreen'], + $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads', '$GodotDisplayScreen', '$GodotDisplayVK'], $GodotDisplay: { window_icon: '', findDPI: function () { @@ -555,7 +670,7 @@ const GodotDisplay = { godot_js_display_pixel_ratio_get__sig: 'f', godot_js_display_pixel_ratio_get: function () { - return window.devicePixelRatio || 1; + return GodotDisplayScreen.getPixelRatio(); }, godot_js_display_fullscreen_request__sig: 'i', @@ -576,12 +691,16 @@ const GodotDisplay = { godot_js_display_size_update__sig: 'i', godot_js_display_size_update: function () { - return GodotDisplayScreen.updateSize(); + const updated = GodotDisplayScreen.updateSize(); + if (updated) { + GodotDisplayVK.updateSize(); + } + return updated; }, godot_js_display_screen_size_get__sig: 'vii', godot_js_display_screen_size_get: function (width, height) { - const scale = window.devicePixelRatio || 1; + const scale = GodotDisplayScreen.getPixelRatio(); GodotRuntime.setHeapValue(width, window.screen.width * scale, 'i32'); GodotRuntime.setHeapValue(height, window.screen.height * scale, 'i32'); }, @@ -776,8 +895,8 @@ const GodotDisplay = { GodotDisplayListeners.add(canvas, 'drop', GodotDisplayDragDrop.handler(dropFiles)); }, - godot_js_display_setup_canvas__sig: 'viii', - godot_js_display_setup_canvas: function (p_width, p_height, p_fullscreen) { + godot_js_display_setup_canvas__sig: 'viiii', + godot_js_display_setup_canvas: function (p_width, p_height, p_fullscreen, p_hidpi) { const canvas = GodotConfig.canvas; GodotDisplayListeners.add(canvas, 'contextmenu', function (ev) { ev.preventDefault(); @@ -786,6 +905,7 @@ const GodotDisplay = { alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert ev.preventDefault(); }, false); + GodotDisplayScreen.hidpi = !!p_hidpi; switch (GodotConfig.canvas_resize_policy) { case 0: // None GodotDisplayScreen.desired_size = [canvas.width, canvas.height]; @@ -800,12 +920,42 @@ const GodotDisplay = { canvas.style.left = 0; break; } + GodotDisplayScreen.updateSize(); if (p_fullscreen) { GodotDisplayScreen.requestFullscreen(); } }, /* + * Virtual Keyboard + */ + godot_js_display_vk_show__sig: 'viiii', + godot_js_display_vk_show: function (p_text, p_multiline, p_start, p_end) { + const text = GodotRuntime.parseString(p_text); + const start = p_start > 0 ? p_start : 0; + const end = p_end > 0 ? p_end : start; + GodotDisplayVK.show(text, p_multiline, start, end); + }, + + godot_js_display_vk_hide__sig: 'v', + godot_js_display_vk_hide: function () { + GodotDisplayVK.hide(); + }, + + godot_js_display_vk_available__sig: 'i', + godot_js_display_vk_available: function () { + return GodotDisplayVK.available(); + }, + + godot_js_display_vk_cb__sig: 'vi', + godot_js_display_vk_cb: function (p_input_cb) { + const input_cb = GodotRuntime.get_func(p_input_cb); + if (GodotDisplayVK.available()) { + GodotDisplayVK.init(input_cb); + } + }, + + /* * Gamepads */ godot_js_display_gamepad_cb__sig: 'vi', diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js index 0f189b013c..1d9f889bce 100644 --- a/platform/javascript/js/libs/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -59,6 +59,8 @@ const GodotConfig = { canvas: null, locale: 'en', canvas_resize_policy: 2, // Adaptive + virtual_keyboard: false, + persistent_drops: false, on_execute: null, on_exit: null, @@ -66,6 +68,8 @@ const GodotConfig = { GodotConfig.canvas_resize_policy = p_opts['canvasResizePolicy']; GodotConfig.canvas = p_opts['canvas']; GodotConfig.locale = p_opts['locale'] || GodotConfig.locale; + GodotConfig.virtual_keyboard = p_opts['virtualKeyboard']; + GodotConfig.persistent_drops = !!p_opts['persistentDrops']; GodotConfig.on_execute = p_opts['onExecute']; GodotConfig.on_exit = p_opts['onExit']; }, @@ -77,6 +81,8 @@ const GodotConfig = { GodotConfig.canvas = null; GodotConfig.locale = 'en'; GodotConfig.canvas_resize_policy = 2; + GodotConfig.virtual_keyboard = false; + GodotConfig.persistent_drops = false; GodotConfig.on_execute = null; GodotConfig.on_exit = null; }, diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp index e24e466f88..e2d507eddd 100644 --- a/platform/windows/crash_handler_windows.cpp +++ b/platform/windows/crash_handler_windows.cpp @@ -36,7 +36,7 @@ #ifdef CRASH_HANDLER_EXCEPTION -// Backtrace code code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app +// Backtrace code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app #include <algorithm> #include <iterator> diff --git a/platform/windows/detect.py b/platform/windows/detect.py index f26dea8d35..0b2145a92b 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -72,6 +72,7 @@ def get_opts(): BoolVariable("use_llvm", "Use the LLVM compiler", False), BoolVariable("use_thinlto", "Use ThinLTO", False), BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True), + BoolVariable("use_asan", "Use address sanitizer (ASAN)", False), ] @@ -306,6 +307,12 @@ def configure_msvc(env, manual_msvc_config): env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")]) env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")]) + # Sanitizers + if env["use_asan"]: + env.extra_suffix += ".s" + env.Append(LINKFLAGS=["/INFERASANLIBS"]) + env.Append(CCFLAGS=["/fsanitize=address"]) + # Incremental linking fix env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"] env["BUILDERS"]["Program"] = methods.precious_program diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index b9b78f7bd4..e29faf4f3c 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1253,12 +1253,12 @@ void DisplayServerWindows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTra HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap); HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap); - // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap + // Assign the monochrome AND mask bitmap pixels so that the pixels of the source bitmap // with 'clrTransparent' will be white pixels of the monochrome bitmap SetBkColor(hMainDC, clrTransparent); BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY); - // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap + // Assign the color XOR mask bitmap pixels so that the pixels of the source bitmap // with 'clrTransparent' will be black and rest the pixels same as corresponding // pixels of the source bitmap SetBkColor(hXorMaskDC, RGB(0, 0, 0)); @@ -2305,7 +2305,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_alt(alt_mem); if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { - // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not update recently. + // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently. if (windows[window_id].last_pressure_update < 10) { windows[window_id].last_pressure_update++; } else { diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index f46a0dbe2e..b8679a87fe 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -110,12 +110,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) { if (GetRawInputDeviceList(nullptr, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) { return false; } - dev_list = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count); - if (!dev_list) - return false; + dev_list = (PRAWINPUTDEVICELIST)memalloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count); + ERR_FAIL_NULL_V_MSG(dev_list, false, "Out of memory."); if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) { - free(dev_list); + memfree(dev_list); return false; } for (unsigned int i = 0; i < dev_list_count; i++) { @@ -130,11 +129,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) { (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == (LONG)p_guid->Data1) && (GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) && (strstr(dev_name, "IG_") != nullptr)) { - free(dev_list); + memfree(dev_list); return true; } } - free(dev_list); + memfree(dev_list); return false; } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3280a36e9b..1e9cdd241d 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -334,7 +334,7 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { } // Bias value returned by GetTimeZoneInformation is inverted of what we expect - // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 + // For example, on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 ret.bias = -info.Bias; return ret; } diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp index 56b620a6d9..c1f3827d15 100644 --- a/platform/windows/windows_terminal_logger.cpp +++ b/platform/windows/windows_terminal_logger.cpp @@ -53,7 +53,8 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er if (wlen < 0) return; - wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t)); + wchar_t *wbuf = (wchar_t *)memalloc((len + 1) * sizeof(wchar_t)); + ERR_FAIL_NULL_MSG(wbuf, "Out of memory."); MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen); wbuf[wlen] = 0; @@ -62,7 +63,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er else wprintf(L"%ls", wbuf); - free(wbuf); + memfree(wbuf); #ifdef DEBUG_ENABLED fflush(stdout); diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 892ccadfda..c478f03356 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -375,7 +375,7 @@ void LineBuilder::build() { } if (intersection_result != SEGMENT_INTERSECT) { - // In this case the joint is too corrputed to be re-used, + // In this case the joint is too corrupted to be re-used, // start again the strip with fallback points strip_begin(pos_up0, pos_down0, color1, uvx1); } @@ -485,7 +485,7 @@ void LineBuilder::strip_add_tri(Vector2 up, Orientation orientation) { if (texture_mode != Line2D::LINE_TEXTURE_NONE) { // UVs are just one slice of the texture all along - // (otherwise we can't share the bottom vertice) + // (otherwise we can't share the bottom vertex) uvs.push_back(uvs[_last_index[opposite_orientation]]); } @@ -520,7 +520,7 @@ void LineBuilder::strip_add_arc(Vector2 center, float angle_delta, Orientation o strip_add_tri(rpos, orientation); } - // Last arc vertice + // Last arc vertex rpos = center + Vector2(Math::cos(end_angle), Math::sin(end_angle)) * radius; strip_add_tri(rpos, orientation); } @@ -569,7 +569,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col } } - // Last arc vertice + // Last arc vertex Vector2 sc = Vector2(Math::cos(end_angle), Math::sin(end_angle)); rpos = center + sc * radius; vertices.push_back(rpos); diff --git a/scene/2d/navigation_2d.cpp b/scene/2d/navigation_2d.cpp deleted file mode 100644 index bec5ee7984..0000000000 --- a/scene/2d/navigation_2d.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************/ -/* navigation_2d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation_2d.h" -#include "servers/navigation_server_2d.h" - -void Navigation2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_rid"), &Navigation2D::get_rid); - - ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation2D::get_simple_path, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation2D::get_closest_point); - ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation2D::get_closest_point_owner); - - ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation2D::set_cell_size); - ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation2D::get_cell_size); - - ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation2D::set_edge_connection_margin); - ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation2D::get_edge_connection_margin); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); -} - -void Navigation2D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - NavigationServer2D::get_singleton()->map_set_active(map, true); - } break; - case NOTIFICATION_EXIT_TREE: { - NavigationServer2D::get_singleton()->map_set_active(map, false); - } break; - } -} - -void Navigation2D::set_cell_size(float p_cell_size) { - cell_size = p_cell_size; - NavigationServer2D::get_singleton()->map_set_cell_size(map, cell_size); -} - -void Navigation2D::set_edge_connection_margin(float p_edge_connection_margin) { - edge_connection_margin = p_edge_connection_margin; - NavigationServer2D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); -} - -Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize) const { - return NavigationServer2D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); -} - -Vector2 Navigation2D::get_closest_point(const Vector2 &p_point) const { - return NavigationServer2D::get_singleton()->map_get_closest_point(map, p_point); -} - -RID Navigation2D::get_closest_point_owner(const Vector2 &p_point) const { - return NavigationServer2D::get_singleton()->map_get_closest_point_owner(map, p_point); -} - -Navigation2D::Navigation2D() { - map = NavigationServer2D::get_singleton()->map_create(); - set_cell_size(10); // Ten pixels - set_edge_connection_margin(100); -} - -Navigation2D::~Navigation2D() { - NavigationServer2D::get_singleton()->free(map); -} diff --git a/scene/2d/navigation_2d.h b/scene/2d/navigation_2d.h deleted file mode 100644 index 12847e52ac..0000000000 --- a/scene/2d/navigation_2d.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************/ -/* navigation_2d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_2D_H -#define NAVIGATION_2D_H - -#include "scene/2d/navigation_region_2d.h" -#include "scene/2d/node_2d.h" - -class Navigation2D : public Node2D { - GDCLASS(Navigation2D, Node2D); - - RID map; - real_t cell_size; - real_t edge_connection_margin; - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - RID get_rid() const { - return map; - } - - void set_cell_size(float p_cell_size); - float get_cell_size() const { - return cell_size; - } - - void set_edge_connection_margin(float p_edge_connection_margin); - float get_edge_connection_margin() const { - return edge_connection_margin; - } - - Vector<Vector2> get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize = true) const; - Vector2 get_closest_point(const Vector2 &p_point) const; - RID get_closest_point_owner(const Vector2 &p_point) const; - - Navigation2D(); - ~Navigation2D(); -}; - -#endif // NAVIGATION_2D_H diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 534e31b1f2..064fcc91a4 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -32,7 +32,6 @@ #include "core/config/engine.h" #include "core/math/geometry_2d.h" -#include "scene/2d/navigation_2d.h" #include "servers/navigation_server_2d.h" void NavigationAgent2D::_bind_methods() { @@ -42,9 +41,6 @@ void NavigationAgent2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent2D::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent2D::get_radius); - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent2D::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent2D::get_navigation_node); - ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent2D::set_neighbor_dist); ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent2D::get_neighbor_dist); @@ -95,27 +91,10 @@ void NavigationAgent2D::_notification(int p_what) { NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); - // Search the navigation node and set it - { - Navigation2D *nav = nullptr; - Node *p = get_parent(); - while (p != nullptr) { - nav = Object::cast_to<Navigation2D>(p); - if (nav != nullptr) { - p = nullptr; - } else { - p = p->get_parent(); - } - } - - set_navigation(nav); - } - set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { agent_parent = nullptr; - set_navigation(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -146,23 +125,13 @@ NavigationAgent2D::~NavigationAgent2D() { agent = RID(); // Pointless } -void NavigationAgent2D::set_navigation(Navigation2D *p_nav) { - if (navigation == p_nav) { - return; // Pointless - } - - navigation = p_nav; - NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); -} - -void NavigationAgent2D::set_navigation_node(Node *p_nav) { - Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav); - ERR_FAIL_COND(nav == nullptr); - set_navigation(nav); +void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) { + navigable_layers = p_layers; + update_navigation(); } -Node *NavigationAgent2D::get_navigation_node() const { - return Object::cast_to<Node>(navigation); +uint32_t NavigationAgent2D::get_navigable_layers() const { + return navigable_layers; } void NavigationAgent2D::set_target_desired_distance(real_t p_dd) { @@ -287,7 +256,7 @@ void NavigationAgent2D::update_navigation() { if (agent_parent == nullptr) { return; } - if (navigation == nullptr) { + if (!agent_parent->is_inside_tree()) { return; } if (update_frame_id == Engine::get_singleton()->get_physics_frames()) { @@ -319,7 +288,7 @@ void NavigationAgent2D::update_navigation() { } if (reload_path) { - navigation_path = NavigationServer2D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers); navigation_finished = false; nav_path_index = 0; emit_signal("path_changed"); diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 6b7da4a5f2..153ede8cec 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -35,16 +35,16 @@ #include "scene/main/node.h" class Node2D; -class Navigation2D; class NavigationAgent2D : public Node { GDCLASS(NavigationAgent2D, Node); Node2D *agent_parent = nullptr; - Navigation2D *navigation = nullptr; RID agent; + uint32_t navigable_layers = 1; + real_t target_desired_distance = 1.0; real_t radius; real_t neighbor_dist; @@ -74,18 +74,13 @@ public: NavigationAgent2D(); virtual ~NavigationAgent2D(); - void set_navigation(Navigation2D *p_nav); - const Navigation2D *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - RID get_rid() const { return agent; } + void set_navigable_layers(uint32_t p_layers); + uint32_t get_navigable_layers() const; + void set_target_desired_distance(real_t p_dd); real_t get_target_desired_distance() const { return target_desired_distance; diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index 7e1aefe5e2..965e2b6dc1 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -31,48 +31,31 @@ #include "navigation_obstacle_2d.h" #include "scene/2d/collision_shape_2d.h" -#include "scene/2d/navigation_2d.h" #include "scene/2d/physics_body_2d.h" #include "servers/navigation_server_2d.h" void NavigationObstacle2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node); } void NavigationObstacle2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - update_agent_shape(); - - // Search the navigation node and set it - { - Navigation2D *nav = nullptr; - Node *p = get_parent(); - while (p != nullptr) { - nav = Object::cast_to<Navigation2D>(p); - if (nav != nullptr) { - p = nullptr; - } else { - p = p->get_parent(); - } - } - - set_navigation(nav); - } - set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - set_navigation(nullptr); set_physics_process_internal(false); } break; + case NOTIFICATION_PARENTED: { + parent_node2d = Object::cast_to<Node2D>(get_parent()); + update_agent_shape(); + } break; + case NOTIFICATION_UNPARENTED: { + parent_node2d = nullptr; + } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - Node2D *node = Object::cast_to<Node2D>(get_parent()); - if (node) { - NavigationServer2D::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin()); + if (parent_node2d) { + NavigationServer2D::get_singleton()->agent_set_position(agent, parent_node2d->get_global_transform().get_origin()); } - } break; } } @@ -86,25 +69,6 @@ NavigationObstacle2D::~NavigationObstacle2D() { agent = RID(); // Pointless } -void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) { - if (navigation == p_nav) { - return; // Pointless - } - - navigation = p_nav; - NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); -} - -void NavigationObstacle2D::set_navigation_node(Node *p_nav) { - Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav); - ERR_FAIL_COND(nav == nullptr); - set_navigation(nav); -} - -Node *NavigationObstacle2D::get_navigation_node() const { - return Object::cast_to<Node>(navigation); -} - String NavigationObstacle2D::get_configuration_warning() const { String warning = Node::get_configuration_warning(); @@ -119,40 +83,37 @@ String NavigationObstacle2D::get_configuration_warning() const { } void NavigationObstacle2D::update_agent_shape() { - Node *node = get_parent(); - - // Estimate the radius of this physics body - real_t radius = 0.0; - for (int i(0); i < node->get_child_count(); i++) { - // For each collision shape - CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(node->get_child(i)); - if (cs) { - // Take the distance between the Body center to the shape center - real_t r = cs->get_transform().get_origin().length(); - if (cs->get_shape().is_valid()) { - // and add the enclosing shape radius - r += cs->get_shape()->get_enclosing_radius(); + if (parent_node2d) { + // Estimate the radius of this physics body + real_t radius = 0.0; + for (int i(0); i < parent_node2d->get_child_count(); i++) { + // For each collision shape + CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i)); + if (cs) { + // Take the distance between the Body center to the shape center + real_t r = cs->get_transform().get_origin().length(); + if (cs->get_shape().is_valid()) { + // and add the enclosing shape radius + r += cs->get_shape()->get_enclosing_radius(); + } + Size2 s = cs->get_global_transform().get_scale(); + r *= MAX(s.x, s.y); + // Takes the biggest radius + radius = MAX(radius, r); } - Size2 s = cs->get_global_transform().get_scale(); - r *= MAX(s.x, s.y); - // Takes the biggest radius - radius = MAX(radius, r); } - } - Node2D *node_2d = Object::cast_to<Node2D>(node); - if (node_2d) { - Vector2 s = node_2d->get_global_transform().get_scale(); + Vector2 s = parent_node2d->get_global_transform().get_scale(); radius *= MAX(s.x, s.y); - } - if (radius == 0.0) { - radius = 1.0; // Never a 0 radius - } + if (radius == 0.0) { + radius = 1.0; // Never a 0 radius + } - // Initialize the Agent as an object - NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); - NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0); - NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0); - NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); - NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0); + // Initialize the Agent as an object + NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); + NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0); + } } diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 421f8ca7cd..135ca4651e 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -31,15 +31,13 @@ #ifndef NAVIGATION_OBSTACLE_2D_H #define NAVIGATION_OBSTACLE_2D_H +#include "scene/2d/node_2d.h" #include "scene/main/node.h" -class Navigation2D; - class NavigationObstacle2D : public Node { GDCLASS(NavigationObstacle2D, Node); - Navigation2D *navigation = nullptr; - + Node2D *parent_node2d = nullptr; RID agent; protected: @@ -50,14 +48,6 @@ public: NavigationObstacle2D(); virtual ~NavigationObstacle2D(); - void set_navigation(Navigation2D *p_nav); - const Navigation2D *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - RID get_rid() const { return agent; } diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index b02cdf12ad..794993f892 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -34,7 +34,6 @@ #include "core/core_string_names.h" #include "core/math/geometry_2d.h" #include "core/os/mutex.h" -#include "navigation_2d.h" #include "servers/navigation_server_2d.h" #include "thirdparty/misc/polypartition.h" @@ -366,9 +365,7 @@ void NavigationRegion2D::set_enabled(bool p_enabled) { if (!enabled) { NavigationServer2D::get_singleton()->region_set_map(region, RID()); } else { - if (navigation) { - NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); - } + NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); } if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) { @@ -380,6 +377,14 @@ bool NavigationRegion2D::is_enabled() const { return enabled; } +void NavigationRegion2D::set_layers(uint32_t p_layers) { + NavigationServer2D::get_singleton()->region_set_layers(region, p_layers); +} + +uint32_t NavigationRegion2D::get_layers() const { + return NavigationServer2D::get_singleton()->region_get_layers(region); +} + ///////////////////////////// #ifdef TOOLS_ENABLED Rect2 NavigationRegion2D::_edit_get_rect() const { @@ -394,29 +399,15 @@ bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, doubl void NavigationRegion2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - Node2D *c = this; - while (c) { - navigation = Object::cast_to<Navigation2D>(c); - if (navigation) { - if (enabled) { - NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); - } - break; - } - - c = Object::cast_to<Node2D>(c->get_parent()); + if (enabled) { + NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); } - } break; case NOTIFICATION_TRANSFORM_CHANGED: { NavigationServer2D::get_singleton()->region_set_transform(region, get_global_transform()); - } break; case NOTIFICATION_EXIT_TREE: { - if (navigation) { - NavigationServer2D::get_singleton()->region_set_map(region, RID()); - } - navigation = nullptr; + NavigationServer2D::get_singleton()->region_set_map(region, RID()); } break; case NOTIFICATION_DRAW: { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) { @@ -507,18 +498,8 @@ String NavigationRegion2D::get_configuration_warning() const { } warning += TTR("A NavigationPolygon resource must be set or created for this node to work. Please set a property or draw a polygon."); } - const Node2D *c = this; - while (c) { - if (Object::cast_to<Navigation2D>(c)) { - return warning; - } - c = Object::cast_to<Node2D>(c->get_parent()); - } - if (!warning.is_empty()) { - warning += "\n\n"; - } - return warning + TTR("NavigationRegion2D must be a child or grandchild to a Navigation2D node. It only provides navigation data."); + return warning; } void NavigationRegion2D::_bind_methods() { @@ -528,10 +509,14 @@ void NavigationRegion2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled); + ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion2D::set_layers); + ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion2D::get_layers); + ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_layers", "get_layers"); } NavigationRegion2D::NavigationRegion2D() { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 0b9a258a25..7b471bd555 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -91,14 +91,11 @@ public: ~NavigationPolygon() {} }; -class Navigation2D; - class NavigationRegion2D : public Node2D { GDCLASS(NavigationRegion2D, Node2D); bool enabled = true; RID region; - Navigation2D *navigation = nullptr; Ref<NavigationPolygon> navpoly; void _navpoly_changed(); @@ -116,6 +113,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly); Ref<NavigationPolygon> get_navigation_polygon() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 96d8fb609b..a615d96687 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -411,13 +411,13 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { } } - //process remotions + //process removals for (int i = 0; i < toremove_count; i++) { _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } - //process aditions + //process additions for (int i = 0; i < toadd_count; i++) { _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 5728230a8c..e028b5f5b7 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -184,7 +184,7 @@ void Skeleton2D::_update_bone_setup() { bone_setup_dirty = false; RS::get_singleton()->skeleton_allocate_data(skeleton, bones.size(), true); - bones.sort(); //sorty so they are always in the same order/index + bones.sort(); //sorting so that they are always in the same order/index for (int i = 0; i < bones.size(); i++) { bones.write[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index d868ebae25..81a5b0b28c 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -48,16 +48,6 @@ int TileMap::_get_quadrant_size() const { void TileMap::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - Node2D *c = this; - while (c) { - navigation = Object::cast_to<Navigation2D>(c); - if (navigation) { - break; - } - - c = Object::cast_to<Node2D>(c->get_parent()); - } - if (use_parent) { _clear_quadrants(); collision_parent = Object::cast_to<CollisionObject2D>(get_parent()); @@ -77,12 +67,10 @@ void TileMap::_notification(int p_what) { _update_quadrant_space(RID()); for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - if (navigation) { - for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID()); - } - q.navpoly_ids.clear(); + for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { + NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID()); } + q.navpoly_ids.clear(); if (collision_parent) { collision_parent->remove_shape_owner(q.shape_owner_id); @@ -96,8 +84,6 @@ void TileMap::_notification(int p_what) { } collision_parent = nullptr; - navigation = nullptr; - } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -135,11 +121,6 @@ void TileMap::_update_quadrant_transform() { local_transform = get_transform(); } - Transform2D nav_rel; - if (navigation) { - nav_rel = get_relative_transform_to_parent(navigation); - } - for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); Transform2D xform; @@ -150,9 +131,9 @@ void TileMap::_update_quadrant_transform() { PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); } - if (navigation) { + if (bake_navigation) { for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - NavigationServer2D::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform); + NavigationServer2D::get_singleton()->region_set_transform(F->get().region, F->get().xform); } } @@ -315,11 +296,6 @@ void TileMap::update_dirty_quadrants() { RenderingServer *vs = RenderingServer::get_singleton(); PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); Vector2 tofs = get_cell_draw_offset(); - Transform2D nav_rel; - if (navigation) { - nav_rel = get_relative_transform_to_parent(navigation); - } - Vector2 qofs; SceneTree *st = SceneTree::get_singleton(); @@ -352,12 +328,10 @@ void TileMap::update_dirty_quadrants() { } int shape_idx = 0; - if (navigation) { - for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); - } - q.navpoly_ids.clear(); + for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { + NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); } + q.navpoly_ids.clear(); for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) { RS::get_singleton()->free(E->get().id); @@ -579,7 +553,7 @@ void TileMap::update_dirty_quadrants() { vs->canvas_item_add_set_transform(debug_canvas_item, Transform2D()); } - if (navigation) { + if (bake_navigation) { Ref<NavigationPolygon> navpoly; Vector2 npoly_ofs; if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) { @@ -596,8 +570,8 @@ void TileMap::update_dirty_quadrants() { _fix_cell_transform(xform, c, npoly_ofs, s); RID region = NavigationServer2D::get_singleton()->region_create(); - NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); - NavigationServer2D::get_singleton()->region_set_transform(region, nav_rel * xform); + NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); + NavigationServer2D::get_singleton()->region_set_transform(region, xform); NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly); Quadrant::NavPoly np; @@ -787,12 +761,10 @@ void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) { dirty_quadrant_list.remove(&q.dirty_list); } - if (navigation) { - for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); - } - q.navpoly_ids.clear(); + for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { + NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); } + q.navpoly_ids.clear(); for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) { RS::get_singleton()->free(E->get().id); @@ -1360,6 +1332,17 @@ float TileMap::get_collision_bounce() const { return bounce; } +void TileMap::set_bake_navigation(bool p_bake_navigation) { + bake_navigation = p_bake_navigation; + for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) { + _make_quadrant_dirty(F); + } +} + +bool TileMap::is_baking_navigation() { + return bake_navigation; +} + uint32_t TileMap::get_collision_layer() const { return collision_layer; } @@ -1784,6 +1767,9 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_bounce", "value"), &TileMap::set_collision_bounce); ClassDB::bind_method(D_METHOD("get_collision_bounce"), &TileMap::get_collision_bounce); + ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &TileMap::set_bake_navigation); + ClassDB::bind_method(D_METHOD("is_baking_navigation"), &TileMap::is_baking_navigation); + ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &TileMap::set_occluder_light_mask); ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask); @@ -1842,6 +1828,9 @@ void TileMap::_bind_methods() { ADD_GROUP("Occluder", "occluder_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "occluder_light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask"); + ADD_GROUP("Navigation", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation"); + ADD_PROPERTY_DEFAULT("format", FORMAT_1); ADD_SIGNAL(MethodInfo("settings_changed")); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 3bf4587921..26c84a0bb9 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -33,7 +33,6 @@ #include "core/templates/self_list.h" #include "core/templates/vset.h" -#include "scene/2d/navigation_2d.h" #include "scene/2d/node_2d.h" #include "scene/resources/tile_set.h" @@ -78,7 +77,7 @@ private: bool use_parent = false; CollisionObject2D *collision_parent = nullptr; bool use_kinematic = false; - Navigation2D *navigation = nullptr; + bool bake_navigation = false; union PosKey { struct { @@ -295,6 +294,9 @@ public: void set_collision_bounce(float p_bounce); float get_collision_bounce() const; + void set_bake_navigation(bool p_bake_navigation); + bool is_baking_navigation(); + void set_mode(Mode p_mode); Mode get_mode() const; diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 23eda379be..749cf4ff9d 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -211,7 +211,7 @@ void Area3D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = Object::cast_to<Node>(obj); - if (!node) { //node may have been deleted in previous frame or at other legiminate point + if (!node) { //node may have been deleted in previous frame or at other legitimate point continue; } //ERR_CONTINUE(!node); @@ -240,7 +240,7 @@ void Area3D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = Object::cast_to<Node>(obj); - if (!node) { //node may have been deleted in previous frame or at other legiminate point + if (!node) { //node may have been deleted in previous frame or at other legitimate point continue; } //ERR_CONTINUE(!node); diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 402e2b8f40..95ffbe48c1 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -449,7 +449,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug // Failed to separate the tetrahedrons using planes - // this means Delaunay borked at some point. + // this means Delaunay broke at some point. // Luckily, because we are using tetrahedrons, we can resort to // less precise but still working ways to generate the separating plane // this will most likely look bad when interpolating, but at least it will not crash. @@ -511,7 +511,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const node.plane = best_plane; if (indices_under.size() == 0) { - //noting to do here + //nothing to do here node.under = BSPNode::EMPTY_LEAF; } else if (indices_under.size() == 1) { node.under = -(indices_under[0] + 1); @@ -520,7 +520,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const } if (indices_over.size() == 0) { - //noting to do here + //nothing to do here node.over = BSPNode::EMPTY_LEAF; } else if (indices_over.size() == 1) { node.over = -(indices_over[0] + 1); @@ -660,7 +660,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d } // create mesh data for insert - //get the base material textures, help compute altlas size and bounds + //get the base material textures, help compute atlas size and bounds for (int m_i = 0; m_i < meshes_found.size(); m_i++) { if (p_bake_step) { float p = (float)(m_i) / meshes_found.size(); @@ -974,7 +974,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { images.push_back(lightmapper->get_bake_texture(i)); } - //we assume they are all the same, so lets create a large one for saving + //we assume they are all the same, so let's create a large one for saving Ref<Image> large_image; large_image.instance(); diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index f0623c625e..cd8d02233b 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -102,7 +102,7 @@ void Camera3D::_update_camera() { void Camera3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { - // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD + // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD // and Spatial will handle it first, including clearing its reference to the Viewport, // therefore making it impossible to subclasses to access it viewport = get_viewport(); @@ -715,7 +715,7 @@ void ClippedCamera3D::_notification(int p_what) { Vector3 ray_from = parent_plane.project(cam_pos); - clip_offset = 0; //reset by defau;t + clip_offset = 0; //reset by default { //check if points changed Vector<Vector3> local_points = get_near_plane_points(); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 17a61b3e4d..e2cfc2ed87 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -348,7 +348,7 @@ void GPUParticles3D::_notification(int p_what) { } } - // Use internal process when emitting and one_shot are on so that when + // Use internal process when emitting and one_shot is on so that when // the shot ends the editor can properly update if (p_what == NOTIFICATION_INTERNAL_PROCESS) { if (one_shot && !is_emitting()) { diff --git a/scene/3d/navigation_3d.cpp b/scene/3d/navigation_3d.cpp deleted file mode 100644 index eaddec7601..0000000000 --- a/scene/3d/navigation_3d.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************/ -/* navigation_3d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation_3d.h" - -#include "servers/navigation_server_3d.h" - -Vector<Vector3> Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const { - return NavigationServer3D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); -} - -Vector3 Navigation3D::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const { - return NavigationServer3D::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision); -} - -Vector3 Navigation3D::get_closest_point(const Vector3 &p_point) const { - return NavigationServer3D::get_singleton()->map_get_closest_point(map, p_point); -} - -Vector3 Navigation3D::get_closest_point_normal(const Vector3 &p_point) const { - return NavigationServer3D::get_singleton()->map_get_closest_point_normal(map, p_point); -} - -RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const { - return NavigationServer3D::get_singleton()->map_get_closest_point_owner(map, p_point); -} - -void Navigation3D::set_up_vector(const Vector3 &p_up) { - up = p_up; - NavigationServer3D::get_singleton()->map_set_up(map, up); -} - -Vector3 Navigation3D::get_up_vector() const { - return up; -} - -void Navigation3D::set_cell_size(float p_cell_size) { - cell_size = p_cell_size; - NavigationServer3D::get_singleton()->map_set_cell_size(map, cell_size); -} - -void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) { - edge_connection_margin = p_edge_connection_margin; - NavigationServer3D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); -} - -void Navigation3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_rid"), &Navigation3D::get_rid); - - ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation3D::get_simple_path, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation3D::get_closest_point_to_segment, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation3D::get_closest_point); - ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation3D::get_closest_point_normal); - ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation3D::get_closest_point_owner); - - ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation3D::set_up_vector); - ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation3D::get_up_vector); - - ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation3D::set_cell_size); - ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation3D::get_cell_size); - - ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation3D::set_edge_connection_margin); - ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation3D::get_edge_connection_margin); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); -} - -void Navigation3D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - NavigationServer3D::get_singleton()->map_set_active(map, true); - } break; - case NOTIFICATION_EXIT_TREE: { - NavigationServer3D::get_singleton()->map_set_active(map, false); - } break; - } -} - -Navigation3D::Navigation3D() { - map = NavigationServer3D::get_singleton()->map_create(); - - set_cell_size(0.3); - set_edge_connection_margin(5.0); // Five meters, depends a lot on the agent's radius -} - -Navigation3D::~Navigation3D() { - NavigationServer3D::get_singleton()->free(map); -} diff --git a/scene/3d/navigation_3d.h b/scene/3d/navigation_3d.h deleted file mode 100644 index b89725a3f5..0000000000 --- a/scene/3d/navigation_3d.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* navigation_3d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_3D_H -#define NAVIGATION_3D_H - -#include "scene/3d/navigation_region_3d.h" -#include "scene/3d/node_3d.h" - -class Navigation3D : public Node3D { - GDCLASS(Navigation3D, Node3D); - - RID map; - - Vector3 up = Vector3(0, 1, 0); - real_t cell_size; - real_t edge_connection_margin; - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - RID get_rid() const { - return map; - } - - void set_up_vector(const Vector3 &p_up); - Vector3 get_up_vector() const; - - void set_cell_size(float p_cell_size); - float get_cell_size() const { - return cell_size; - } - - void set_edge_connection_margin(float p_edge_connection_margin); - float get_edge_connection_margin() const { - return edge_connection_margin; - } - - Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const; - Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const; - Vector3 get_closest_point(const Vector3 &p_point) const; - Vector3 get_closest_point_normal(const Vector3 &p_point) const; - RID get_closest_point_owner(const Vector3 &p_point) const; - - Navigation3D(); - ~Navigation3D(); -}; - -#endif // NAVIGATION_H diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 8917cc4664..21ca3d70dd 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -31,7 +31,6 @@ #include "navigation_agent_3d.h" #include "core/config/engine.h" -#include "scene/3d/navigation_3d.h" #include "servers/navigation_server_3d.h" void NavigationAgent3D::_bind_methods() { @@ -47,9 +46,6 @@ void NavigationAgent3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent3D::set_ignore_y); ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent3D::get_ignore_y); - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent3D::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent3D::get_navigation_node); - ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent3D::set_neighbor_dist); ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent3D::get_neighbor_dist); @@ -101,28 +97,10 @@ void NavigationAgent3D::_notification(int p_what) { agent_parent = Object::cast_to<Node3D>(get_parent()); NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); - - // Search the navigation node and set it - { - Navigation3D *nav = nullptr; - Node *p = get_parent(); - while (p != nullptr) { - nav = Object::cast_to<Navigation3D>(p); - if (nav != nullptr) { - p = nullptr; - } else { - p = p->get_parent(); - } - } - - set_navigation(nav); - } - set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { agent_parent = nullptr; - set_navigation(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -154,25 +132,6 @@ NavigationAgent3D::~NavigationAgent3D() { agent = RID(); // Pointless } -void NavigationAgent3D::set_navigation(Navigation3D *p_nav) { - if (navigation == p_nav) { - return; // Pointless - } - - navigation = p_nav; - NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); -} - -void NavigationAgent3D::set_navigation_node(Node *p_nav) { - Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav); - ERR_FAIL_COND(nav == nullptr); - set_navigation(nav); -} - -Node *NavigationAgent3D::get_navigation_node() const { - return Object::cast_to<Node>(navigation); -} - void NavigationAgent3D::set_target_desired_distance(real_t p_dd) { target_desired_distance = p_dd; } @@ -303,7 +262,7 @@ void NavigationAgent3D::update_navigation() { if (agent_parent == nullptr) { return; } - if (navigation == nullptr) { + if (!agent_parent->is_inside_tree()) { return; } if (update_frame_id == Engine::get_singleton()->get_physics_frames()) { @@ -337,7 +296,7 @@ void NavigationAgent3D::update_navigation() { } if (reload_path) { - navigation_path = NavigationServer3D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true); navigation_finished = false; nav_path_index = 0; emit_signal("path_changed"); diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index bd890a051b..22db889618 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -35,13 +35,11 @@ #include "scene/main/node.h" class Node3D; -class Navigation3D; class NavigationAgent3D : public Node { GDCLASS(NavigationAgent3D, Node); Node3D *agent_parent = nullptr; - Navigation3D *navigation = nullptr; RID agent; @@ -76,14 +74,6 @@ public: NavigationAgent3D(); virtual ~NavigationAgent3D(); - void set_navigation(Navigation3D *p_nav); - const Navigation3D *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - RID get_rid() const { return agent; } diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index 01bf7de913..df03bca4fd 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -31,55 +31,38 @@ #include "navigation_obstacle_3d.h" #include "scene/3d/collision_shape_3d.h" -#include "scene/3d/navigation_3d.h" #include "scene/3d/physics_body_3d.h" #include "servers/navigation_server_3d.h" void NavigationObstacle3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle3D::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle3D::get_navigation_node); } void NavigationObstacle3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - update_agent_shape(); - - // Search the navigation node and set it - { - Navigation3D *nav = nullptr; - Node *p = get_parent(); - while (p != nullptr) { - nav = Object::cast_to<Navigation3D>(p); - if (nav != nullptr) { - p = nullptr; - } else { - p = p->get_parent(); - } - } - - set_navigation(nav); - } - set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - set_navigation(nullptr); set_physics_process_internal(false); } break; + case NOTIFICATION_PARENTED: { + parent_node3d = Object::cast_to<Node3D>(get_parent()); + update_agent_shape(); + } break; + case NOTIFICATION_UNPARENTED: { + parent_node3d = nullptr; + } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - Node3D *spatial = Object::cast_to<Node3D>(get_parent()); - if (spatial) { - NavigationServer3D::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); - } - - PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent()); - if (rigid) { - Vector3 v = rigid->get_linear_velocity(); - NavigationServer3D::get_singleton()->agent_set_velocity(agent, v); - NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v); + if (parent_node3d) { + NavigationServer3D::get_singleton()->agent_set_position(agent, parent_node3d->get_global_transform().origin); + + PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent()); + if (rigid) { + Vector3 v = rigid->get_linear_velocity(); + NavigationServer3D::get_singleton()->agent_set_velocity(agent, v); + NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v); + } } - } break; } } @@ -93,29 +76,10 @@ NavigationObstacle3D::~NavigationObstacle3D() { agent = RID(); // Pointless } -void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) { - if (navigation == p_nav) { - return; // Pointless - } - - navigation = p_nav; - NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); -} - -void NavigationObstacle3D::set_navigation_node(Node *p_nav) { - Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav); - ERR_FAIL_COND(nav == nullptr); - set_navigation(nav); -} - -Node *NavigationObstacle3D::get_navigation_node() const { - return Object::cast_to<Node>(navigation); -} - String NavigationObstacle3D::get_configuration_warning() const { String warning = Node::get_configuration_warning(); - if (!Object::cast_to<Node3D>(get_parent())) { + if (!parent_node3d) { if (!warning.is_empty()) { warning += "\n\n"; } @@ -126,40 +90,38 @@ String NavigationObstacle3D::get_configuration_warning() const { } void NavigationObstacle3D::update_agent_shape() { - Node *node = get_parent(); - - // Estimate the radius of this physics body - real_t radius = 0.0; - for (int i(0); i < node->get_child_count(); i++) { - // For each collision shape - CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(node->get_child(i)); - if (cs) { - // Take the distance between the Body center to the shape center - real_t r = cs->get_transform().origin.length(); - if (cs->get_shape().is_valid()) { - // and add the enclosing shape radius - r += cs->get_shape()->get_enclosing_radius(); + if (parent_node3d) { + // Estimate the radius of this physics body + real_t radius = 0.0; + for (int i(0); i < parent_node3d->get_child_count(); i++) { + // For each collision shape + CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(parent_node3d->get_child(i)); + if (cs) { + // Take the distance between the Body center to the shape center + real_t r = cs->get_transform().origin.length(); + if (cs->get_shape().is_valid()) { + // and add the enclosing shape radius + r += cs->get_shape()->get_enclosing_radius(); + } + Vector3 s = cs->get_global_transform().basis.get_scale(); + r *= MAX(s.x, MAX(s.y, s.z)); + // Takes the biggest radius + radius = MAX(radius, r); } - Vector3 s = cs->get_global_transform().basis.get_scale(); - r *= MAX(s.x, MAX(s.y, s.z)); - // Takes the biggest radius - radius = MAX(radius, r); } - } - Node3D *spa = Object::cast_to<Node3D>(node); - if (spa) { - Vector3 s = spa->get_global_transform().basis.get_scale(); + + Vector3 s = parent_node3d->get_global_transform().basis.get_scale(); radius *= MAX(s.x, MAX(s.y, s.z)); - } - if (radius == 0.0) { - radius = 1.0; // Never a 0 radius - } + if (radius == 0.0) { + radius = 1.0; // Never a 0 radius + } - // Initialize the Agent as an object - NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); - NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0); - NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0); - NavigationServer3D::get_singleton()->agent_set_radius(agent, radius); - NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0); + // Initialize the Agent as an object + NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_radius(agent, radius); + NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0); + } } diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h index b8d05b8a87..b1bb53724a 100644 --- a/scene/3d/navigation_obstacle_3d.h +++ b/scene/3d/navigation_obstacle_3d.h @@ -31,15 +31,13 @@ #ifndef NAVIGATION_OBSTACLE_H #define NAVIGATION_OBSTACLE_H +#include "scene/3d/node_3d.h" #include "scene/main/node.h" -class Navigation3D; - class NavigationObstacle3D : public Node { GDCLASS(NavigationObstacle3D, Node); - Navigation3D *navigation = nullptr; - + Node3D *parent_node3d = nullptr; RID agent; protected: @@ -50,14 +48,6 @@ public: NavigationObstacle3D(); virtual ~NavigationObstacle3D(); - void set_navigation(Navigation3D *p_nav); - const Navigation3D *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - RID get_rid() const { return agent; } diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 19bde94222..3ca704e4b8 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -32,7 +32,6 @@ #include "core/os/thread.h" #include "mesh_instance_3d.h" -#include "navigation_3d.h" #include "servers/navigation_server_3d.h" void NavigationRegion3D::set_enabled(bool p_enabled) { @@ -48,9 +47,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) { if (!enabled) { NavigationServer3D::get_singleton()->region_set_map(region, RID()); } else { - if (navigation) { - NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); - } + NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); } if (debug_view) { @@ -69,22 +66,21 @@ bool NavigationRegion3D::is_enabled() const { return enabled; } +void NavigationRegion3D::set_layers(uint32_t p_layers) { + NavigationServer3D::get_singleton()->region_set_layers(region, p_layers); +} + +uint32_t NavigationRegion3D::get_layers() const { + return NavigationServer3D::get_singleton()->region_get_layers(region); +} + ///////////////////////////// void NavigationRegion3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - Node3D *c = this; - while (c) { - navigation = Object::cast_to<Navigation3D>(c); - if (navigation) { - if (enabled) { - NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); - } - break; - } - - c = c->get_parent_spatial(); + if (enabled) { + NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); } if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { @@ -105,15 +101,12 @@ void NavigationRegion3D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - if (navigation) { - NavigationServer3D::get_singleton()->region_set_map(region, RID()); - } + NavigationServer3D::get_singleton()->region_set_map(region, RID()); if (debug_view) { debug_view->queue_delete(); debug_view = nullptr; } - navigation = nullptr; } break; } } @@ -198,19 +191,7 @@ String NavigationRegion3D::get_configuration_warning() const { warning += TTR("A NavigationMesh resource must be set or created for this node to work."); } - const Node3D *c = this; - while (c) { - if (Object::cast_to<Navigation3D>(c)) { - return warning; - } - - c = Object::cast_to<Node3D>(c->get_parent()); - } - - if (!warning.is_empty()) { - warning += "\n\n"; - } - return warning + TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data."); + return warning; } void NavigationRegion3D::_bind_methods() { @@ -220,11 +201,15 @@ void NavigationRegion3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled); + ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion3D::set_layers); + ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion3D::get_layers); + ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion3D::bake_navigation_mesh); ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion3D::_bake_finished); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_layers", "get_layers"); ADD_SIGNAL(MethodInfo("navigation_mesh_changed")); ADD_SIGNAL(MethodInfo("bake_finished")); diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index 6ae15c9360..52fa2d6159 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -35,8 +35,6 @@ #include "scene/resources/mesh.h" #include "scene/resources/navigation_mesh.h" -class Navigation3D; - class NavigationRegion3D : public Node3D { GDCLASS(NavigationRegion3D, Node3D); @@ -44,7 +42,6 @@ class NavigationRegion3D : public Node3D { RID region; Ref<NavigationMesh> navmesh; - Navigation3D *navigation = nullptr; Node *debug_view = nullptr; Thread bake_thread; @@ -58,6 +55,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_layers(uint32_t p_layers); + uint32_t get_layers() const; + void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh); Ref<NavigationMesh> get_navigation_mesh() const; diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 4575716f7a..ba0f8cc870 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -48,7 +48,7 @@ a) If above is invalid, don't keep invalidating upwards 2) If a node sets a GLOBAL, it is converted to LOCAL (and forces validation of everything pending below) - drawback: setting/reading globals is useful and used very very often, and using affine inverses is slow + drawback: setting/reading globals is useful and used very often, and using affine inverses is slow --- diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 6d135c8283..e225c1f22d 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -416,13 +416,13 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { } } - //process remotions + //process removals for (int i = 0; i < toremove_count; i++) { _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } - //process aditions + //process additions for (int i = 0; i < toadd_count; i++) { _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 465de2cb47..66f3e539a2 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -428,10 +428,10 @@ void RayCast3D::_update_debug_shape_material(bool p_check_collision) { if (p_check_collision) { if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) { - // If base color is already quite reddish, hightlight collision with green color + // If base color is already quite reddish, highlight collision with green color color = Color(0.0, 1.0, 0.0, color.a); } else { - // Else, hightlight collision with red color + // Else, highlight collision with red color color = Color(1.0, 0, 0, color.a); } } diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index cb486a12ae..80c1f0ddb1 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -63,7 +63,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain chain.chain_root.bone = p_task->root_bone; chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(chain.chain_root.bone); chain.chain_root.current_pos = chain.chain_root.initial_transform.origin; - chain.chain_root.pb = p_task->skeleton->get_physical_bone(chain.chain_root.bone); chain.middle_chain_item = nullptr; // Holds all IDs that are composing a single chain in reverse order @@ -96,8 +95,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain if (!child_ci) { child_ci = sub_chain->add_child(chain_ids[i]); - child_ci->pb = p_task->skeleton->get_physical_bone(child_ci->bone); - child_ci->initial_transform = p_task->skeleton->get_bone_global_pose(child_ci->bone); child_ci->current_pos = child_ci->initial_transform.origin; @@ -123,7 +120,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain if (p_force_simple_chain) { // NOTE: - // This is an "hack" that force to create only one tip per chain since the solver of multi tip (end effector) + // This is a "hack" that force to create only one tip per chain since the solver of multi tip (end effector) // is not yet created. // Remove this code when this is done break; @@ -132,20 +129,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain return true; } -void FabrikInverseKinematic::update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item) { - if (!p_chain_item) { - return; - } - - p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone); - p_chain_item->current_pos = p_chain_item->initial_transform.origin; - - ChainItem *items = p_chain_item->children.ptrw(); - for (int i = 0; i < p_chain_item->children.size(); i += 1) { - update_chain(p_sk, items + i); - } -} - void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) { real_t distance_to_goal(1e4); real_t previous_distance_to_goal(0); @@ -263,7 +246,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_ p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform; } else { // End effector in local transform - const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors.write[0].tip_bone)); + const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors[0].tip_bone)); // Update the end_effector (local transform) by blending with current pose p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta); @@ -285,9 +268,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true); } - make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse().scaled(p_task->skeleton->get_global_transform().get_basis().get_scale()), blending_delta); - - update_chain(p_task->skeleton, &p_task->chain.chain_root); + make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta); if (p_use_magnet && p_task->chain.middle_chain_item) { p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.lerp(p_magnet_position, blending_delta); @@ -310,6 +291,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1))); new_bone_pose.basis.rotate(rot_axis, rot_angle); } + } else { // Set target orientation to tip if (override_tip_basis) { @@ -319,6 +301,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove } } + // IK should not affect scale, so undo any scaling + new_bone_pose.basis.orthonormalize(); + new_bone_pose.basis.scale(p_task->skeleton->get_bone_global_pose(ci->bone).basis.get_scale()); + p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true); if (!ci->children.is_empty()) { diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h index eefecf68bb..c98f55804c 100644 --- a/scene/3d/skeleton_ik_3d.h +++ b/scene/3d/skeleton_ik_3d.h @@ -52,7 +52,6 @@ class FabrikInverseKinematic { // Bone info BoneId bone = -1; - PhysicalBone3D *pb = nullptr; real_t length = 0.0; /// Positions relative to root bone @@ -107,8 +106,6 @@ private: /// Init a chain that starts from the root to tip static bool build_chain(Task *p_task, bool p_force_simple_chain = true); - static void update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item); - static void solve_simple(Task *p_task, bool p_solve_magnet); /// Special solvers that solve only chains with one end effector static void solve_simple_backwards(Chain &r_chain, bool p_solve_magnet); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index b7a3135bd5..a3265ffb30 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -692,7 +692,7 @@ void AnimatedSprite3D::_draw() { Ref<Texture2D> texture = frames->get_frame(animation, frame); if (!texture.is_valid()) { - return; //no texuture no life + return; //no texture no life } Vector2 tsize = texture->get_size(); if (tsize.x == 0 || tsize.y == 0) { diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 8b774444b9..5b0b3b89d3 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -563,7 +563,7 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const b2invmass); // FIXME: rel_vel assignment here is overwritten by the following assignment. - // What seems to be intended in the next next assignment is: rel_vel = normal.dot(rel_vel); + // What seems to be intended in the next assignment is: rel_vel = normal.dot(rel_vel); // Investigate why. real_t rel_vel = jac.getRelativeVelocity( s->get_linear_velocity(), diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 17c8596e8f..16718b956f 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -151,7 +151,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector2 uv; Vector3 lnormal; get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal); - if (lnormal == Vector3()) { //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal is not provided lnormal = normal; } @@ -183,7 +183,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector3 lnormal; Vector2 uv; get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal); - if (lnormal == Vector3()) { //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal is not provided lnormal = normal; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 2c19307c52..0c1798a876 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -605,7 +605,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } if (p_seeked) { - //find whathever should be playing + //find whatever should be playing int idx = a->track_find_key(i, p_time); if (idx < 0) { continue; @@ -634,7 +634,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -665,7 +665,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -1343,7 +1343,7 @@ void AnimationPlayer::_stop_playing_caches() { } void AnimationPlayer::_node_removed(Node *p_node) { - clear_caches(); // nodes contained here ar being removed, clear the caches + clear_caches(); // nodes contained here are being removed, clear the caches } void AnimationPlayer::clear_caches() { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 26a13f33c9..24c73a6b1b 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1009,7 +1009,7 @@ void AnimationTree::_process_graph(float p_delta) { TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); if (seeked) { - //find whathever should be playing + //find whatever should be playing int idx = a->track_find_key(i, time); if (idx < 0) { continue; @@ -1038,7 +1038,7 @@ void AnimationTree::_process_graph(float p_delta) { t->playing = true; playing_caches.insert(t); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time t->len = len - start_ofs - end_ofs; } else { t->len = 0; @@ -1069,7 +1069,7 @@ void AnimationTree::_process_graph(float p_delta) { t->playing = true; playing_caches.insert(t); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time t->len = len - start_ofs - end_ofs; } else { t->len = 0; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index eb35979a47..2030808724 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -1115,7 +1115,7 @@ real_t Tween::tell() const { // For each interpolation... for (const List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { - // Get the data and figure out if it's position is further along than the previous ones + // Get the data and figure out if its position is further along than the previous ones const InterpolateData &data = E->get(); if (data.elapsed > pos) { // Save it if so diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 2853a8b9d9..1478cbf69e 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -171,7 +171,7 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { if (active.is_set() && stream_playback.is_valid() && !stream_paused) { //changing streams out of the blue is not a great idea, but at least - //lets try to somehow avoid a click + //let's try to somehow avoid a click AudioFrame *buffer = fadeout_buffer.ptrw(); int buffer_size = fadeout_buffer.size(); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 4dbe3cc1c4..a1d4adcd41 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -487,7 +487,7 @@ void LiveEditor::_send_tree() { } Array arr; - // Encoded as a flat list depth fist. + // Encoded as a flat list depth first. SceneDebuggerTree tree(scene_tree->root); tree.serialize(arr); EngineDebugger::get_singleton()->send_message("scene:scene_tree", arr); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index e8586b72e9..bddbe30f53 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -113,6 +113,24 @@ void ColorPicker::_update_controls() { btn_hsv->set_disabled(false); } + if (raw_mode_enabled) { + for (int i = 0; i < 3; i++) { + scroll[i]->add_theme_icon_override("grabber", Ref<Texture2D>()); + scroll[i]->add_theme_icon_override("grabber_highlight", Ref<Texture2D>()); + scroll[i]->add_theme_style_override("slider", Ref<StyleBox>()); + scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBox>()); + scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBox>()); + } + } else { + for (int i = 0; i < 3; i++) { + scroll[i]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow")); + scroll[i]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow")); + scroll[i]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + } + } + if (edit_alpha) { values[3]->show(); scroll[3]->show(); @@ -243,6 +261,9 @@ void ColorPicker::_update_color(bool p_update_sliders) { sample->update(); uv_edit->update(); w_edit->update(); + for (int i = 0; i < 4; i++) { + scroll[i]->update(); + } updating = false; } @@ -456,6 +477,69 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } } +void ColorPicker::_slider_draw(int p_which) { + Vector<Vector2> pos; + pos.resize(4); + Vector<Color> col; + col.resize(4); + Size2 size = scroll[p_which]->get_size(); + Color left_color; + Color right_color; +#ifdef TOOLS_ENABLED + const real_t margin = 4 * EDSCALE; +#else + const real_t margin = 4; +#endif + + if (p_which == 3) { + scroll[p_which]->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), Rect2(Point2(0, margin), Size2(size.x, margin)), true); + + left_color = color; + left_color.a = 0; + right_color = color; + right_color.a = 1; + } else { + if (raw_mode_enabled) { + return; + } + if (hsv_mode_enabled) { + if (p_which == 0) { + Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker"); + scroll[p_which]->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); + scroll[p_which]->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(scroll[p_which]->get_size().x, margin)), false, Color(1, 1, 1), true); + return; + } + Color s_col; + Color v_col; + s_col.set_hsv(h, 0, v); + left_color = (p_which == 1) ? s_col : Color(0, 0, 0); + s_col.set_hsv(h, 1, v); + v_col.set_hsv(h, s, 1); + right_color = (p_which == 1) ? s_col : v_col; + } else { + left_color = Color( + p_which == 0 ? 0 : color.r, + p_which == 1 ? 0 : color.g, + p_which == 2 ? 0 : color.b); + right_color = Color( + p_which == 0 ? 1 : color.r, + p_which == 1 ? 1 : color.g, + p_which == 2 ? 1 : color.b); + } + } + + col.set(0, left_color); + col.set(1, right_color); + col.set(2, right_color); + col.set(3, left_color); + pos.set(0, Vector2(0, margin)); + pos.set(1, Vector2(size.x, margin)); + pos.set(2, Vector2(size.x, margin * 2)); + pos.set(3, Vector2(0, margin * 2)); + + scroll[p_which]->draw_polygon(pos, col); +} + void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> bev = p_event; @@ -799,10 +883,16 @@ ColorPicker::ColorPicker() : scroll[i]->set_h_size_flags(SIZE_EXPAND_FILL); scroll[i]->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed)); + scroll[i]->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(i)); vbr->add_child(hbc); } labels[3]->set_text("A"); + scroll[3]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow")); + scroll[3]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow")); + scroll[3]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + scroll[3]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + scroll[3]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); HBoxContainer *hhb = memnew(HBoxContainer); vbr->add_child(hhb); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 7915527bc0..24e1746c41 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -91,6 +91,7 @@ private: void _text_type_toggled(); void _sample_draw(); void _hsv_draw(int p_which, Control *c); + void _slider_draw(int p_which); void _uv_input(const Ref<InputEvent> &p_event); void _w_input(const Ref<InputEvent> &p_event); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index bff3024e38..d209b17fa1 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -73,6 +73,9 @@ Dictionary Control::_edit_get_state() const { } void Control::_edit_set_state(const Dictionary &p_state) { + ERR_FAIL_COND((p_state.size() <= 0) || + !p_state.has("rotation") || !p_state.has("scale") || + !p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets")); Dictionary state = p_state; set_rotation(state["rotation"]); @@ -581,7 +584,7 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_MOVED_IN_PARENT: { - // some parents need to know the order of the childrens to draw (like TabContainer) + // some parents need to know the order of the children to draw (like TabContainer) // update if necessary if (data.parent) { data.parent->update(); @@ -1779,7 +1782,7 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } - // clear if "null" is passed instead of a icon + // clear if "null" is passed instead of an icon if (p_icon.is_null()) { data.icon_override.erase(p_name); } else { diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 7453324505..7fb5113130 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -731,9 +731,9 @@ FileDialog::Access FileDialog::get_access() const { } void FileDialog::_make_dir_confirm() { - Error err = dir_access->make_dir(makedirname->get_text()); + Error err = dir_access->make_dir(makedirname->get_text().strip_edges()); if (err == OK) { - dir_access->change_dir(makedirname->get_text()); + dir_access->change_dir(makedirname->get_text().strip_edges()); invalidate(); update_filters(); update_dir(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 7afc04c51c..fa72599fb3 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -768,7 +768,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } } } else if (p_event->is_action("ui_accept")) { - search_string = ""; //any mousepress cance + search_string = ""; //any mousepress cancels if (current >= 0 && current < items.size()) { emit_signal("item_activated", current); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 830ffc092f..ce371e3b56 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -809,7 +809,7 @@ void LineEdit::_notification(int p_what) { } } else { { - // IME intermidiet text range. + // IME intermediate text range. Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, cursor_pos, cursor_pos + ime_text.length()); for (int i = 0; i < sel.size(); i++) { Rect2 rect = Rect2(sel[i].x + ofs.x, ofs.y, sel[i].y - sel[i].x, text_height); @@ -848,7 +848,7 @@ void LineEdit::_notification(int p_what) { } if (has_focus()) { - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + TS->shaped_text_get_size(text_rid).y), get_viewport()->get_window_id()); } @@ -865,7 +865,7 @@ void LineEdit::_notification(int p_what) { } } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height; DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id()); @@ -878,7 +878,7 @@ void LineEdit::_notification(int p_what) { caret_blink_timer->stop(); } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); } @@ -1436,7 +1436,7 @@ void LineEdit::set_cursor_position(int p_pos) { ofs_max -= r_icon->get_width(); } - // Note: Use too coordinates to fit IME input range. + // Note: Use two coordinates to fit IME input range. Vector2i primary_catret_offset = get_cursor_pixel_pos(); if (MIN(primary_catret_offset.x, primary_catret_offset.y) <= x_ofs) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index f237f79be1..d733c33c5f 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -222,7 +222,7 @@ void PopupMenu::_activate_submenu(int p_over) { submenu_popup->set_close_on_parent_focus(false); submenu_popup->set_position(submenu_pos); - submenu_popup->set_as_minsize(); // Shrink the popup size to it's contents. + submenu_popup->set_as_minsize(); // Shrink the popup size to its contents. submenu_popup->popup(); // Set autohide areas diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e488e7a914..61266f6d22 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -808,7 +808,7 @@ void TextEdit::_notification(int p_what) { // Get the highlighted words. String highlighted_text = get_selection_text(); - // Check if highlighted words contains only whitespaces (tabs or spaces). + // Check if highlighted words contain only whitespaces (tabs or spaces). bool only_whitespaces_highlighted = highlighted_text.strip_edges() == String(); int cursor_wrap_index = get_cursor_wrap_index(); @@ -1057,7 +1057,7 @@ void TextEdit::_notification(int p_what) { } if (str.length() == 0) { - // Draw line background if empty as we won't loop at at all. + // Draw line background if empty as we won't loop at all. if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { if (rtl) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), cache.current_line_color); @@ -1442,7 +1442,7 @@ void TextEdit::_notification(int p_what) { } } else { { - // IME intermidiet text range. + // IME Intermediate text range. Vector<Vector2> sel = TS->shaped_text_get_selection(rid, cursor.column, cursor.column + ime_text.length()); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, text_height); @@ -1702,7 +1702,7 @@ void TextEdit::_notification(int p_what) { } if (has_focus()) { - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id()); } @@ -1715,7 +1715,7 @@ void TextEdit::_notification(int p_what) { draw_caret = true; } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + _get_cursor_pixel_pos(false), get_viewport()->get_window_id()); } @@ -1744,7 +1744,7 @@ void TextEdit::_notification(int p_what) { caret_blink_timer->stop(); } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); } @@ -2009,7 +2009,7 @@ void TextEdit::indent_selected_lines_right() { // We don't really care where selection is - we just need to know indentation level at the beginning of the line. int left = _find_first_non_whitespace_column_of_line(line_text); int spaces_to_add = _calculate_spaces_till_next_right_indent(left); - // Since we will add this much spaces we want move whole selection and cursor by this much. + // Since we will add these many spaces, we want to move the whole selection and cursor by this much. selection_offset = spaces_to_add; for (int j = 0; j < spaces_to_add; j++) { line_text = ' ' + line_text; @@ -2034,7 +2034,7 @@ void TextEdit::indent_selected_lines_left() { int end_line; // Moving cursor and selection after unindenting can get tricky because - // changing content of line can move cursor and selection on it's own (if new line ends before previous position of either), + // changing content of line can move cursor and selection on its own (if new line ends before previous position of either), // therefore we just remember initial values and at the end of the operation offset them by number of removed characters. int removed_characters = 0; int initial_selection_end_column = selection.to_column; @@ -2454,7 +2454,7 @@ void TextEdit::_move_cursor_to_line_start(bool p_select) { row_start_col += rows[i].length(); } if (cursor.column == row_start_col || wi == 0) { - // Compute whitespace symbols seq length. + // Compute whitespace symbols sequence length. int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { char32_t c = text[cursor.line][current_line_whitespace_len]; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 71c372aec2..e4ed5c6e6c 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -335,7 +335,7 @@ bool HTTPRequest::_update_connection() { call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray()); return true; - // Request migh have been done + // Request might have been done } else { // Did not request yet, do request diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9d8c7981e6..933f67db68 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -428,7 +428,7 @@ void Node::set_process_mode(ProcessMode p_mode) { _propagate_process_owner(data.process_owner, pause_notification); #ifdef TOOLS_ENABLED // This is required for the editor to update the visibility of disabled nodes - // Its very expensive during runtime to change, so editor-only + // It's very expensive during runtime to change, so editor-only if (Engine::get_singleton()->is_editor_hint()) { get_tree()->emit_signal("tree_process_mode_changed"); } @@ -1021,22 +1021,8 @@ void Node::_set_name_nocheck(const StringName &p_name) { data.name = p_name; } -String Node::invalid_character = ". : @ / \""; - -bool Node::_validate_node_name(String &p_name) { - String name = p_name; - Vector<String> chars = Node::invalid_character.split(" "); - for (int i = 0; i < chars.size(); i++) { - name = name.replace(chars[i], ""); - } - bool is_valid = name == p_name; - p_name = name; - return is_valid; -} - void Node::set_name(const String &p_name) { - String name = p_name; - _validate_node_name(name); + String name = p_name.validate_node_name(); ERR_FAIL_COND(name == ""); data.name = name; @@ -1144,7 +1130,7 @@ String increase_numeric_string(const String &s) { void Node::_generate_serial_child_name(const Node *p_child, StringName &name) const { if (name == StringName()) { - //no name and a new nade is needed, create one. + //no name and a new name is needed, create one. name = p_child->get_class(); // Adjust casing according to project setting. The current type name is expected to be in PascalCase. @@ -1170,7 +1156,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co bool exists = false; for (int i = 0; i < cc; i++) { - if (children_ptr[i] == p_child) { //exclude self in renaming if its already a child + if (children_ptr[i] == p_child) { //exclude self in renaming if it's already a child continue; } if (children_ptr[i]->data.name == name) { @@ -1959,7 +1945,7 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) { if (!p_editable) { p_node->data.editable_instance = false; // Avoid this flag being needlessly saved; - // also give more visual feedback if editable children is re-enabled + // also give more visual feedback if editable children are re-enabled set_display_folded(false); } else { p_node->data.editable_instance = true; @@ -2065,19 +2051,26 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const // Since nodes in the instanced hierarchy won't be duplicated explicitly, we need to make an inventory // of all the nodes in the tree of the instanced scene in order to transfer the values of the properties + Vector<const Node *> instance_roots; + instance_roots.push_back(this); + for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) { for (int i = 0; i < N->get()->get_child_count(); ++i) { Node *descendant = N->get()->get_child(i); // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later // but remember non-instanced nodes that are hidden below instanced ones - if (descendant->data.owner != this) { - if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this && descendant->data.owner != descendant->get_parent()) { + if (!instance_roots.has(descendant->get_owner())) { + if (descendant->get_parent() && descendant->get_parent() != this && descendant->data.owner != descendant->get_parent()) { hidden_roots.push_back(descendant); } continue; } node_tree.push_back(descendant); + + if (descendant->get_filename() != "" && instance_roots.has(descendant->get_owner())) { + instance_roots.push_back(descendant); + } } } } diff --git a/scene/main/node.h b/scene/main/node.h index d47d271a10..b1e51d2aee 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -190,12 +190,6 @@ private: _FORCE_INLINE_ bool _can_process(bool p_paused) const; -#ifdef TOOLS_ENABLED - friend class SceneTreeEditor; -#endif - static String invalid_character; - static bool _validate_node_name(String &p_name); - protected: void _block() { data.blocked++; } void _unblock() { data.blocked--; } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 40b85e6d7b..e2b30cfa3d 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2201,7 +2201,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { embedder = this; viewport_pos = mpos; } else { - //not an embeder, but may be a subwindow of an embedder + //not an embedder, but may be a subwindow of an embedder Window *w = Object::cast_to<Window>(this); if (w) { if (w->is_embedded()) { @@ -2393,7 +2393,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { //keyboard focus //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) { Ref<InputEventKey> k = p_event; - //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be. + //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be. bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey()); if (from && p_event->is_pressed()) { @@ -2672,7 +2672,7 @@ void Viewport::_post_gui_grab_click_focus() { Ref<InputEventMouseButton> mb; mb.instance(); - //send unclic + //send unclick mb->set_position(click); mb->set_button_index(i + 1); @@ -2690,7 +2690,7 @@ void Viewport::_post_gui_grab_click_focus() { Ref<InputEventMouseButton> mb; mb.instance(); - //send clic + //send click mb->set_position(click); mb->set_button_index(i + 1); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 51d4643883..fe8591e3d9 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -50,7 +50,6 @@ #include "scene/2d/line_2d.h" #include "scene/2d/mesh_instance_2d.h" #include "scene/2d/multimesh_instance_2d.h" -#include "scene/2d/navigation_2d.h" #include "scene/2d/navigation_agent_2d.h" #include "scene/2d/navigation_obstacle_2d.h" #include "scene/2d/parallax_background.h" @@ -206,7 +205,6 @@ #include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h" -#include "scene/3d/navigation_3d.h" #include "scene/3d/navigation_agent_3d.h" #include "scene/3d/navigation_obstacle_3d.h" #include "scene/3d/navigation_region_3d.h" @@ -516,7 +514,6 @@ void register_scene_types() { ClassDB::register_class<ConeTwistJoint3D>(); ClassDB::register_class<Generic6DOFJoint3D>(); - ClassDB::register_class<Navigation3D>(); ClassDB::register_class<NavigationRegion3D>(); ClassDB::register_class<NavigationAgent3D>(); ClassDB::register_class<NavigationObstacle3D>(); @@ -793,7 +790,6 @@ void register_scene_types() { ClassDB::register_class<PathFollow2D>(); ClassDB::register_class<NavigationMesh>(); - ClassDB::register_class<Navigation2D>(); ClassDB::register_class<NavigationPolygon>(); ClassDB::register_class<NavigationRegion2D>(); ClassDB::register_class<NavigationAgent2D>(); @@ -814,6 +810,8 @@ void register_scene_types() { ClassDB::add_compatibility_class("DynamicFont", "Font"); ClassDB::add_compatibility_class("DynamicFontData", "FontData"); ClassDB::add_compatibility_class("ToolButton", "Button"); + ClassDB::add_compatibility_class("Navigation3D", "Node3D"); + ClassDB::add_compatibility_class("Navigation2D", "Node2D"); // Renamed in 4.0. // Keep alphabetical ordering to easily locate classes and avoid duplicates. @@ -865,7 +863,6 @@ void register_scene_types() { ClassDB::add_compatibility_class("Listener", "Listener3D"); ClassDB::add_compatibility_class("MeshInstance", "MeshInstance3D"); ClassDB::add_compatibility_class("MultiMeshInstance", "MultiMeshInstance3D"); - ClassDB::add_compatibility_class("Navigation", "Navigation3D"); ClassDB::add_compatibility_class("NavigationAgent", "NavigationAgent3D"); ClassDB::add_compatibility_class("NavigationMeshInstance", "NavigationRegion3D"); ClassDB::add_compatibility_class("NavigationObstacle", "NavigationObstacle3D"); @@ -950,8 +947,10 @@ void register_scene_types() { for (int i = 0; i < 20; i++) { GLOBAL_DEF_BASIC(vformat("layer_names/2d_render/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/2d_physics/layer_%d", i), ""); + GLOBAL_DEF_BASIC(vformat("layer_names/2d_navigation/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/3d_render/layer_%d", i), ""); GLOBAL_DEF_BASIC(vformat("layer_names/3d_physics/layer_%d", i), ""); + GLOBAL_DEF_BASIC(vformat("layer_names/3d_navigation/layer_%d", i), ""); } bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index cc1dafd0db..6f64ac6d04 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2738,7 +2738,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { - return false; //beyond allowed error for colinearity + return false; //beyond allowed error for collinearity } if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) { @@ -2828,7 +2828,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { - return false; //beyond allowed error for colinearity + return false; //beyond allowed error for collinearity } t[2] = (d1 - d0) / (d2 - d0); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 8ffc7b4b4c..3cc1af59ae 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -285,7 +285,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) +---+---+ | 4 | | +---+---+ - this normally go RIGHT, but if its coming from RIGHT, it should go LEFT + this normally go RIGHT, but if it's coming from RIGHT, it should go LEFT */ if (case6s.has(Point2i(curx, cury))) { //found, so we go left, and delete from case6s; diff --git a/scene/resources/default_theme/bar_arrow.png b/scene/resources/default_theme/bar_arrow.png Binary files differnew file mode 100644 index 0000000000..7cf146b8da --- /dev/null +++ b/scene/resources/default_theme/bar_arrow.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index ddf1fc3db4..0c661cc17d 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -884,6 +884,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png)); theme->set_icon("preset_bg", "ColorPicker", make_icon(mini_checkerboard_png)); theme->set_icon("overbright_indicator", "ColorPicker", make_icon(overbright_indicator_png)); + theme->set_icon("bar_arrow", "ColorPicker", make_icon(bar_arrow_png)); theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png)); diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index b905c9db69..6b78ba7933 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -14,6 +14,10 @@ static const unsigned char arrow_right_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char bar_arrow_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x14, 0x8, 0x4, 0x0, 0x0, 0x0, 0x2e, 0x6b, 0x75, 0xfc, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x1, 0x73, 0x52, 0x47, 0x42, 0x0, 0xae, 0xce, 0x1c, 0xe9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0xe, 0xc0, 0x1, 0x6a, 0xd6, 0x89, 0x9, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0xfc, 0xcf, 0x80, 0x1f, 0x30, 0x8e, 0x20, 0x5, 0x8c, 0x38, 0x24, 0xff, 0x53, 0x5f, 0xc1, 0xb, 0xee, 0x9f, 0x53, 0x18, 0x18, 0xd8, 0x73, 0x24, 0xbe, 0x62, 0x55, 0x70, 0x5f, 0x83, 0x61, 0x15, 0xa3, 0x2e, 0x3, 0x3, 0xc3, 0xd, 0xe6, 0x30, 0xd9, 0xcb, 0x18, 0xa, 0x1e, 0xc6, 0xfd, 0x9f, 0xc6, 0xc0, 0xd, 0x35, 0xea, 0x3b, 0x63, 0x81, 0xfc, 0x2c, 0x14, 0x5, 0xf, 0x2a, 0x18, 0xda, 0xd1, 0x1c, 0x50, 0xa9, 0xd0, 0x1, 0x57, 0xf0, 0x10, 0x53, 0x9a, 0x81, 0x81, 0x81, 0xa1, 0x52, 0xbe, 0x83, 0x81, 0x81, 0xf1, 0x3f, 0x2e, 0x69, 0xa8, 0x12, 0x3a, 0x4, 0x14, 0x0, 0x7b, 0xda, 0x34, 0x1, 0xbb, 0xb5, 0x3e, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char bookmark_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 9931757cc4..0d02bde90d 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1703,7 +1703,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NOEDITOR; } - // you can only enable anti-aliasing (in mataerials) on alpha scissor and alpha hash + // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH); // alpha anti aliasiasing is only enabled when you can select aa const bool alpha_aa_enabled = (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) && can_select_aa; @@ -1722,7 +1722,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = 0; } - // we cant choose an antialiasing mode if alpha isnt possible + // we can't choose an antialiasing mode if alpha isn't possible if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) { property.usage = 0; } diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 167540eb77..a0f4bf9409 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -1075,7 +1075,7 @@ ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() cons void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) { sub_emitter_frequency = p_frequency; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pass delta instead of frequency, since its easier to compute } float ParticlesMaterial::get_sub_emitter_frequency() const { return sub_emitter_frequency; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index f292140d6b..536318ed16 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -77,7 +77,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> outside_point.x += 20.451 + Math::randf() * 10.2039; outside_point.y += 21.193 + Math::randf() * 12.5412; - //insert edges (which are also connetions) + //insert edges (which are also connections) for (int i = 0; i < p_connections.size(); i += 2) { Edge e(p_connections[i], p_connections[i + 1]); @@ -335,7 +335,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //oh this was visited already, can we win the cost? if (p.distance > distance) { - p.prev = least_cost_point; //reasign previous + p.prev = least_cost_point; //reassign previous p.distance = distance; } } else { diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 7ca532e1d6..f2751b7604 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -1321,7 +1321,7 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - return ""; //could not rwead + return ""; //could not read } ResourceLoaderText loader; diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 156c7d0576..a064ade362 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -34,6 +34,7 @@ #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" #include "scene/main/window.h" +#include "servers/navigation_server_2d.h" #include "servers/physics_server_2d.h" #include "servers/rendering_server.h" @@ -315,14 +316,18 @@ void World2D::_update() { indexer->_update(); } -RID World2D::get_canvas() { +RID World2D::get_canvas() const { return canvas; } -RID World2D::get_space() { +RID World2D::get_space() const { return space; } +RID World2D::get_navigation_map() const { + return navigation_map; +} + void World2D::get_viewport_list(List<Viewport *> *r_viewports) { for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) { r_viewports->push_back(E->key()); @@ -332,11 +337,13 @@ void World2D::get_viewport_list(List<Viewport *> *r_viewports) { void World2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &World2D::get_navigation_map); ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World2D::get_direct_space_state); ADD_PROPERTY(PropertyInfo(Variant::RID, "canvas", PROPERTY_HINT_NONE, "", 0), "", "get_canvas"); ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space"); + ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState2D", 0), "", "get_direct_space_state"); } @@ -346,9 +353,9 @@ PhysicsDirectSpaceState2D *World2D::get_direct_space_state() { World2D::World2D() { canvas = RenderingServer::get_singleton()->canvas_create(); - space = PhysicsServer2D::get_singleton()->space_create(); - //set space2D to be more friendly with pixels than meters, by adjusting some constants + // Create and configure space2D to be more friendly with pixels than meters + space = PhysicsServer2D::get_singleton()->space_create(); PhysicsServer2D::get_singleton()->space_set_active(space, true); PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); @@ -356,11 +363,19 @@ World2D::World2D() { ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0)); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + + // Create and configure the navigation_map to be more friendly with pixels than meters. + navigation_map = NavigationServer2D::get_singleton()->map_create(); + NavigationServer2D::get_singleton()->map_set_active(navigation_map, true); + NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 10)); + NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 100)); + indexer = memnew(SpatialIndexer2D); } World2D::~World2D() { RenderingServer::get_singleton()->free(canvas); PhysicsServer2D::get_singleton()->free(space); + NavigationServer2D::get_singleton()->free(navigation_map); memdelete(indexer); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index ae13367421..38abf3d7ad 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -44,6 +44,7 @@ class World2D : public Resource { RID canvas; RID space; + RID navigation_map; SpatialIndexer2D *indexer; @@ -63,8 +64,9 @@ protected: void _update(); public: - RID get_canvas(); - RID get_space(); + RID get_canvas() const; + RID get_space() const; + RID get_navigation_map() const; PhysicsDirectSpaceState2D *get_direct_space_state(); diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp index 9c0317454b..0e9f7a6cf2 100644 --- a/scene/resources/world_3d.cpp +++ b/scene/resources/world_3d.cpp @@ -35,6 +35,7 @@ #include "scene/3d/camera_3d.h" #include "scene/3d/visibility_notifier_3d.h" #include "scene/scene_string_names.h" +#include "servers/navigation_server_3d.h" struct SpatialIndexer { Octree<VisibilityNotifier3D> octree; @@ -243,6 +244,10 @@ RID World3D::get_space() const { return space; } +RID World3D::get_navigation_map() const { + return navigation_map; +} + RID World3D::get_scenario() const { return scenario; } @@ -310,6 +315,7 @@ void World3D::get_camera_list(List<Camera3D *> *r_cameras) { void World3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map); ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario); ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment); ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment); @@ -322,6 +328,7 @@ void World3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects"); ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space"); + ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map"); ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", 0), "", "get_scenario"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState3D", 0), "", "get_direct_space_state"); } @@ -338,6 +345,11 @@ World3D::World3D() { PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1)); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + navigation_map = NavigationServer3D::get_singleton()->map_create(); + NavigationServer3D::get_singleton()->map_set_active(navigation_map, true); + NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.3)); + NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 5.0)); // Five meters, depends a lot on the agent's radius + #ifdef _3D_DISABLED indexer = nullptr; #else @@ -348,6 +360,7 @@ World3D::World3D() { World3D::~World3D() { PhysicsServer3D::get_singleton()->free(space); RenderingServer::get_singleton()->free(scenario); + NavigationServer3D::get_singleton()->free(navigation_map); #ifndef _3D_DISABLED memdelete(indexer); diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index 3d6c33997e..4e2717a2bb 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -46,6 +46,7 @@ class World3D : public Resource { private: RID space; + RID navigation_map; RID scenario; SpatialIndexer *indexer; Ref<Environment> environment; @@ -70,6 +71,7 @@ protected: public: RID get_space() const; + RID get_navigation_map() const; RID get_scenario() const; void set_environment(const Ref<Environment> &p_environment); diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index df348d2add..fee74f3dbc 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -80,6 +80,18 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr; return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \ } +#define FORWARD_5_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \ + const { \ + return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4))); \ + } + +#define FORWARD_5_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4)); \ + } + static RID rid_to_rid(const RID d) { return d; } @@ -92,6 +104,10 @@ static int int_to_int(const int d) { return d; } +static uint32_t uint32_to_uint32(const uint32_t d) { + return d; +} + static real_t real_to_real(const real_t d) { return d; } @@ -148,12 +164,14 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer2D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers); + ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform); ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly); @@ -193,14 +211,15 @@ real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real); real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid); -Vector<Vector2> FORWARD_4_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool); +Vector<Vector2> FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, uint32_t, p_layers, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool, uint32_to_uint32); Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); RID FORWARD_0_C(region_create); void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid); - +void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32); +uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid); void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3); void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const { diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 7be5a74cb3..46c8f6a71d 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -77,7 +77,7 @@ public: virtual real_t map_get_edge_connection_margin(RID p_map) const; /// Returns the navigation path to reach the destination from the origin. - virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize) const; + virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const; virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; @@ -88,6 +88,10 @@ public: /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const; + /// Set the region's layers + virtual void region_set_layers(RID p_region, uint32_t p_layers) const; + virtual uint32_t region_get_layers(RID p_region) const; + /// Set the global transformation of this region. virtual void region_set_transform(RID p_region, Transform2D p_transform) const; diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 0e5ae82b0d..d81ce70af6 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -46,7 +46,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer3D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); @@ -54,6 +54,8 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers); + ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform); ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh); ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 3761c3871a..beed19d563 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -88,7 +88,7 @@ public: virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; /// Returns the navigation path to reach the destination from the origin. - virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const = 0; + virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0; virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0; virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0; @@ -101,6 +101,10 @@ public: /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const = 0; + /// Set the region's layers + virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0; + virtual uint32_t region_get_layers(RID p_region) const = 0; + /// Set the global transformation of this region. virtual void region_set_transform(RID p_region, Transform p_transform) const = 0; diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index 82356e77ef..9eff14bbeb 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -51,18 +51,18 @@ void Body3DSW::_update_transform_dependant() { } void Body3DSW::update_inertias() { - //update shapes and motions + // Update shapes and motions. switch (mode) { case PhysicsServer3D::BODY_MODE_RIGID: { - //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet) + // Update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet) real_t total_area = 0; for (int i = 0; i < get_shape_count(); i++) { total_area += get_shape_area(i); } - // We have to recompute the center of mass + // We have to recompute the center of mass. center_of_mass_local.zero(); for (int i = 0; i < get_shape_count(); i++) { @@ -70,21 +70,24 @@ void Body3DSW::update_inertias() { real_t mass = area * this->mass / total_area; - // NOTE: we assume that the shape origin is also its center of mass + // NOTE: we assume that the shape origin is also its center of mass. center_of_mass_local += mass * get_shape_transform(i).origin; } center_of_mass_local /= mass; - // Recompute the inertia tensor + // Recompute the inertia tensor. Basis inertia_tensor; inertia_tensor.set_zero(); + bool inertia_set = false; for (int i = 0; i < get_shape_count(); i++) { if (is_shape_disabled(i)) { continue; } + inertia_set = true; + const Shape3DSW *shape = get_shape(i); real_t area = get_shape_area(i); @@ -102,7 +105,12 @@ void Body3DSW::update_inertias() { inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass; } - // Compute the principal axes of inertia + // Set the inertia to a valid value when there are no valid shapes. + if (!inertia_set) { + inertia_tensor.set_diagonal(Vector3(1.0, 1.0, 1.0)); + } + + // Compute the principal axes of inertia. principal_inertia_axes_local = inertia_tensor.diagonalize().transposed(); _inv_inertia = inertia_tensor.get_main_diagonal().inverse(); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index be2552bd32..d5ac05d1d1 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -175,5 +175,5 @@ RendererCompositorRD::RendererCompositorRD() { storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); - scene = memnew(RendererSceneRenderForward(storage)); + scene = memnew(RendererSceneRenderForwardClustered(storage)); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index cb85fc79e0..67a843452b 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -35,14 +35,14 @@ #include "core/templates/thread_work_pool.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_render_forward.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" class RendererCompositorRD : public RendererCompositor { protected: RendererCanvasRenderRD *canvas; RendererStorageRD *storage; - RendererSceneRenderForward *scene; + RendererSceneRenderRD *scene; RID copy_viewports_rd_shader; RID copy_viewports_rd_pipeline; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index bfb5b729ef..4e4e553605 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1100,8 +1100,6 @@ void RendererSceneGIRD::SDFGI::update_cascades() { } void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { - // !BAS! Need to find a nicer way then adding width/height/renderbuffer/texture as parameters - if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -2806,9 +2804,11 @@ RendererSceneGIRD::RendererSceneGIRD() { RendererSceneGIRD::~RendererSceneGIRD() { } -void RendererSceneGIRD::init_gi(RendererStorageRD *p_storage) { +void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) { storage = p_storage; + /* GI */ + { //kinda complicated to compute the amount of slots, we try to use as many as we can @@ -2861,9 +2861,9 @@ void RendererSceneGIRD::init_gi(RendererStorageRD *p_storage) { giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); } } -} -void RendererSceneGIRD::init_sdfgi(RendererSceneSkyRD *p_sky) { + /* SDGFI */ + { Vector<String> preprocess_modes; preprocess_modes.push_back("\n#define MODE_SCROLL\n"); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index 691a2e1841..c0f3318538 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -53,8 +53,6 @@ class RendererSceneRenderRD; class RendererSceneGIRD { private: - // !BAS! need to see which things become internal.. - RendererStorageRD *storage; /* GIPROBE INSTANCE */ @@ -652,9 +650,7 @@ public: RendererSceneGIRD(); ~RendererSceneGIRD(); - // !BAS! Can we merge these two inits? Possibly, need to check - void init_gi(RendererStorageRD *p_storage); - void init_sdfgi(RendererSceneSkyRD *p_sky); + void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky); void free(); SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp index 874389f7e9..7a19495f48 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_render_forward.cpp */ +/* renderer_scene_render_forward_clustered.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_scene_render_forward.h" +#include "renderer_scene_render_forward_clustered.h" #include "core/config/project_settings.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" /* SCENE SHADER */ -void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) { +void RendererSceneRenderForwardClustered::ShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -123,7 +123,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; + RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; Error err = scene_singleton->shader.compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); @@ -257,7 +257,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) { RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; for (int k = 0; k < SHADER_VERSION_MAX; k++) { - if (!static_cast<RendererSceneRenderForward *>(singleton)->shader.scene_shader.is_variant_enabled(k)) { + if (!static_cast<RendererSceneRenderForwardClustered *>(singleton)->shader.scene_shader.is_variant_enabled(k)) { continue; } RD::PipelineRasterizationState raster_state; @@ -324,7 +324,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneRenderForward::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneRenderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { if (!p_texture.is_valid()) { default_texture_params.erase(p_name); } else { @@ -332,7 +332,7 @@ void RendererSceneRenderForward::ShaderData::set_default_texture_param(const Str } } -void RendererSceneRenderForward::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererSceneRenderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { @@ -354,7 +354,7 @@ void RendererSceneRenderForward::ShaderData::get_param_list(List<PropertyInfo> * } } -void RendererSceneRenderForward::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneRenderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; @@ -369,7 +369,7 @@ void RendererSceneRenderForward::ShaderData::get_instance_param_list(List<Render } } -bool RendererSceneRenderForward::ShaderData::is_param_texture(const StringName &p_param) const { +bool RendererSceneRenderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -377,15 +377,15 @@ bool RendererSceneRenderForward::ShaderData::is_param_texture(const StringName & return uniforms[p_param].texture_order >= 0; } -bool RendererSceneRenderForward::ShaderData::is_animated() const { +bool RendererSceneRenderForwardClustered::ShaderData::is_animated() const { return false; } -bool RendererSceneRenderForward::ShaderData::casts_shadows() const { +bool RendererSceneRenderForwardClustered::ShaderData::casts_shadows() const { return false; } -Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererSceneRenderForwardClustered::ShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -394,19 +394,19 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri return Variant(); } -RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const { - RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; +RS::ShaderNativeSourceCode RendererSceneRenderForwardClustered::ShaderData::get_native_source_code() const { + RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; return scene_singleton->shader.scene_shader.version_get_native_source_code(version); } -RendererSceneRenderForward::ShaderData::ShaderData() { +RendererSceneRenderForwardClustered::ShaderData::ShaderData() { valid = false; uses_screen_texture = false; } -RendererSceneRenderForward::ShaderData::~ShaderData() { - RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; +RendererSceneRenderForwardClustered::ShaderData::~ShaderData() { + RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -414,21 +414,21 @@ RendererSceneRenderForward::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *RendererSceneRenderForward::_create_shader_func() { +RendererStorageRD::ShaderData *RendererSceneRenderForwardClustered::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); return shader_data; } -void RendererSceneRenderForward::MaterialData::set_render_priority(int p_priority) { +void RendererSceneRenderForwardClustered::MaterialData::set_render_priority(int p_priority) { priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits } -void RendererSceneRenderForward::MaterialData::set_next_pass(RID p_pass) { +void RendererSceneRenderForwardClustered::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -void RendererSceneRenderForward::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; +void RendererSceneRenderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { p_uniform_dirty = true; @@ -507,7 +507,7 @@ void RendererSceneRenderForward::MaterialData::update_parameters(const Map<Strin uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } -RendererSceneRenderForward::MaterialData::~MaterialData() { +RendererSceneRenderForwardClustered::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } @@ -517,7 +517,7 @@ RendererSceneRenderForward::MaterialData::~MaterialData() { } } -RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_func(ShaderData *p_shader) { +RendererStorageRD::MaterialData *RendererSceneRenderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -525,11 +525,11 @@ RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_fu return material_data; } -RendererSceneRenderForward::RenderBufferDataForward::~RenderBufferDataForward() { +RendererSceneRenderForwardClustered::RenderBufferDataForward::~RenderBufferDataForward() { clear(); } -void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() { +void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_specular() { if (!specular.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -583,7 +583,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() { } } -void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() { +void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_giprobe() { if (!giprobe_buffer.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8_UINT; @@ -619,7 +619,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() { } } -void RendererSceneRenderForward::RenderBufferDataForward::clear() { +void RendererSceneRenderForwardClustered::RenderBufferDataForward::clear() { if (giprobe_buffer != RID()) { RD::get_singleton()->free(giprobe_buffer); giprobe_buffer = RID(); @@ -673,7 +673,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::clear() { } } -void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { +void RendererSceneRenderForwardClustered::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { clear(); msaa = p_msaa; @@ -740,7 +740,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_ } } -void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) { +void RendererSceneRenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) { if (rb->normal_roughness_buffer.is_valid()) { return; } @@ -778,11 +778,11 @@ void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBuffer _render_buffers_clear_uniform_set(rb); } -RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForward::_create_render_buffer_data() { +RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForwardClustered::_create_render_buffer_data() { return memnew(RenderBufferDataForward); } -bool RendererSceneRenderForward::free(RID p_rid) { +bool RendererSceneRenderForwardClustered::free(RID p_rid) { if (RendererSceneRenderRD::free(p_rid)) { return true; } @@ -791,8 +791,8 @@ bool RendererSceneRenderForward::free(RID p_rid) { /// RENDERING /// -template <RendererSceneRenderForward::PassMode p_pass_mode> -void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { +template <RendererSceneRenderForwardClustered::PassMode p_pass_mode> +void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -961,7 +961,7 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList } } -void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { +void RendererSceneRenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { //use template for faster performance (pass mode comparisons are inlined) switch (p_params->pass_mode) { @@ -998,7 +998,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw } } -void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { +void RendererSceneRenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { uint32_t render_total = p_params->element_count; uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); uint32_t render_from = p_thread * render_total / total_threads; @@ -1006,7 +1006,7 @@ void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); } -void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +void RendererSceneRenderForwardClustered::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; @@ -1014,7 +1014,7 @@ void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters //multi threaded thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params); + RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForwardClustered::_render_list_thread_function, p_params); RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded @@ -1024,7 +1024,7 @@ void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters } } -void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { +void RendererSceneRenderForwardClustered::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { //CameraMatrix projection = p_cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; @@ -1274,7 +1274,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); } -void RendererSceneRenderForward::_update_instance_data_buffer(RenderListType p_render_list) { +void RendererSceneRenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { if (scene_state.instance_data[p_render_list].size() > 0) { if (scene_state.instance_buffer[p_render_list] == RID() || scene_state.instance_buffer_size[p_render_list] < scene_state.instance_data[p_render_list].size()) { if (scene_state.instance_buffer[p_render_list] != RID()) { @@ -1287,7 +1287,7 @@ void RendererSceneRenderForward::_update_instance_data_buffer(RenderListType p_r RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER); } } -void RendererSceneRenderForward::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { +void RendererSceneRenderForwardClustered::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { RenderList *rl = &render_list[p_render_list]; uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size(); @@ -1298,7 +1298,7 @@ void RendererSceneRenderForward::_fill_instance_data(RenderListType p_render_lis GeometryInstanceSurfaceDataCache *prev_surface = nullptr; for (uint32_t i = 0; i < element_total; i++) { GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset]; - GeometryInstanceForward *inst = surface->owner; + GeometryInstanceForwardClustered *inst = surface->owner; SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset]; @@ -1355,7 +1355,7 @@ void RendererSceneRenderForward::_fill_instance_data(RenderListType p_render_lis } } -void RendererSceneRenderForward::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { +void RendererSceneRenderForwardClustered::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1381,7 +1381,7 @@ void RendererSceneRenderForward::_fill_render_list(RenderListType p_render_list, //fill list for (int i = 0; i < (int)p_instances.size(); i++) { - GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]); + GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>(p_instances[i]); Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); inst->depth = near_plane.distance_to(support_min); @@ -1549,14 +1549,14 @@ void RendererSceneRenderForward::_fill_render_list(RenderListType p_render_list, } } -void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) { +void RendererSceneRenderForwardClustered::_setup_giprobes(const PagedArray<RID> &p_giprobes) { scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES)); for (uint32_t i = 0; i < scene_state.giprobes_used; i++) { scene_state.giprobe_ids[i] = p_giprobes[i]; } } -void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { +void RendererSceneRenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { scene_state.lightmaps_used = 0; for (int i = 0; i < (int)p_lightmaps.size(); i++) { if (i >= (int)scene_state.max_lightmaps) { @@ -1578,7 +1578,7 @@ void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_light } } -void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { +void RendererSceneRenderForwardClustered::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { RenderBufferDataForward *render_buffer = nullptr; if (p_render_buffer.is_valid()) { render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); @@ -1981,7 +1981,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_shadow_begin() { +void RendererSceneRenderForwardClustered::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); _update_render_base_uniform_set(); @@ -1989,7 +1989,7 @@ void RendererSceneRenderForward::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RendererSceneRenderForward::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) { +void RendererSceneRenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -2036,7 +2036,7 @@ void RendererSceneRenderForward::_render_shadow_append(RID p_framebuffer, const } } -void RendererSceneRenderForward::_render_shadow_process() { +void RendererSceneRenderForwardClustered::_render_shadow_process() { _update_instance_data_buffer(RENDER_LIST_SECONDARY); //render shadows one after the other, so this can be done un-barriered and the driver can optimize (as well as allow us to run compute at the same time) @@ -2048,7 +2048,7 @@ void RendererSceneRenderForward::_render_shadow_process() { RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_shadow_end(uint32_t p_barrier) { +void RendererSceneRenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_begin_label("Shadow Render"); for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { @@ -2063,7 +2063,7 @@ void RendererSceneRenderForward::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RendererSceneRenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup Render Collider Heightfield"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -2091,7 +2091,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForwardClustered::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering Material"); RD::get_singleton()->draw_command_begin_label("Render Material"); @@ -2129,7 +2129,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering UV2"); RD::get_singleton()->draw_command_begin_label("Render UV2"); @@ -2191,7 +2191,7 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance * RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { +void RendererSceneRenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { RENDER_TIMESTAMP("Render SDFGI"); RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel"); @@ -2272,14 +2272,14 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForward::_base_uniforms_changed() { +void RendererSceneRenderForwardClustered::_base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } render_base_uniform_set = RID(); } -void RendererSceneRenderForward::_update_render_base_uniform_set() { +void RendererSceneRenderForwardClustered::_update_render_base_uniform_set() { if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); @@ -2405,7 +2405,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() { } } -RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { +RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { //there should always be enough uniform buffers for render passes, otherwise bugs ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID()); @@ -2655,7 +2655,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RenderListType p_ return render_pass_uniform_sets[p_index]; } -RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { +RID RendererSceneRenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { RD::get_singleton()->free(sdfgi_pass_uniform_set); } @@ -2788,30 +2788,25 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed return sdfgi_pass_uniform_set; } -void RendererSceneRenderForward::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) { +void RendererSceneRenderForwardClustered::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) { } -void RendererSceneRenderForward::_render_buffers_uniform_set_changed(RID p_render_buffers) { +void RendererSceneRenderForwardClustered::_render_buffers_uniform_set_changed(RID p_render_buffers) { RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); _render_buffers_clear_uniform_set(rb); } -RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_buffers) { +RID RendererSceneRenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); return rb->normal_roughness_buffer; } -RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr; +RendererSceneRenderForwardClustered *RendererSceneRenderForwardClustered::singleton = nullptr; -void RendererSceneRenderForward::set_time(double p_time, double p_step) { - time = p_time; - RendererSceneRenderRD::set_time(p_time, p_step); -} - -void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); if (ginstance->dirty_list_element.in_list()) { return; } @@ -2830,7 +2825,7 @@ void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance geometry_instance_dirty_list.add(&ginstance->dirty_list_element); } -void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { +void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; @@ -2854,7 +2849,7 @@ void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(Ge flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE; } - if (ginstance->data->cast_double_sided_shaodows) { + if (ginstance->data->cast_double_sided_shadows) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; } @@ -2926,7 +2921,7 @@ void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(Ge sdcache->sort.priority = p_material->priority; } -void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { +void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; @@ -2966,8 +2961,8 @@ void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstance } } -void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { ginstance->data->dependency_tracker.update_begin(); @@ -3124,24 +3119,24 @@ void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_g ginstance->dirty_list_element.remove_from_list(); } -void RendererSceneRenderForward::_update_dirty_geometry_instances() { +void RendererSceneRenderForwardClustered::_update_dirty_geometry_instances() { while (geometry_instance_dirty_list.first()) { _geometry_instance_update(geometry_instance_dirty_list.first()->self()); } } -void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +void RendererSceneRenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { switch (p_notification) { case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: case RendererStorage::DEPENDENCY_CHANGED_MESH: case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } break; case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata); + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = static_cast<RendererSceneRenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { @@ -3149,16 +3144,16 @@ void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererS } break; } } -void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { - static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +void RendererSceneRenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { + static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } -RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) { +RendererSceneRender::GeometryInstance *RendererSceneRenderForwardClustered::geometry_instance_create(RID p_base) { RS::InstanceType type = storage->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); - GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc(); - ginstance->data = memnew(GeometryInstanceForward::Data); + GeometryInstanceForwardClustered *ginstance = geometry_instance_alloc.alloc(); + ginstance->data = memnew(GeometryInstanceForwardClustered::Data); ginstance->data->base = p_base; ginstance->data->base_type = type; @@ -3170,35 +3165,35 @@ RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_inst return ginstance; } -void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->data->skeleton = p_skeleton; _geometry_instance_mark_dirty(ginstance); ginstance->data->dirty_dependencies = true; } -void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->data->material_override = p_override; _geometry_instance_mark_dirty(ginstance); ginstance->data->dirty_dependencies = true; } -void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->data->surface_materials = p_materials; _geometry_instance_mark_dirty(ginstance); ginstance->data->dirty_dependencies = true; } -void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->mesh_instance = p_mesh_instance; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->transform = p_transform; ginstance->mirror = p_transform.basis.determinant() < 0; @@ -3214,33 +3209,33 @@ void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstanc ginstance->lod_model_scale = max_scale; } -void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->lod_bias = p_lod_bias; } -void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->data->use_baked_light = p_enable; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->data->use_dynamic_gi = p_enable; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->lightmap_instance = p_lightmap_instance; ginstance->lightmap_uv_scale = p_lightmap_uv_scale; ginstance->lightmap_slice_index = p_lightmap_slice_index; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (p_sh9) { if (ginstance->lightmap_sh == nullptr) { @@ -3256,28 +3251,28 @@ void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(Geometry } _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->shader_parameters_offset = p_offset; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); - ginstance->data->cast_double_sided_shaodows = p_enable; + ginstance->data->cast_double_sided_shadows = p_enable; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->layer_mask = p_layer_mask; } -void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (ginstance->lightmap_sh != nullptr) { geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); @@ -3292,29 +3287,29 @@ void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geom geometry_instance_alloc.free(ginstance); } -uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() { +uint32_t RendererSceneRenderForwardClustered::geometry_instance_get_pair_mask() { return (1 << RS::INSTANCE_GI_PROBE); } -void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { +void RendererSceneRenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { } -void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { +void RendererSceneRenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { } -void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { +void RendererSceneRenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { } -Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); +Transform RendererSceneRenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance); ERR_FAIL_COND_V(!ginstance, Transform()); return ginstance->transform; } -AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); +AABB RendererSceneRenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance); ERR_FAIL_COND_V(!ginstance, AABB()); return ginstance->data->aabb; } -void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { - GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +void RendererSceneRenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (p_gi_probe_instance_count > 0) { ginstance->gi_probes[0] = p_gi_probe_instances[0]; @@ -3329,11 +3324,10 @@ void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(Geome } } -RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) : +RendererSceneRenderForwardClustered::RendererSceneRenderForwardClustered(RendererStorageRD *p_storage) : RendererSceneRenderRD(p_storage) { singleton = this; low_end = is_low_end(); - storage = p_storage; /* SCENE SHADER */ @@ -3628,7 +3622,7 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); } -RendererSceneRenderForward::~RendererSceneRenderForward() { +RendererSceneRenderForwardClustered::~RendererSceneRenderForwardClustered() { directional_shadow_atlas_set_size(0); //clear base uniform set if still valid diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h index af78c50fda..98e2a7efcc 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_render_forward.h */ +/* renderer_scene_render_forward_clustered.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H -#define RENDERING_SERVER_SCENE_RENDER_FORWARD_H +#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H +#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" -#include "servers/rendering/renderer_rd/shaders/scene_forward.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" -class RendererSceneRenderForward : public RendererSceneRenderRD { +class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { enum { SCENE_UNIFORM_SET = 0, RENDER_PASS_UNIFORM_SET = 1, @@ -79,12 +79,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { }; struct { - SceneForwardShaderRD scene_shader; + SceneForwardClusteredShaderRD scene_shader; ShaderCompilerRD compiler; } shader; - RendererStorageRD *storage; - /* Material */ struct ShaderData : public RendererStorageRD::ShaderData { @@ -186,7 +184,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { RendererStorageRD::ShaderData *_create_shader_func(); static RendererStorageRD::ShaderData *_create_shader_funcs() { - return static_cast<RendererSceneRenderForward *>(singleton)->_create_shader_func(); + return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_shader_func(); } struct MaterialData : public RendererStorageRD::MaterialData { @@ -208,7 +206,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { - return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } /* Framebuffer */ @@ -490,9 +488,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { } scene_state; - static RendererSceneRenderForward *singleton; + static RendererSceneRenderForwardClustered *singleton; - double time; RID default_shader; RID default_material; RID overdraw_material_shader; @@ -534,7 +531,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { Map<Size2i, RID> sdfgi_framebuffer_size_cache; struct GeometryInstanceData; - struct GeometryInstanceForward; + struct GeometryInstanceForwardClustered; struct GeometryInstanceLightmapSH { Color sh[9]; @@ -588,10 +585,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { ShaderData *shader_shadow = nullptr; GeometryInstanceSurfaceDataCache *next = nullptr; - GeometryInstanceForward *owner = nullptr; + GeometryInstanceForwardClustered *owner = nullptr; }; - struct GeometryInstanceForward : public GeometryInstance { + struct GeometryInstanceForwardClustered : public GeometryInstance { //used during rendering bool mirror = false; bool non_uniform_scale = false; @@ -617,7 +614,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { RID lightmap_instance; GeometryInstanceLightmapSH *lightmap_sh = nullptr; GeometryInstanceSurfaceDataCache *surface_caches = nullptr; - SelfList<GeometryInstanceForward> dirty_list_element; + SelfList<GeometryInstanceForwardClustered> dirty_list_element; struct Data { //data used less often goes into regular heap @@ -631,7 +628,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { bool use_dynamic_gi = false; bool use_baked_light = false; - bool cast_double_sided_shaodows = false; + bool cast_double_sided_shadows = false; bool mirror = false; bool dirty_dependencies = false; @@ -640,21 +637,21 @@ class RendererSceneRenderForward : public RendererSceneRenderRD { Data *data = nullptr; - GeometryInstanceForward() : + GeometryInstanceForwardClustered() : dirty_list_element(this) {} }; static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); - SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list; + SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list; - PagedAllocator<GeometryInstanceForward> geometry_instance_alloc; + PagedAllocator<GeometryInstanceForwardClustered> geometry_instance_alloc; PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc; PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; - void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); - void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); + void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); void _geometry_instance_update(GeometryInstance *p_geometry_instance); void _update_dirty_geometry_instances(); @@ -761,11 +758,9 @@ public: virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count); virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count); - virtual void set_time(double p_time, double p_step); - virtual bool free(RID p_rid); - RendererSceneRenderForward(RendererStorageRD *p_storage); - ~RendererSceneRenderForward(); + RendererSceneRenderForwardClustered(RendererStorageRD *p_storage); + ~RendererSceneRenderForwardClustered(); }; -#endif // RASTERIZER_SCENE_HIGHEND_RD_H +#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index f9ee01e751..4cf296f0db 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -4097,17 +4097,14 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { low_end = true; } - if (!low_end) { - gi.init_gi(storage); - } - /* SKY SHADER */ sky.init(storage); + /* GI */ + if (!low_end) { - //SDFGI - gi.init_sdfgi(&sky); + gi.init(storage, &sky); } { //decals diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index eefaf237a4..001cfeb74d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -48,6 +48,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneGIRD; protected: + RendererStorageRD *storage; double time; double time_step = 0; @@ -111,8 +112,6 @@ private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; static RendererSceneRenderRD *singleton; - RendererStorageRD *storage; - /* REFLECTION ATLAS */ struct ReflectionAtlas { @@ -1183,7 +1182,7 @@ public: return debug_draw; } - virtual void set_time(double p_time, double p_step); + void set_time(double p_time, double p_step); RID get_reflection_probe_buffer(); RID get_omni_light_buffer(); diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index c192574ff2..0f85e3fa30 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -11,7 +11,7 @@ if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("cubemap_roughness.glsl") env.RD_GLSL("cubemap_downsampler.glsl") env.RD_GLSL("cubemap_filter.glsl") - env.RD_GLSL("scene_forward.glsl") + env.RD_GLSL("scene_forward_clustered.glsl") env.RD_GLSL("sky.glsl") env.RD_GLSL("tonemap.glsl") env.RD_GLSL("cube_to_dp.glsl") diff --git a/servers/rendering/renderer_rd/shaders/scene_forward.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 1cea9bf8db..7b86dac143 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -4,7 +4,7 @@ VERSION_DEFINES -#include "scene_forward_inc.glsl" +#include "scene_forward_clustered_inc.glsl" /* INPUT ATTRIBS */ @@ -327,7 +327,7 @@ VERTEX_SHADER_CODE VERSION_DEFINES -#include "scene_forward_inc.glsl" +#include "scene_forward_clustered_inc.glsl" /* Varyings */ diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index d78890fa9e..d78890fa9e 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl diff --git a/tests/test_string.h b/tests/test_string.h index 17f24fb0d8..6febf22765 100644 --- a/tests/test_string.h +++ b/tests/test_string.h @@ -1318,6 +1318,20 @@ TEST_CASE("[String] humanize_size") { CHECK(String::humanize_size(100523550) == "95.86 MiB"); CHECK(String::humanize_size(5345555000) == "4.97 GiB"); } + +TEST_CASE("[String] validate_node_name") { + String numeric_only = "12345"; + CHECK(numeric_only.validate_node_name() == "12345"); + + String name_with_spaces = "Name with spaces"; + CHECK(name_with_spaces.validate_node_name() == "Name with spaces"); + + String name_with_kana = "Name with kana ゴドツ"; + CHECK(name_with_kana.validate_node_name() == "Name with kana ゴドツ"); + + String name_with_invalid_chars = "Name with invalid characters :.@removed!"; + CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!"); +} } // namespace TestString #endif // TEST_STRING_H diff --git a/thirdparty/README.md b/thirdparty/README.md index 3803e87fea..efeefedbdd 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -324,7 +324,7 @@ changes are marked with `// -- GODOT --` comments. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.16.9 (3fac0bae4a50113989b3d015cd2d948f51a6d9ac, 2020) +- Version: 2.16.10 (d61fa61bef06b64132e3490543c81b8ee40fbee3, 2021) - License: Apache 2.0 File extracted from upstream release tarball: diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index e17bc7e306..610f5d1f50 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -1747,6 +1747,23 @@ //#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT /** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** * \def MBEDTLS_THREADING_ALT * * Provide your own alternate threading implementation. diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index 278fbbbb7a..6c099adf4d 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -214,6 +214,13 @@ typedef struct mbedtls_ctr_drbg_context void *p_entropy; /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ mbedtls_threading_mutex_t mutex; #endif } @@ -277,6 +284,15 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * device. */ #endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ /** * \param ctx The CTR_DRBG context to seed. * It must have been initialized with @@ -286,6 +302,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * the same context unless you call * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. @@ -377,6 +395,11 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, * \brief This function reseeds the CTR_DRBG context, that is * extracts data from the entropy source. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The CTR_DRBG context. * \param additional Additional data to add to the state. Can be \c NULL. * \param len The length of the additional data. @@ -394,6 +417,11 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, /** * \brief This function updates the state of the CTR_DRBG context. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. This must not be * \c NULL unless \p add_len is \c 0. @@ -417,6 +445,11 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. @@ -445,8 +478,16 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. - * - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index 1e1d3f56ec..1d6e9b821b 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -147,13 +147,15 @@ mbedtls_entropy_source_state; */ typedef struct mbedtls_entropy_context { - int accumulator_started; + int accumulator_started; /* 0 after init. + * 1 after the first update. + * -1 after free. */ #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_context accumulator; #else mbedtls_sha256_context accumulator; #endif - int source_count; + int source_count; /* Number of entries used in source. */ mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_state havege_data; diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 970c033c15..5718e187a9 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -128,6 +128,14 @@ typedef struct mbedtls_hmac_drbg_context void *p_entropy; /*!< context for the entropy function */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ mbedtls_threading_mutex_t mutex; #endif } mbedtls_hmac_drbg_context; @@ -177,7 +185,17 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); * \note During the initial seeding, this function calls * the entropy source to obtain a nonce * whose length is half the entropy length. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param ctx HMAC_DRBG context to be seeded. * \param md_info MD algorithm to use for HMAC_DRBG. * \param f_entropy The entropy callback, taking as arguments the @@ -216,7 +234,17 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, * * This function is meant for use in algorithms that need a pseudorandom * input such as deterministic ECDSA. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param ctx HMAC_DRBG context to be initialised. * \param md_info MD algorithm to use for HMAC_DRBG. * \param data Concatenation of the initial entropy string and @@ -279,6 +307,11 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, /** * \brief This function updates the state of the HMAC_DRBG context. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The HMAC_DRBG context. * \param additional The data to update the state with. * If this is \c NULL, there is no additional data. @@ -295,6 +328,11 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, * \brief This function reseeds the HMAC_DRBG context, that is * extracts data from the entropy source. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The HMAC_DRBG context. * \param additional Additional data to add to the state. * If this is \c NULL, there is no additional data @@ -320,6 +358,11 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. @@ -349,7 +392,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 00fea7db19..c6e1a0270e 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -151,6 +151,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_LISTEN_FAILED * @@ -170,6 +171,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * can be NULL if client_ip is null * * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_ACCEPT_FAILED, or * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to @@ -182,6 +185,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, /** * \brief Check and wait for the context to be ready for read/write * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * * \param ctx Socket to check * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and * MBEDTLS_NET_POLL_WRITE specifying the events @@ -263,16 +270,21 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); * 'timeout' seconds. If no error occurs, the actual amount * read is returned. * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (wait forever) * - * \return the number of bytes received, - * or a non-zero error code: - * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \return The number of bytes received if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. * * \note This function will block (until data becomes available or * timeout is reached) even if the socket is set to diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 188c37cf3a..b2f65334fe 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -124,7 +124,10 @@ extern "C" { */ typedef struct mbedtls_rsa_context { - int ver; /*!< Always 0.*/ + int ver; /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ size_t len; /*!< The size of \p N in Bytes. */ mbedtls_mpi N; /*!< The public modulus. */ @@ -154,6 +157,7 @@ typedef struct mbedtls_rsa_context mask generating function used in the EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ #endif } diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index a8183a6ef4..45161ce467 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -73,6 +73,9 @@ extern "C" { typedef struct mbedtls_threading_mutex_t { pthread_mutex_t mutex; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ char is_valid; } mbedtls_threading_mutex_t; #endif diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index 5f0a8f114c..bd5c730c1d 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -65,16 +65,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 16 -#define MBEDTLS_VERSION_PATCH 9 +#define MBEDTLS_VERSION_PATCH 10 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02100900 -#define MBEDTLS_VERSION_STRING "2.16.9" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.9" +#define MBEDTLS_VERSION_NUMBER 0x02100A00 +#define MBEDTLS_VERSION_STRING "2.16.10" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c index bfafb05353..692e11e3fa 100644 --- a/thirdparty/mbedtls/library/base64.c +++ b/thirdparty/mbedtls/library/base64.c @@ -97,6 +97,99 @@ static const unsigned char base64_dec_map[128] = #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ /* + * Constant flow conditional assignment to unsigned char + */ +static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src, + unsigned char condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFF or 0 */ + unsigned char mask = ( condition | -condition ); + mask >>= 7; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow conditional assignment to uint_32 + */ +static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src, + uint32_t condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */ + uint32_t mask = ( condition | -condition ); + mask >>= 31; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( src & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow check for equality + */ +static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b ) +{ + size_t difference = in_a ^ in_b; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + difference |= -difference; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* cope with the varying size of size_t per platform */ + difference >>= ( sizeof( difference ) * 8 - 1 ); + + return (unsigned char) ( 1 ^ difference ); +} + +/* + * Constant flow lookup into table. + */ +static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table, + const size_t table_size, const size_t table_index ) +{ + size_t i; + unsigned char result = 0; + + for( i = 0; i < table_size; ++i ) + { + mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) ); + } + + return result; +} + +/* * Encode a buffer into base64 format */ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, @@ -136,10 +229,17 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, C2 = *src++; C3 = *src++; - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; - *p++ = base64_enc_map[C3 & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( C3 & 0x3F ) ); } if( i < slen ) @@ -147,11 +247,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, C1 = *src++; C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); if( ( i + 1 ) < slen ) - *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( C2 & 15 ) << 2 ) & 0x3F ) ); else *p++ = '='; *p++ = '='; @@ -172,6 +276,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, size_t i, n; uint32_t j, x; unsigned char *p; + unsigned char dec_map_lookup; /* First pass: check for validity and get output length */ for( i = n = j = 0; i < slen; i++ ) @@ -202,10 +307,12 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, if( src[i] == '=' && ++j > 2 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] ); + + if( src[i] > 127 || dec_map_lookup == 127 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - if( base64_dec_map[src[i]] < 64 && j != 0 ) + if( dec_map_lookup < 64 && j != 0 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); n++; @@ -235,8 +342,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, if( *src == '\r' || *src == '\n' || *src == ' ' ) continue; - j -= ( base64_dec_map[*src] == 64 ); - x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src ); + + mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) ); + x = ( x << 6 ) | ( dec_map_lookup & 0x3F ); if( ++n == 4 ) { diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 2feb727d89..f133f6c13c 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -1354,6 +1354,12 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi for( n = B->n; n > 0; n-- ) if( B->p[n - 1] != 0 ) break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } carry = mpi_sub_hlp( n, X->p, B->p ); if( carry != 0 ) diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index e92008bbe8..90264e844a 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -83,10 +83,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } /* @@ -99,14 +95,13 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) return; #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_aes_free( &ctx->aes_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) @@ -422,6 +417,11 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + mbedtls_aes_init( &ctx->aes_ctx ); ctx->f_entropy = f_entropy; diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index da8df9cde2..2456238b17 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -247,6 +247,9 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) #endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ + !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 @@ -269,6 +272,7 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, cleanup: return( ret ); } +#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /* @@ -780,6 +784,8 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, (void) md_alg; #if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) rs_ctx; + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); #else @@ -888,6 +894,8 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) + (void) rs_ctx; + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index f6e24580c7..0532a295e6 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -850,6 +850,8 @@ static const unsigned char ecjpake_test_password[] = { 0x65, 0x73, 0x74 }; +#if !defined(MBEDTLS_ECJPAKE_ALT) + static const unsigned char ecjpake_test_x1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, @@ -994,6 +996,8 @@ cleanup: return( ret ); } +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + /* For tests we don't need a secure RNG; * use the LGC from Numerical Recipes for simplicity */ static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) @@ -1089,6 +1093,12 @@ int mbedtls_ecjpake_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); +#if !defined(MBEDTLS_ECJPAKE_ALT) + /* 'reference handshake' tests can only be run against implementations + * for which we have 100% control over how the random ephemeral keys + * are generated. This is only the case for the internal mbed TLS + * implementation, so these tests are skipped in case the internal + * implementation is swapped out for an alternative one. */ if( verbose != 0 ) mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); @@ -1137,6 +1147,7 @@ int mbedtls_ecjpake_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); +#endif /* ! MBEDTLS_ECJPAKE_ALT */ cleanup: mbedtls_ecjpake_free( &cli ); diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c index 666c55654c..c5f414a010 100644 --- a/thirdparty/mbedtls/library/entropy.c +++ b/thirdparty/mbedtls/library/entropy.c @@ -146,6 +146,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) { + /* If the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_free( &ctx->havege_data ); #endif @@ -162,7 +167,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) #endif ctx->source_count = 0; mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); - ctx->accumulator_started = 0; + ctx->accumulator_started = -1; } int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index 10cbd462ba..b45d61616f 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -84,10 +84,6 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } /* @@ -159,6 +155,10 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) return( ret ); +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the @@ -284,6 +284,11 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) return( ret ); + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + md_size = mbedtls_md_get_size( md_info ); /* @@ -451,14 +456,13 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) return; #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_md_free( &ctx->md_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } #if defined(MBEDTLS_FS_IO) diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 1130408263..671115f15f 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -496,6 +496,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) if( fd < 0 ) return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + #if defined(__has_feature) #if __has_feature(memory_sanitizer) /* Ensure that memory sanitizers consider read_fds and write_fds as @@ -615,6 +622,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, if( fd < 0 ) return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + FD_ZERO( &read_fds ); FD_SET( fd, &read_fds ); diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index 150626c147..a770dfb93e 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -455,7 +455,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 * } */ -#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE +#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE ) /* * RSA private keys: @@ -472,10 +472,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) * } */ -#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ - MBEDTLS_MPI_MAX_SIZE % 2 -#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ - + 5 * MPI_MAX_SIZE_2 +#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 ) +#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 ) #else /* MBEDTLS_RSA_C */ @@ -496,7 +496,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * + 2 * ECP_MAX (coords) [1] * } */ -#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) /* * EC private keys: @@ -507,7 +507,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above * } */ -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) #else /* MBEDTLS_ECP_C */ @@ -516,10 +516,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ #endif /* MBEDTLS_ECP_C */ -#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ - RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES -#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ - RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES +#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES ) +#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES ) int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index a25c633bc6..c8c23dba8c 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -520,6 +520,9 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, mbedtls_rsa_set_padding( ctx, padding, hash_id ); #if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; mbedtls_mutex_init( &ctx->mutex ); #endif } @@ -567,9 +570,6 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, RSA_VALIDATE_RET( ctx != NULL ); RSA_VALIDATE_RET( f_rng != NULL ); - if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - /* * If the modulus is 1024 bit long or shorter, then the security strength of * the RSA algorithm is less than or equal to 80 bits and therefore an error @@ -582,6 +582,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, mbedtls_mpi_init( &G ); mbedtls_mpi_init( &L ); + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + /* * find primes P and Q with Q < P so that: * 1. |P-Q| > 2^( nbits / 2 - 100 ) @@ -659,7 +665,9 @@ cleanup: if( ret != 0 ) { mbedtls_rsa_free( ctx ); - return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret; + return( ret ); } return( 0 ); @@ -1106,10 +1114,10 @@ cleanup: mbedtls_mpi_free( &C ); mbedtls_mpi_free( &I ); - if( ret != 0 ) + if( ret != 0 && ret >= -0x007f ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); - return( 0 ); + return( ret ); } #if defined(MBEDTLS_PKCS1_V21) @@ -2502,7 +2510,6 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) RSA_VALIDATE_RET( dst != NULL ); RSA_VALIDATE_RET( src != NULL ); - dst->ver = src->ver; dst->len = src->len; MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); @@ -2561,7 +2568,12 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } #endif } diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index f4f29cff5e..0dc5488c1a 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -98,6 +98,12 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) if( mutex == NULL ) return; + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see helpers.function for + * details. */ mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; } diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index cbf38dc2c2..8c8e815e9d 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -553,6 +553,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", #endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_THREADING_ALT) "MBEDTLS_THREADING_ALT", #endif /* MBEDTLS_THREADING_ALT */ |