diff options
Diffstat (limited to 'core')
31 files changed, 232 insertions, 140 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index db3191334a..00e74a7cce 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1286,6 +1286,10 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF(PropertyInfo(Variant::STRING, "editor/script/templates_search_path", PROPERTY_HINT_DIR), "res://script_templates"); + // For correct doc generation. + GLOBAL_DEF("editor/naming/default_signal_callback_name", "_on_{node_name}_{signal_name}"); + GLOBAL_DEF("editor/naming/default_signal_callback_to_self_name", "_on_{signal_name}"); + _add_builtin_input_map(); // Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum. diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 96e1da9dde..9de901754a 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1105,8 +1105,8 @@ void Semaphore::wait() { semaphore.wait(); } -Error Semaphore::try_wait() { - return semaphore.try_wait() ? OK : ERR_BUSY; +bool Semaphore::try_wait() { + return semaphore.try_wait(); } void Semaphore::post() { @@ -1125,7 +1125,7 @@ void Mutex::lock() { mutex.lock(); } -Error Mutex::try_lock() { +bool Mutex::try_lock() { return mutex.try_lock(); } diff --git a/core/core_bind.h b/core/core_bind.h index c0c87fd009..8852463234 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -361,7 +361,7 @@ class Mutex : public RefCounted { public: void lock(); - Error try_lock(); + bool try_lock(); void unlock(); }; @@ -373,7 +373,7 @@ class Semaphore : public RefCounted { public: void wait(); - Error try_wait(); + bool try_wait(); void post(); }; diff --git a/core/core_constants.cpp b/core/core_constants.cpp index e28f7bfc4f..b1f56539e5 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -586,7 +586,8 @@ void register_global_constants() { BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_ENUM); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NIL_IS_VARIANT); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ARRAY); - BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE); + BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ALWAYS_DUPLICATE); + BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NEVER_DUPLICATE); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_HIGH_END_GFX); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT); diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 7be14b741d..e26ead6d8c 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -82,6 +82,11 @@ static String get_property_info_type_name(const PropertyInfo &p_info) { return get_builtin_or_variant_type_name(p_info.type); } +static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) { + static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" }; + return argmeta[metadata]; +} + Dictionary GDExtensionAPIDump::generate_extension_api() { Dictionary api_dump; @@ -840,6 +845,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() { d3["type"] = get_property_info_type_name(pinfo); + if (mi.get_argument_meta(i) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(i)); + } + if (i == -1) { d2["return_value"] = d3; } else { @@ -884,8 +893,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api() { d3["type"] = get_property_info_type_name(pinfo); if (method->get_argument_meta(i) > 0) { - static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" }; - d3["meta"] = argmeta[method->get_argument_meta(i)]; + d3["meta"] = get_type_meta_name(method->get_argument_meta(i)); } if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) { @@ -929,6 +937,9 @@ Dictionary GDExtensionAPIDump::generate_extension_api() { Dictionary d3; d3["name"] = F.arguments[i].name; d3["type"] = get_property_info_type_name(F.arguments[i]); + if (F.get_argument_meta(i) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i)); + } arguments.push_back(d3); } if (arguments.size()) { diff --git a/core/input/input.cpp b/core/input/input.cpp index 1ea9f00fee..3cf83fd64b 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -349,8 +349,8 @@ float Input::get_axis(const StringName &p_negative_action, const StringName &p_p Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone) const { Vector2 vector = Vector2( - get_action_raw_strength(p_positive_x) - get_action_raw_strength(p_negative_x), - get_action_raw_strength(p_positive_y) - get_action_raw_strength(p_negative_y)); + get_action_strength(p_positive_x) - get_action_strength(p_negative_x), + get_action_strength(p_positive_y) - get_action_strength(p_negative_y)); if (p_deadzone < 0.0f) { // If the deadzone isn't specified, get it from the average of the actions. diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index dbe9b55ee3..5a9ec74184 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -478,7 +478,6 @@ Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) { Ref<InputEventKey> ie; ie.instantiate(); ie->set_keycode(p_keycode & KeyModifierMask::CODE_MASK); - ie->set_key_label(p_keycode & KeyModifierMask::CODE_MASK); ie->set_unicode(char32_t(p_keycode & KeyModifierMask::CODE_MASK)); if ((p_keycode & KeyModifierMask::SHIFT) != Key::NONE) { @@ -1500,7 +1499,18 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool p_exact } String InputEventAction::as_text() const { - return vformat(RTR("Input Action %s was %s"), action, pressed ? "pressed" : "released"); + const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(action); + if (!events) { + return String(); + } + + for (const Ref<InputEvent> &E : *events) { + if (E.is_valid()) { + return E->as_text(); + } + } + + return String(); } String InputEventAction::to_string() { diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 6d3575b9fa..4abcbffb61 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -260,15 +260,35 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { } Variant p = get(E.name); - if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) { - r->set(E.name, p.duplicate(p_subresources)); - } else if (p.get_type() == Variant::OBJECT && (p_subresources || (E.usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) { - Ref<Resource> sr = p; - if (sr.is_valid()) { - r->set(E.name, sr->duplicate(p_subresources)); + switch (p.get_type()) { + case Variant::Type::DICTIONARY: + case Variant::Type::ARRAY: + case Variant::Type::PACKED_BYTE_ARRAY: + case Variant::Type::PACKED_COLOR_ARRAY: + case Variant::Type::PACKED_INT32_ARRAY: + case Variant::Type::PACKED_INT64_ARRAY: + case Variant::Type::PACKED_FLOAT32_ARRAY: + case Variant::Type::PACKED_FLOAT64_ARRAY: + case Variant::Type::PACKED_STRING_ARRAY: + case Variant::Type::PACKED_VECTOR2_ARRAY: + case Variant::Type::PACKED_VECTOR3_ARRAY: { + r->set(E.name, p.duplicate(p_subresources)); + } break; + + case Variant::Type::OBJECT: { + if (!(E.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && (p_subresources || (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE))) { + Ref<Resource> sr = p; + if (sr.is_valid()) { + r->set(E.name, sr->duplicate(p_subresources)); + } + } else { + r->set(E.name, p); + } + } break; + + default: { + r->set(E.name, p); } - } else { - r->set(E.name, p); } } diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 646bdea758..f0f160940d 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -327,7 +327,7 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) { bool found_route = false; - Vector<Point *> open_list; + LocalVector<Point *> open_list; SortArray<Point *, SortPoints> sorter; begin_point->g_score = 0; @@ -335,19 +335,19 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) { open_list.push_back(begin_point); while (!open_list.is_empty()) { - Point *p = open_list[0]; // The currently processed point + Point *p = open_list[0]; // The currently processed point. if (p == end_point) { found_route = true; break; } - sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list + sorter.pop_heap(0, open_list.size(), open_list.ptr()); // Remove the current point from the open list. open_list.remove_at(open_list.size() - 1); - p->closed_pass = pass; // Mark the point as closed + p->closed_pass = pass; // Mark the point as closed. for (OAHashMap<int64_t, Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) { - Point *e = *(it.value); // The neighbor point + Point *e = *(it.value); // The neighbor point. if (!e->enabled || e->closed_pass == pass) { continue; @@ -370,9 +370,9 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) { e->f_score = e->g_score + _estimate_cost(e->id, end_point->id); if (new_point) { // The position of the new points is already known. - sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw()); + sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptr()); } else { - sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw()); + sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptr()); } } } diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp index 677e609763..139dc3afb1 100644 --- a/core/math/a_star_grid_2d.cpp +++ b/core/math/a_star_grid_2d.cpp @@ -265,7 +265,7 @@ AStarGrid2D::Point *AStarGrid2D::_jump(Point *p_from, Point *p_to) { return nullptr; } -void AStarGrid2D::_get_nbors(Point *p_point, List<Point *> &r_nbors) { +void AStarGrid2D::_get_nbors(Point *p_point, LocalVector<Point *> &r_nbors) { bool ts0 = false, td0 = false, ts1 = false, td1 = false, ts2 = false, td2 = false, @@ -378,7 +378,7 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) { bool found_route = false; - Vector<Point *> open_list; + LocalVector<Point *> open_list; SortArray<Point *, SortPoints> sorter; p_begin_point->g_score = 0; @@ -394,14 +394,14 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) { break; } - sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list. + sorter.pop_heap(0, open_list.size(), open_list.ptr()); // Remove the current point from the open list. open_list.remove_at(open_list.size() - 1); p->closed_pass = pass; // Mark the point as closed. - List<Point *> nbors; + LocalVector<Point *> nbors; _get_nbors(p, nbors); - for (List<Point *>::Element *E = nbors.front(); E; E = E->next()) { - Point *e = E->get(); // The neighbor point. + + for (Point *e : nbors) { real_t weight_scale = 1.0; if (jumping_enabled) { @@ -433,9 +433,9 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) { e->f_score = e->g_score + _estimate_cost(e->id, p_end_point->id); if (new_point) { // The position of the new points is already known. - sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw()); + sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptr()); } else { - sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw()); + sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptr()); } } } diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h index 6b9012a5e3..e4e62ec360 100644 --- a/core/math/a_star_grid_2d.h +++ b/core/math/a_star_grid_2d.h @@ -124,7 +124,7 @@ private: // Internal routines. return &points[p_y][p_x]; } - void _get_nbors(Point *p_point, List<Point *> &r_nbors); + void _get_nbors(Point *p_point, LocalVector<Point *> &r_nbors); Point *_jump(Point *p_from, Point *p_to); bool _solve(Point *p_begin_point, Point *p_end_point); diff --git a/core/math/bvh.h b/core/math/bvh.h index 357d483375..ea8289607e 100644 --- a/core/math/bvh.h +++ b/core/math/bvh.h @@ -780,7 +780,7 @@ private: if (p_thread_safe) { _mutex = p_mutex; - if (_mutex->try_lock() != OK) { + if (!_mutex->try_lock()) { WARN_PRINT("Info : multithread BVH access detected (benign)"); _mutex->lock(); } diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index 4786110054..590483bf20 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -151,7 +151,7 @@ void Geometry3D::MeshData::optimize_vertices() { } } - for (MeshData::Edge edge : edges) { + for (MeshData::Edge &edge : edges) { int a = edge.vertex_a; int b = edge.vertex_b; diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 910995d717..96010b4096 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -263,39 +263,12 @@ real_t Transform2D::basis_determinant() const { return columns[0].x * columns[1].y - columns[0].y * columns[1].x; } -Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const { - //extract parameters - Vector2 p1 = get_origin(); - Vector2 p2 = p_transform.get_origin(); - - real_t r1 = get_rotation(); - real_t r2 = p_transform.get_rotation(); - - Size2 s1 = get_scale(); - Size2 s2 = p_transform.get_scale(); - - //slerp rotation - Vector2 v1(Math::cos(r1), Math::sin(r1)); - Vector2 v2(Math::cos(r2), Math::sin(r2)); - - real_t dot = v1.dot(v2); - - dot = CLAMP(dot, (real_t)-1.0, (real_t)1.0); - - Vector2 v; - - if (dot > 0.9995f) { - v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues - } else { - real_t angle = p_c * Math::acos(dot); - Vector2 v3 = (v2 - v1 * dot).normalized(); - v = v1 * Math::cos(angle) + v3 * Math::sin(angle); - } - - //construct matrix - Transform2D res(v.angle(), p1.lerp(p2, p_c)); - res.scale_basis(s1.lerp(s2, p_c)); - return res; +Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_weight) const { + return Transform2D( + Math::lerp_angle(get_rotation(), p_transform.get_rotation(), p_weight), + get_scale().lerp(p_transform.get_scale(), p_weight), + Math::lerp_angle(get_skew(), p_transform.get_skew(), p_weight), + get_origin().lerp(p_transform.get_origin(), p_weight)); } void Transform2D::operator*=(const real_t p_val) { diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 0ee95835a6..18f27ae4a4 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -72,6 +72,7 @@ def generate_version(argcount, const=False, returns=False): s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;") method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n" + method_info += "\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;\\\n" else: s = s.replace("$RET", "") s = s.replace("$RVOID", "") @@ -113,6 +114,9 @@ def generate_version(argcount, const=False, returns=False): ) callptrargsptr += "&argval" + str(i + 1) method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n" + method_info += ( + "\tmethod_info.arguments_metadata.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::METADATA);\\\n" + ) if argcount: callsiargs += "};\\\n" diff --git a/core/object/object.cpp b/core/object/object.cpp index 2cb56dfe6c..57aa1339ec 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -499,7 +499,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 user-friendliness - p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NEVER_DUPLICATE)); } if (script_instance && !p_reversed) { @@ -1549,7 +1549,9 @@ void Object::_bind_methods() { #define BIND_OBJ_CORE_METHOD(m_method) \ ::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true); - BIND_OBJ_CORE_METHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what"))); + MethodInfo notification_mi("_notification", PropertyInfo(Variant::INT, "what")); + notification_mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32); + BIND_OBJ_CORE_METHOD(notification_mi); BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value"))); #ifdef TOOLS_ENABLED MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property")); diff --git a/core/object/object.h b/core/object/object.h index f78c7c34fd..5ec69a371b 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -109,15 +109,16 @@ enum PropertyUsageFlags { PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16, PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17, PROPERTY_USAGE_ARRAY = 1 << 18, // Used in the inspector to group properties as elements of an array. - PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 19, // If the object is duplicated also this property will be duplicated. - PROPERTY_USAGE_HIGH_END_GFX = 1 << 20, - PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 21, - PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 22, - PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 23, // Used in inspector to increment property when keyed in animation player. - PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 24, // when loading, the resource for this property can be set at the end of loading. - PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 25, // For Object properties, instantiate them when creating in editor. - PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 26, //for project or editor settings, show when basic settings are selected. - PROPERTY_USAGE_READ_ONLY = 1 << 27, // Mark a property as read-only in the inspector. + PROPERTY_USAGE_ALWAYS_DUPLICATE = 1 << 19, // When duplicating a resource, always duplicate, even with subresource duplication disabled. + PROPERTY_USAGE_NEVER_DUPLICATE = 1 << 20, // When duplicating a resource, never duplicate, even with subresource duplication enabled. + PROPERTY_USAGE_HIGH_END_GFX = 1 << 21, + PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 22, + PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 23, + PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 24, // Used in inspector to increment property when keyed in animation player. + PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // when loading, the resource for this property can be set at the end of loading. + PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor. + PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected. + PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector. PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR, PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE, @@ -222,6 +223,16 @@ struct MethodInfo { int id = 0; List<PropertyInfo> arguments; Vector<Variant> default_arguments; + int return_val_metadata = 0; + Vector<int> arguments_metadata; + + int get_argument_meta(int p_arg) const { + ERR_FAIL_COND_V(p_arg < -1 || p_arg > arguments.size(), 0); + if (p_arg == -1) { + return return_val_metadata; + } + return arguments_metadata.size() > p_arg ? arguments_metadata[p_arg] : 0; + } inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; } inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); } diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 6315356510..84017e89a6 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -124,8 +124,6 @@ enum class Key { KP_7 = SPECIAL | 0x8D, KP_8 = SPECIAL | 0x8E, KP_9 = SPECIAL | 0x8F, - SUPER_L = SPECIAL | 0x40, - SUPER_R = SPECIAL | 0x41, MENU = SPECIAL | 0x42, HYPER = SPECIAL | 0x43, HELP = SPECIAL | 0x45, diff --git a/core/os/mutex.h b/core/os/mutex.h index c91917a9a1..ceedcb235a 100644 --- a/core/os/mutex.h +++ b/core/os/mutex.h @@ -31,7 +31,6 @@ #ifndef MUTEX_H #define MUTEX_H -#include "core/error/error_list.h" #include "core/typedefs.h" #include <mutex> @@ -49,8 +48,8 @@ public: mutex.unlock(); } - _ALWAYS_INLINE_ Error try_lock() const { - return mutex.try_lock() ? OK : ERR_BUSY; + _ALWAYS_INLINE_ bool try_lock() const { + return mutex.try_lock(); } }; diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index e290b7c00b..a232fcb1ce 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -31,7 +31,7 @@ #ifndef RW_LOCK_H #define RW_LOCK_H -#include "core/error/error_list.h" +#include "core/typedefs.h" #include <shared_mutex> @@ -39,34 +39,34 @@ class RWLock { mutable std::shared_timed_mutex mutex; public: - // Lock the rwlock, block if locked by someone else - void read_lock() const { + // Lock the RWLock, block if locked by someone else. + _ALWAYS_INLINE_ void read_lock() const { mutex.lock_shared(); } - // Unlock the rwlock, let other threads continue - void read_unlock() const { + // Unlock the RWLock, let other threads continue. + _ALWAYS_INLINE_ void read_unlock() const { mutex.unlock_shared(); } - // Attempt to lock the rwlock, OK on success, ERR_BUSY means it can't lock. - Error read_try_lock() const { - return mutex.try_lock_shared() ? OK : ERR_BUSY; + // Attempt to lock the RWLock for reading. True on success, false means it can't lock. + _ALWAYS_INLINE_ bool read_try_lock() const { + return mutex.try_lock_shared(); } - // Lock the rwlock, block if locked by someone else - void write_lock() { + // Lock the RWLock, block if locked by someone else. + _ALWAYS_INLINE_ void write_lock() { mutex.lock(); } - // Unlock the rwlock, let other thwrites continue - void write_unlock() { + // Unlock the RWLock, let other threads continue. + _ALWAYS_INLINE_ void write_unlock() { mutex.unlock(); } - // Attempt to lock the rwlock, OK on success, ERR_BUSY means it can't lock. - Error write_try_lock() { - return mutex.try_lock() ? OK : ERR_BUSY; + // Attempt to lock the RWLock for writing. True on success, false means it can't lock. + _ALWAYS_INLINE_ bool write_try_lock() { + return mutex.try_lock(); } }; @@ -74,11 +74,11 @@ class RWLockRead { const RWLock &lock; public: - RWLockRead(const RWLock &p_lock) : + _ALWAYS_INLINE_ RWLockRead(const RWLock &p_lock) : lock(p_lock) { lock.read_lock(); } - ~RWLockRead() { + _ALWAYS_INLINE_ ~RWLockRead() { lock.read_unlock(); } }; @@ -87,11 +87,11 @@ class RWLockWrite { RWLock &lock; public: - RWLockWrite(RWLock &p_lock) : + _ALWAYS_INLINE_ RWLockWrite(RWLock &p_lock) : lock(p_lock) { lock.write_lock(); } - ~RWLockWrite() { + _ALWAYS_INLINE_ ~RWLockWrite() { lock.write_unlock(); } }; diff --git a/core/os/semaphore.h b/core/os/semaphore.h index 6a290f21c6..a992a4587d 100644 --- a/core/os/semaphore.h +++ b/core/os/semaphore.h @@ -39,32 +39,33 @@ class Semaphore { private: - mutable std::mutex mutex_; - mutable std::condition_variable condition_; - mutable unsigned long count_ = 0; // Initialized as locked. + mutable std::mutex mutex; + mutable std::condition_variable condition; + mutable uint32_t count = 0; // Initialized as locked. public: _ALWAYS_INLINE_ void post() const { - std::lock_guard<decltype(mutex_)> lock(mutex_); - ++count_; - condition_.notify_one(); + std::lock_guard lock(mutex); + count++; + condition.notify_one(); } _ALWAYS_INLINE_ void wait() const { - std::unique_lock<decltype(mutex_)> lock(mutex_); - while (!count_) { // Handle spurious wake-ups. - condition_.wait(lock); + std::unique_lock lock(mutex); + while (!count) { // Handle spurious wake-ups. + condition.wait(lock); } - --count_; + count--; } _ALWAYS_INLINE_ bool try_wait() const { - std::lock_guard<decltype(mutex_)> lock(mutex_); - if (count_) { - --count_; + std::lock_guard lock(mutex); + if (count) { + count--; return true; + } else { + return false; } - return false; } }; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 9e468f7075..b34d9f3271 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -4342,6 +4342,9 @@ bool String::is_valid_html_color() const { return Color::html_is_valid(*this); } +// Changes made to the set of invalid filename characters must also be reflected in the String documentation for is_valid_filename. +static const char *invalid_filename_characters = ": / \\ ? * \" | % < >"; + bool String::is_valid_filename() const { String stripped = strip_edges(); if (*this != stripped) { @@ -4352,7 +4355,22 @@ bool String::is_valid_filename() const { return false; } - return !(find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1); + Vector<String> chars = String(invalid_filename_characters).split(" "); + for (const String &ch : chars) { + if (contains(ch)) { + return false; + } + } + return true; +} + +String String::validate_filename() const { + Vector<String> chars = String(invalid_filename_characters).split(" "); + String name = strip_edges(); + for (int i = 0; i < chars.size(); i++) { + name = name.replace(chars[i], "_"); + } + return name; } bool String::is_valid_ip_address() const { diff --git a/core/string/ustring.h b/core/string/ustring.h index 6338f1d3cd..1582504c57 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -433,6 +433,7 @@ public: static const String invalid_node_name_characters; String validate_node_name() const; String validate_identifier() const; + String validate_filename() const; bool is_valid_identifier() const; bool is_valid_int() const; diff --git a/core/variant/array.cpp b/core/variant/array.cpp index f8af78f3c1..94d1596514 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -775,15 +775,9 @@ Variant Array::get_typed_script() const { return _p->typed.script; } -void Array::set_read_only(bool p_enable) { - if (p_enable == bool(_p->read_only != nullptr)) { - return; - } - if (p_enable) { +void Array::make_read_only() { + if (_p->read_only == nullptr) { _p->read_only = memnew(Variant); - } else { - memdelete(_p->read_only); - _p->read_only = nullptr; } } diff --git a/core/variant/array.h b/core/variant/array.h index 3728c22fe0..d9ca3278fb 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -127,7 +127,7 @@ public: StringName get_typed_class_name() const; Variant get_typed_script() const; - void set_read_only(bool p_enable); + void make_read_only(); bool is_read_only() const; Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script); diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index f87064a0d1..0429508cc5 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -333,15 +333,9 @@ Dictionary Dictionary::duplicate(bool p_deep) const { return recursive_duplicate(p_deep, 0); } -void Dictionary::set_read_only(bool p_enable) { - if (p_enable == bool(_p->read_only != nullptr)) { - return; - } - if (p_enable) { +void Dictionary::make_read_only() { + if (_p->read_only == nullptr) { _p->read_only = memnew(Variant); - } else { - memdelete(_p->read_only); - _p->read_only = nullptr; } } bool Dictionary::is_read_only() const { diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h index e6d8ebe25b..8935d35ed9 100644 --- a/core/variant/dictionary.h +++ b/core/variant/dictionary.h @@ -86,7 +86,7 @@ public: Dictionary duplicate(bool p_deep = false) const; Dictionary recursive_duplicate(bool p_deep, int recursion_count) const; - void set_read_only(bool p_enable); + void make_read_only(); bool is_read_only() const; const void *id() const; diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index ca42738b05..672b030806 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -3492,6 +3492,46 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const } } +bool Variant::identity_compare(const Variant &p_variant) const { + if (type != p_variant.type) { + return false; + } + + switch (type) { + case OBJECT: { + return _get_obj().obj == p_variant._get_obj().obj; + } break; + + case DICTIONARY: { + const Dictionary &l = *(reinterpret_cast<const Dictionary *>(_data._mem)); + const Dictionary &r = *(reinterpret_cast<const Dictionary *>(p_variant._data._mem)); + return l.id() == r.id(); + } break; + + case ARRAY: { + const Array &l = *(reinterpret_cast<const Array *>(_data._mem)); + const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem)); + return l.id() == r.id(); + } break; + + case PACKED_BYTE_ARRAY: + case PACKED_INT32_ARRAY: + case PACKED_INT64_ARRAY: + case PACKED_FLOAT32_ARRAY: + case PACKED_FLOAT64_ARRAY: + case PACKED_STRING_ARRAY: + case PACKED_VECTOR2_ARRAY: + case PACKED_VECTOR3_ARRAY: + case PACKED_COLOR_ARRAY: { + return _data.packed_array == p_variant._data.packed_array; + } break; + + default: { + return hash_compare(p_variant); + } + } +} + bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p_rhs) { if (p_lhs.hash_compare(p_rhs)) { return true; diff --git a/core/variant/variant.h b/core/variant/variant.h index b9294de77d..b2f31a6d57 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -748,6 +748,7 @@ public: uint32_t recursive_hash(int recursion_count) const; bool hash_compare(const Variant &p_variant, int recursion_count = 0) const; + bool identity_compare(const Variant &p_variant) const; bool booleanize() const; String stringify(int recursion_count = 0) const; String to_json_string() const; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 9e8c6fccb3..3b2d29734d 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1695,6 +1695,7 @@ static void _register_variant_builtin_methods() { bind_string_method(json_escape, sarray(), varray()); bind_string_method(validate_node_name, sarray(), varray()); + bind_string_method(validate_filename, sarray(), varray()); bind_string_method(is_valid_identifier, sarray(), varray()); bind_string_method(is_valid_int, sarray(), varray()); @@ -2179,6 +2180,8 @@ static void _register_variant_builtin_methods() { bind_method(Dictionary, values, sarray(), varray()); bind_method(Dictionary, duplicate, sarray("deep"), varray(false)); bind_method(Dictionary, get, sarray("key", "default"), varray(Variant())); + bind_method(Dictionary, make_read_only, sarray(), varray()); + bind_method(Dictionary, is_read_only, sarray(), varray()); /* Array */ @@ -2226,7 +2229,7 @@ static void _register_variant_builtin_methods() { bind_method(Array, get_typed_builtin, sarray(), varray()); bind_method(Array, get_typed_class_name, sarray(), varray()); bind_method(Array, get_typed_script, sarray(), varray()); - bind_method(Array, set_read_only, sarray("enable"), varray()); + bind_method(Array, make_read_only, sarray(), varray()); bind_method(Array, is_read_only, sarray(), varray()); /* Byte Array */ diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index fe7150bca9..042ebe368a 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1007,9 +1007,14 @@ struct VariantUtilityFunctions { static inline uint64_t rid_allocate_id() { return RID_AllocBase::_gen_id(); } + static inline RID rid_from_int64(uint64_t p_base) { return RID::from_uint64(p_base); } + + static inline bool is_same(const Variant &p_a, const Variant &p_b) { + return p_a.identity_compare(p_b); + } }; #ifdef DEBUG_METHODS_ENABLED @@ -1601,6 +1606,8 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(rid_allocate_id, Vector<String>(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(rid_from_int64, sarray("base"), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(is_same, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_GENERAL); } void Variant::_unregister_variant_utility_functions() { |