diff options
40 files changed, 526 insertions, 154 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index bc56cba21b..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: Bug report -about: Report a bug in Godot -title: '' -labels: '' -assignees: '' - ---- -<!-- Please search existing issues for potential duplicates before filing yours: -https://github.com/godotengine/godot/issues?q=is%3Aissue ---> - -**Godot version:** -<!-- Specify commit hash if using non-official build. --> - - -**OS/device including version:** -<!-- Specify GPU model, drivers, and the backend (GLES2, GLES3, Vulkan) if graphics-related. --> - - -**Issue description:** -<!-- What happened, and what was expected. --> - - -**Steps to reproduce:** - - -**Minimal reproduction project:** -<!-- A small Godot project which reproduces the issue. Drag and drop a zip archive to upload it. --> diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..43ba5ef357 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,56 @@ +name: Bug report +description: Report a bug in Godot +body: + +- type: markdown + attributes: + value: | + - Read our [CONTRIBUTING.md guide](CONTRIBUTING.md#reporting-bugs) on reporting bugs. + - Write a descriptive issue title above. + - Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. + - Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html). + +- type: input + attributes: + label: Godot version + description: > + Specify the Git commit hash if using a development or non-official build. + If you use a custom build, please test if your issue is reproducible in official builds too. + placeholder: 3.3.stable, 4.0.dev (3041becc6) + validations: + required: true + +- type: input + attributes: + label: System information + description: | + Specify the OS version, and when relevant hardware information. + For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan). + placeholder: Windows 10, GLES3, Intel HD Graphics 620 (27.20.100.9616) + validations: + required: true + +- type: textarea + attributes: + label: Issue description + description: | + Describe your issue briefly. What doesn't work, and how do you expect it to work instead? + You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags. + validations: + required: true + +- type: textarea + attributes: + label: Steps to reproduce + description: | + List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them. + If you include a minimal reproduction project below, you can detail how to use it here. + validations: + required: true + +- type: textarea + attributes: + label: Minimal reproduction project + description: | + A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting. + Drag and drop a ZIP archive to upload it. diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index b9514c8c8b..9e316291e8 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -257,6 +257,7 @@ Error FileAccessEncrypted::get_error() const { void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); + ERR_FAIL_COND(!p_src && p_length > 0); if (pos < get_length()) { for (uint64_t i = 0; i < p_length; i++) { diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 0114ab1765..d9be2a4a75 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -168,6 +168,7 @@ void FileAccessMemory::store_8(uint8_t p_byte) { } void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) { + ERR_FAIL_COND(!p_src && p_length > 0); uint64_t left = length - pos; uint64_t write = MIN(p_length, left); if (write < p_length) { diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index fb7eb42738..5bf874ccae 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -501,12 +501,27 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam compat_classes[p_class] = p_fallback; } +thread_local bool initializing_with_extension = false; +thread_local ObjectNativeExtension *initializing_extension = nullptr; +thread_local void *initializing_extension_instance = nullptr; + +void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance) { + if (initializing_with_extension) { + *r_extension = initializing_extension; + *r_extension_instance = initializing_extension_instance; + initializing_with_extension = false; + } else { + *r_extension = nullptr; + *r_extension_instance = nullptr; + } +} + Object *ClassDB::instance(const StringName &p_class) { ClassInfo *ti; { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func) { + if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) { if (compat_classes.has(p_class)) { ti = classes.getptr(compat_classes[p_class]); } @@ -521,6 +536,11 @@ Object *ClassDB::instance(const StringName &p_class) { return nullptr; } #endif + if (ti->native_extension) { + initializing_with_extension = true; + initializing_extension = ti->native_extension; + initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->create_instance_userdata); + } return ti->creation_func(); } @@ -534,7 +554,7 @@ bool ClassDB::can_instance(const StringName &p_class) { return false; } #endif - return (!ti->disabled && ti->creation_func != nullptr); + return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance)); } void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) { @@ -1310,6 +1330,24 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe return false; } +void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) { + ClassInfo *type = classes.getptr(p_class); + if (!type) { + ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'."); + } + + if (type->method_map.has(p_method->get_name())) { + // overloading not supported + ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'."); + } + +#ifdef DEBUG_METHODS_ENABLED + type->method_order.push_back(p_method->get_name()); +#endif + + type->method_map[p_method->get_name()] = p_method; +} + #ifdef DEBUG_METHODS_ENABLED MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname = method_name.name; @@ -1545,6 +1583,26 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con return var; } +void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) { + GLOBAL_LOCK_FUNCTION; + + ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name)); + ERR_FAIL_COND_MSG(classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name)); + + ClassInfo *parent = classes.getptr(p_extension->parent_class_name); + + ClassInfo c; + c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION; + c.native_extension = p_extension; + c.name = p_extension->class_name; + c.creation_func = parent->creation_func; + c.inherits = parent->name; + c.class_ptr = parent->class_ptr; + c.inherits_ptr = parent; + + classes[p_extension->class_name] = c; +} + RWLock ClassDB::lock; void ClassDB::cleanup_defaults() { diff --git a/core/object/class_db.h b/core/object/class_db.h index 6fd5748dbb..4355c9b0ea 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -97,6 +97,8 @@ public: enum APIType { API_CORE, API_EDITOR, + API_EXTENSION, + API_EDITOR_EXTENSION, API_NONE }; @@ -115,6 +117,8 @@ public: ClassInfo *inherits_ptr = nullptr; void *class_ptr = nullptr; + ObjectNativeExtension *native_extension = nullptr; + HashMap<StringName, MethodBind *> method_map; HashMap<StringName, int> constant_map; HashMap<StringName, List<StringName>> enum_map; @@ -199,6 +203,8 @@ public: //nothing } + static void register_extension_class(ObjectNativeExtension *p_extension); + template <class T> static Object *_create_ptr_func() { return T::create(); @@ -226,6 +232,7 @@ public: static bool is_parent_class(const StringName &p_class, const StringName &p_inherits); static bool can_instance(const StringName &p_class); static Object *instance(const StringName &p_class); + static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance); static APIType get_api_type(const StringName &p_class); static uint64_t get_api_hash(APIType p_api); @@ -334,6 +341,8 @@ public: return bind; } + static void bind_method_custom(const StringName &p_class, MethodBind *p_method); + static void add_signal(StringName p_class, const MethodInfo &p_signal); static bool has_signal(StringName p_class, StringName p_signal, bool p_no_inheritance = false); static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal); diff --git a/core/object/object.cpp b/core/object/object.cpp index a8b2c4a939..7e1c3855c0 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -385,6 +385,15 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid } } + if (_extension && _extension->set) { + if (_extension->set(_extension_instance, &p_name, &p_value)) { + if (r_valid) { + *r_valid = true; + } + return; + } + } + //try built-in setgetter { if (ClassDB::set_property(this, p_name, p_value, r_valid)) { @@ -451,6 +460,15 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { } } + if (_extension && _extension->get) { + if (_extension->get(_extension_instance, &p_name, &ret)) { + if (r_valid) { + *r_valid = true; + } + return ret; + } + } + //try built-in setgetter { if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) { @@ -596,6 +614,17 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons _get_property_listv(p_list, p_reversed); + if (_extension && _extension->get_property_list) { + uint32_t pcount; + const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount); + for (uint32_t i = 0; i < pcount; i++) { + p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name)); + } + if (_extension->free_property_list) { + _extension->free_property_list(_extension_instance, pinfo); + } + } + 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)); } @@ -761,6 +790,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a Variant ret; OBJ_DEBUG_LOCK + if (script_instance) { ret = script_instance->call(p_method, p_args, p_argcount, r_error); //force jumptable @@ -778,6 +808,8 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a } } + //extension does not need this, because all methods are registered in MethodBind + MethodBind *method = ClassDB::get_method(get_class_name(), p_method); if (method) { @@ -795,6 +827,10 @@ void Object::notification(int p_notification, bool p_reversed) { if (script_instance) { script_instance->notification(p_notification); } + + if (_extension && _extension->notification) { + _extension->notification(_extension_instance, p_notification); + } } String Object::to_string() { @@ -805,6 +841,9 @@ String Object::to_string() { return ret; } } + if (_extension && _extension->to_string) { + return _extension->to_string(_extension_instance); + } return "[" + get_class() + ":" + itos(get_instance_id()) + "]"; } @@ -1751,6 +1790,8 @@ void Object::_construct_object(bool p_reference) { _instance_id = ObjectDB::add_instance(this); memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS); + ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance); + #ifdef DEBUG_ENABLED _lock_index.init(1); #endif @@ -1770,6 +1811,12 @@ Object::~Object() { } script_instance = nullptr; + if (_extension && _extension->free_instance) { + _extension->free_instance(_extension->create_instance_userdata, _extension_instance); + _extension = nullptr; + _extension_instance = nullptr; + } + const StringName *S = nullptr; if (_emitting) { diff --git a/core/object/object.h b/core/object/object.h index 448a33d3bc..137025f323 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -238,6 +238,50 @@ struct MethodInfo { ////else //return nullptr; +// API used to extend in GDNative and other C compatible compiled languages +class MethodBind; + +struct ObjectNativeExtension { + ObjectNativeExtension *parent = nullptr; + StringName parent_class_name; + StringName class_name; + bool editor_class = false; + bool (*set)(void *instance, const void *name, const void *value) = nullptr; + bool (*get)(void *instance, const void *name, void *ret_variant) = nullptr; + struct PInfo { + uint32_t type; + const char *name; + const char *class_name; + uint32_t hint; + const char *hint_string; + uint32_t usage; + }; + const PInfo *(*get_property_list)(void *instance, uint32_t *count) = nullptr; + void (*free_property_list)(void *instance, const PInfo *) = nullptr; + + //call is not used, as all methods registered in ClassDB + + void (*notification)(void *instance, int32_t what) = nullptr; + const char *(*to_string)(void *instance) = nullptr; + + void (*reference)(void *instance) = nullptr; + void (*unreference)(void *instance) = nullptr; + + _FORCE_INLINE_ bool is_class(const String &p_class) const { + const ObjectNativeExtension *e = this; + while (e) { + if (p_class == e->class_name.operator String()) { + return true; + } + e = e->parent; + } + return false; + } + void *create_instance_userdata = nullptr; + void *(*create_instance)(void *create_instance_userdata) = nullptr; + void (*free_instance)(void *create_instance_userdata, void *instance) = nullptr; +}; + /* the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model. */ @@ -262,9 +306,15 @@ private: \ public: \ virtual String get_class() const override { \ + if (_get_extension()) { \ + return _get_extension()->class_name.operator String(); \ + } \ return String(#m_class); \ } \ virtual const StringName *_get_class_namev() const override { \ + if (_get_extension()) { \ + return &_get_extension()->class_name; \ + } \ if (!_class_name) { \ _class_name = get_class_static(); \ } \ @@ -297,7 +347,12 @@ public: static String inherits_static() { \ return String(#m_inherits); \ } \ - virtual bool is_class(const String &p_class) const override { return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); } \ + virtual bool is_class(const String &p_class) const override { \ + if (_get_extension() && _get_extension()->is_class(p_class)) { \ + return true; \ + } \ + return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \ + } \ virtual bool is_class_ptr(void *p_ptr) const override { return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); } \ \ static void get_valid_parents_static(List<String> *p_parents) { \ @@ -440,6 +495,9 @@ private: friend bool predelete_handler(Object *); friend void postinitialize_handler(Object *); + ObjectNativeExtension *_extension = nullptr; + void *_extension_instance = nullptr; + struct SignalData { struct Slot { int reference_count = 0; @@ -495,6 +553,8 @@ private: Object(bool p_reference); protected: + _ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; } + _ALWAYS_INLINE_ void *_get_extension_instance() const { return _extension_instance; } virtual void _initialize_classv() { initialize_class(); } virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; }; virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; }; @@ -610,13 +670,25 @@ public: static String get_parent_class_static() { return String(); } static String get_category_static() { return String(); } - virtual String get_class() const { return "Object"; } + virtual String get_class() const { + if (_extension) + return _extension->class_name.operator String(); + return "Object"; + } virtual String get_save_class() const { return get_class(); } //class stored when saving - virtual bool is_class(const String &p_class) const { return (p_class == "Object"); } + virtual bool is_class(const String &p_class) const { + if (_extension && _extension->is_class(p_class)) { + return true; + } + return (p_class == "Object"); + } virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; } _FORCE_INLINE_ const StringName &get_class_name() const { + if (_extension) { + return _extension->class_name; + } if (!_class_ptr) { return *_get_class_namev(); } else { diff --git a/core/object/reference.cpp b/core/object/reference.cpp index 22e4e8a336..086b761e95 100644 --- a/core/object/reference.cpp +++ b/core/object/reference.cpp @@ -62,6 +62,9 @@ bool Reference::reference() { if (get_script_instance()) { get_script_instance()->refcount_incremented(); } + if (_get_extension() && _get_extension()->reference) { + _get_extension()->reference(_get_extension_instance()); + } if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) { for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { if (_script_instance_bindings[i]) { @@ -83,6 +86,9 @@ bool Reference::unreference() { bool script_ret = get_script_instance()->refcount_decremented(); die = die && script_ret; } + if (_get_extension() && _get_extension()->unreference) { + _get_extension()->unreference(_get_extension_instance()); + } if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) { for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { if (_script_instance_bindings[i]) { diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 3d04e4e619..d21c0bd9a2 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -551,6 +551,7 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_ } void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) { + ERR_FAIL_COND(!p_src && p_length > 0); for (uint64_t i = 0; i < p_length; i++) { store_8(p_src[i]); } diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 3b4a001f7e..49edb4c691 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -671,10 +671,7 @@ <constant name="DIFFUSE_LAMBERT_WRAP" value="2" enum="DiffuseMode"> Extends Lambert to cover more than 90 degrees when roughness increases. </constant> - <constant name="DIFFUSE_OREN_NAYAR" value="3" enum="DiffuseMode"> - Attempts to use roughness to emulate microsurfacing. - </constant> - <constant name="DIFFUSE_TOON" value="4" enum="DiffuseMode"> + <constant name="DIFFUSE_TOON" value="3" enum="DiffuseMode"> Uses a hard cut for lighting, with smoothing affected by roughness. </constant> <constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode"> diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml index 80db57d7d0..6665a4a9f6 100644 --- a/doc/classes/Skeleton2D.xml +++ b/doc/classes/Skeleton2D.xml @@ -13,7 +13,7 @@ <method name="execute_modifications"> <return type="void"> </return> - <argument index="0" name="execution_mode" type="float"> + <argument index="0" name="delta" type="float"> </argument> <argument index="1" name="execution_mode" type="int"> </argument> diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index ec23df62d0..6ea55219bb 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -264,7 +264,7 @@ void FileAccessUnix::store_8(uint8_t p_dest) { void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); - ERR_FAIL_COND(!p_src); + ERR_FAIL_COND(!p_src && p_length > 0); ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length); } diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 1f46b44f5e..d6deda7b5d 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -294,6 +294,7 @@ void FileAccessWindows::store_8(uint8_t p_dest) { void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND(!f); + ERR_FAIL_COND(!p_src && p_length > 0); if (flags == READ_WRITE || flags == WRITE_READ) { if (prev_op == READ) { if (last_error != ERR_FILE_EOF) { diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 7527514dca..b8504ad02a 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -141,7 +141,7 @@ EditorAbout::EditorAbout() { version_btn = memnew(LinkButton); String hash = String(VERSION_HASH); if (hash.length() != 0) { - hash = "." + hash.left(9); + hash = " " + vformat("[%s]", hash.left(9)); } version_btn->set_text(VERSION_FULL_NAME + hash); // Set the text to copy in metadata as it slightly differs from the button's text. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2e6ec88d8c..1c2fd50f0b 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6632,7 +6632,7 @@ EditorNode::EditorNode() { version_btn->set_text(VERSION_FULL_CONFIG); String hash = String(VERSION_HASH); if (hash.length() != 0) { - hash = "." + hash.left(9); + hash = " " + vformat("[%s]", hash.left(9)); } // Set the text to copy in metadata as it slightly differs from the button's text. version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index d1c52b4310..63281ae1aa 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -59,15 +59,40 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) { Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj); - int index = get_popup()->get_item_count(); - get_popup()->add_icon_item(icon, E->get().name.capitalize(), objects.size()); - get_popup()->set_item_h_offset(index, p_depth * 10 * EDSCALE); + String proper_name = ""; + Vector<String> name_parts = E->get().name.split("/"); + + for (int i = 0; i < name_parts.size(); i++) { + if (i > 0) { + proper_name += " > "; + } + proper_name += name_parts[i].capitalize(); + } + + int index = sub_objects_menu->get_item_count(); + sub_objects_menu->add_icon_item(icon, proper_name, objects.size()); + sub_objects_menu->set_item_h_offset(index, p_depth * 10 * EDSCALE); objects.push_back(obj->get_instance_id()); _add_children_to_popup(obj, p_depth + 1); } } +void EditorPath::_show_popup() { + sub_objects_menu->clear(); + + Size2 size = get_size(); + Point2 gp = get_screen_position(); + gp.y += size.y; + + sub_objects_menu->set_position(gp); + sub_objects_menu->set_size(Size2(size.width, 1)); + sub_objects_menu->set_parent_rect(Rect2(Point2(gp - sub_objects_menu->get_position()), size)); + + sub_objects_menu->take_mouse_focus(); + sub_objects_menu->popup(); +} + void EditorPath::_about_to_show() { Object *obj = ObjectDB::get_instance(history->get_path_object(history->get_path_size() - 1)); if (!obj) { @@ -75,13 +100,11 @@ void EditorPath::_about_to_show() { } objects.clear(); - get_popup()->clear(); - get_popup()->set_size(Size2(get_size().width, 1)); _add_children_to_popup(obj); - if (get_popup()->get_item_count() == 0) { - get_popup()->add_item(TTR("No sub-resources found.")); - get_popup()->set_item_disabled(0, true); + if (sub_objects_menu->get_item_count() == 0) { + sub_objects_menu->add_item(TTR("No sub-resources found.")); + sub_objects_menu->set_item_disabled(0, true); } } @@ -94,7 +117,7 @@ void EditorPath::update_path() { Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj); if (icon.is_valid()) { - set_icon(icon); + current_object_icon->set_texture(icon); } if (i == history->get_path_size() - 1) { @@ -120,12 +143,26 @@ void EditorPath::update_path() { name = obj->get_class(); } - set_text(" " + name); // An extra space so the text is not too close of the icon. + current_object_label->set_text(" " + name); // An extra space so the text is not too close of the icon. set_tooltip(obj->get_class()); } } } +void EditorPath::clear_path() { + set_disabled(true); + set_tooltip(""); + + current_object_label->set_text(""); + current_object_icon->set_texture(nullptr); + sub_objects_icon->set_visible(false); +} + +void EditorPath::enable_path() { + set_disabled(false); + sub_objects_icon->set_visible(true); +} + void EditorPath::_id_pressed(int p_idx) { ERR_FAIL_INDEX(p_idx, objects.size()); @@ -139,8 +176,16 @@ void EditorPath::_id_pressed(int p_idx) { void EditorPath::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { update_path(); + + sub_objects_icon->set_texture(get_theme_icon("select_arrow", "Tree")); + current_object_label->add_theme_font_override("font", get_theme_font("main", "EditorFonts")); + } break; + + case NOTIFICATION_READY: { + connect("pressed", callable_mp(this, &EditorPath::_show_popup)); } break; } } @@ -150,8 +195,35 @@ void EditorPath::_bind_methods() { EditorPath::EditorPath(EditorHistory *p_history) { history = p_history; - set_clip_text(true); - set_text_align(ALIGN_LEFT); - get_popup()->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show)); - get_popup()->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed)); + + MarginContainer *main_mc = memnew(MarginContainer); + main_mc->set_anchors_and_offsets_preset(PRESET_WIDE); + main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE); + main_mc->add_theme_constant_override("margin_right", 6 * EDSCALE); + add_child(main_mc); + + HBoxContainer *main_hb = memnew(HBoxContainer); + main_mc->add_child(main_hb); + + current_object_icon = memnew(TextureRect); + current_object_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + main_hb->add_child(current_object_icon); + + current_object_label = memnew(Label); + current_object_label->set_clip_text(true); + current_object_label->set_align(Label::ALIGN_LEFT); + current_object_label->set_h_size_flags(SIZE_EXPAND_FILL); + main_hb->add_child(current_object_label); + + sub_objects_icon = memnew(TextureRect); + sub_objects_icon->set_visible(false); + sub_objects_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + main_hb->add_child(sub_objects_icon); + + sub_objects_menu = memnew(PopupMenu); + add_child(sub_objects_menu); + sub_objects_menu->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show)); + sub_objects_menu->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed)); + + set_tooltip(TTR("Open a list of sub-resources.")); } diff --git a/editor/editor_path.h b/editor/editor_path.h index d1090947f9..cabfa931d6 100644 --- a/editor/editor_path.h +++ b/editor/editor_path.h @@ -32,16 +32,24 @@ #define EDITOR_PATH_H #include "editor_data.h" -#include "scene/gui/menu_button.h" +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/popup_menu.h" -class EditorPath : public MenuButton { - GDCLASS(EditorPath, MenuButton); +class EditorPath : public Button { + GDCLASS(EditorPath, Button); EditorHistory *history; + TextureRect *current_object_icon; + Label *current_object_label; + TextureRect *sub_objects_icon; + PopupMenu *sub_objects_menu; + Vector<ObjectID> objects; EditorPath(); + void _show_popup(); void _id_pressed(int p_idx); void _about_to_show(); void _add_children_to_popup(Object *p_obj, int p_depth = 0); @@ -52,6 +60,8 @@ protected: public: void update_path(); + void clear_path(); + void enable_path(); EditorPath(EditorHistory *p_history); }; diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 0e8e9a9a32..e8c01d0e0c 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -42,6 +42,14 @@ void InspectorDock::_menu_option(int p_option) { case COLLAPSE_ALL: { _menu_collapseall(); } break; + + case RESOURCE_SAVE: { + _save_resource(false); + } break; + case RESOURCE_SAVE_AS: { + _save_resource(true); + } break; + case RESOURCE_MAKE_BUILT_IN: { _unref_resource(); } break; @@ -52,13 +60,6 @@ void InspectorDock::_menu_option(int p_option) { _paste_resource(); } break; - case RESOURCE_SAVE: { - _save_resource(false); - } break; - case RESOURCE_SAVE_AS: { - _save_resource(true); - } break; - case OBJECT_REQUEST_HELP: { if (current) { editor->set_visible_editor(EditorNode::EDITOR_SCRIPT); @@ -335,9 +336,16 @@ void InspectorDock::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { set_theme(editor->get_gui_base()->get_theme()); + resource_new_button->set_icon(get_theme_icon("New", "EditorIcons")); resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons")); resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons")); + resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); + + PopupMenu *resource_extra_popup = resource_extra_button->get_popup(); + resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_theme_icon("ActionPaste", "EditorIcons")); + resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_theme_icon("ActionCopy", "EditorIcons")); + if (is_layout_rtl()) { backward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); forward_button->set_icon(get_theme_icon("Back", "EditorIcons")); @@ -345,6 +353,7 @@ void InspectorDock::_notification(int p_what) { backward_button->set_icon(get_theme_icon("Back", "EditorIcons")); forward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); } + history_menu->set_icon(get_theme_icon("History", "EditorIcons")); object_menu->set_icon(get_theme_icon("Tools", "EditorIcons")); warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons")); @@ -403,12 +412,7 @@ void InspectorDock::update(Object *p_object) { object_menu->set_disabled(true); warning->hide(); search->set_editable(false); - - editor_path->set_disabled(true); - editor_path->set_text(""); - editor_path->set_tooltip(""); - editor_path->set_icon(nullptr); - + editor_path->clear_path(); return; } @@ -417,35 +421,28 @@ void InspectorDock::update(Object *p_object) { object_menu->set_disabled(false); search->set_editable(true); - editor_path->set_disabled(false); + editor_path->enable_path(); + resource_save_button->set_disabled(!is_resource); + open_docs_button->set_visible(is_resource || is_node); + + PopupMenu *resource_extra_popup = resource_extra_button->get_popup(); + resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_COPY), !is_resource); + resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_MAKE_BUILT_IN), !is_resource); PopupMenu *p = object_menu->get_popup(); p->clear(); - p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand All Properties")), EXPAND_ALL); - p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All Properties")), COLLAPSE_ALL); - p->add_separator(); - if (is_resource) { - p->add_item(TTR("Save"), RESOURCE_SAVE); - p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS); - p->add_separator(); - } - p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS); - p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS); + p->add_icon_shortcut(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL); + p->add_icon_shortcut(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL); p->add_separator(); - p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource Clipboard")), RESOURCE_EDIT_CLIPBOARD); - if (is_resource) { - p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); - p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_MAKE_BUILT_IN); - } + p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Properties")), OBJECT_COPY_PARAMS); + p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Properties")), OBJECT_PASTE_PARAMS); if (is_resource || is_node) { p->add_separator(); p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES); - p->add_separator(); - p->add_icon_shortcut(get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP); } List<MethodInfo> methods; @@ -525,6 +522,17 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { resource_save_button->set_focus_mode(Control::FOCUS_NONE); resource_save_button->set_disabled(true); + resource_extra_button = memnew(MenuButton); + resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); + general_options_hb->add_child(resource_extra_button); + resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionPaste", "EditorIcons"), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD); + resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionCopy", "EditorIcons"), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); + resource_extra_button->get_popup()->set_item_disabled(1, true); + resource_extra_button->get_popup()->add_separator(); + resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Resource Built-In")), RESOURCE_MAKE_BUILT_IN); + resource_extra_button->get_popup()->set_item_disabled(3, true); + resource_extra_button->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option)); + general_options_hb->add_spacer(); backward_button = memnew(Button); @@ -558,31 +566,42 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history)); history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history)); - HBoxContainer *node_info_hb = memnew(HBoxContainer); - add_child(node_info_hb); - + HBoxContainer *subresource_hb = memnew(HBoxContainer); + add_child(subresource_hb); editor_path = memnew(EditorPath(editor->get_editor_history())); editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); - node_info_hb->add_child(editor_path); + subresource_hb->add_child(editor_path); - object_menu = memnew(MenuButton); - object_menu->set_shortcut_context(this); - object_menu->set_icon(get_theme_icon("Tools", "EditorIcons")); - node_info_hb->add_child(object_menu); - object_menu->set_tooltip(TTR("Object properties.")); - object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option)); + open_docs_button = memnew(Button); + open_docs_button->set_flat(true); + open_docs_button->set_visible(false); + open_docs_button->set_tooltip(TTR("Open documentation for this object.")); + open_docs_button->set_icon(get_theme_icon("HelpSearch", "EditorIcons")); + open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation"))); + subresource_hb->add_child(open_docs_button); + open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP)); new_resource_dialog = memnew(CreateDialog); editor->get_gui_base()->add_child(new_resource_dialog); new_resource_dialog->set_base_type("Resource"); new_resource_dialog->connect("create", callable_mp(this, &InspectorDock::_resource_created)); + HBoxContainer *property_tools_hb = memnew(HBoxContainer); + add_child(property_tools_hb); + search = memnew(LineEdit); search->set_h_size_flags(Control::SIZE_EXPAND_FILL); search->set_placeholder(TTR("Filter properties")); search->set_right_icon(get_theme_icon("Search", "EditorIcons")); search->set_clear_button_enabled(true); - add_child(search); + property_tools_hb->add_child(search); + + object_menu = memnew(MenuButton); + object_menu->set_shortcut_context(this); + object_menu->set_icon(get_theme_icon("Tools", "EditorIcons")); + property_tools_hb->add_child(object_menu); + object_menu->set_tooltip(TTR("Manage object properties.")); + object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option)); warning = memnew(Button); add_child(warning); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index bc16a3b628..d50785d95c 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -81,9 +81,11 @@ class InspectorDock : public VBoxContainer { Button *resource_new_button; Button *resource_load_button; MenuButton *resource_save_button; + MenuButton *resource_extra_button; MenuButton *history_menu; LineEdit *search; + Button *open_docs_button; MenuButton *object_menu; EditorPath *editor_path; diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 8d3242db2b..9323c31fae 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -1541,19 +1541,46 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() { cursor_points = Vector<Vector3>(); Vector<Color> cursor_colors; - float cs = 0.25; + const float cs = 0.25; + // Add more points to create a "hard stop" in the color gradient. cursor_points.push_back(Vector3(+cs, 0, 0)); + cursor_points.push_back(Vector3()); + cursor_points.push_back(Vector3()); cursor_points.push_back(Vector3(-cs, 0, 0)); + cursor_points.push_back(Vector3(0, +cs, 0)); + cursor_points.push_back(Vector3()); + cursor_points.push_back(Vector3()); cursor_points.push_back(Vector3(0, -cs, 0)); + cursor_points.push_back(Vector3(0, 0, +cs)); + cursor_points.push_back(Vector3()); + cursor_points.push_back(Vector3()); cursor_points.push_back(Vector3(0, 0, -cs)); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor")); + + // Use the axis color which is brighter for the positive axis. + // Use a darkened axis color for the negative axis. + // This makes it possible to see in which direction the Position3D node is rotated + // (which can be important depending on how it's used). + const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor"); + cursor_colors.push_back(color_x); + cursor_colors.push_back(color_x); + // FIXME: Use less strong darkening factor once GH-48573 is fixed. + // The current darkening factor compensates for lines being too bright in the 3D editor. + cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75)); + cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75)); + + const Color color_y = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor"); + cursor_colors.push_back(color_y); + cursor_colors.push_back(color_y); + cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75)); + cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75)); + + const Color color_z = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor"); + cursor_colors.push_back(color_z); + cursor_colors.push_back(color_z); + cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75)); + cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75)); Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index cf237f5a4a..235ccb18cb 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -832,7 +832,7 @@ struct FSample { }; static FSample _samples[] = { - { "hani", U"漢語" }, + { "hani", U"漢字" }, { "armn", U"Աբ" }, { "copt", U"Αα" }, { "cyrl", U"Аб" }, diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp index fa58eb5480..8de7dc2447 100644 --- a/editor/plugins/font_editor_plugin.cpp +++ b/editor/plugins/font_editor_plugin.cpp @@ -56,7 +56,7 @@ struct FSample { }; static FSample _samples[] = { - { "hani", U"漢語" }, + { "hani", U"漢字" }, { "armn", U"Աբ" }, { "copt", U"Αα" }, { "cyrl", U"Аб" }, diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 1edcbd2cc9..e1c6e61a0b 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -538,7 +538,7 @@ TextEditor::TextEditor() { edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option)); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("un_redo"), EDIT_REDO); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 9ed9bdcb96..1b596ce599 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2621,7 +2621,7 @@ ProjectManager::ProjectManager() { version_btn = memnew(LinkButton); String hash = String(VERSION_HASH); if (hash.length() != 0) { - hash = "." + hash.left(9); + hash = " " + vformat("[%s]", hash.left(9)); } version_btn->set_text("v" VERSION_FULL_BUILD + hash); // Fade the version label to be less prominent, but still readable. diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 4cdf820877..c05a3c2f89 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -261,10 +261,6 @@ void EditorSettingsDialog::_update_shortcuts() { for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) { String action_name = E.key(); - if (!shortcut_filter.is_subsequence_ofi(action_name)) { - continue; - } - InputMap::Action action = E.get(); Array events; // Need to get the list of events into an array so it can be set as metadata on the item. @@ -298,6 +294,10 @@ void EditorSettingsDialog::_update_shortcuts() { // Join the text of the events with a delimiter so they can all be displayed in one cell. String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings); + if (!shortcut_filter.is_subsequence_ofi(action_name) && (events_display_string == "None" || !shortcut_filter.is_subsequence_ofi(events_display_string))) { + continue; + } + TreeItem *item = shortcuts->create_item(common_section); item->set_text(0, action_name); item->set_text(1, events_display_string); diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format index 2dac8e9a55..81bc412944 100755 --- a/misc/hooks/pre-commit-clang-format +++ b/misc/hooks/pre-commit-clang-format @@ -76,7 +76,8 @@ fi # To get consistent formatting, we recommend contributors to use the same # clang-format version as CI. -RECOMMENDED_CLANG_FORMAT_MAJOR="11" +RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="11" +RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="12" if [ ! -x "$CLANG_FORMAT" ] ; then message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x." @@ -106,8 +107,8 @@ fi CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/\1/")" 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 $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)." +if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then + echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN.x.x and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX.x.x)." echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly." fi diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 98325bcdf1..6ce7c301c4 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1853,7 +1853,7 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { } member_name = ti->get_text(0); } - if (ED_IS_SHORTCUT("visual_script_editor/delete_selected", p_event)) { + if (ED_IS_SHORTCUT("ui_graph_delete", p_event)) { _member_option(MEMBER_REMOVE); } if (ED_IS_SHORTCUT("visual_script_editor/edit_member", p_event)) { @@ -4121,7 +4121,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); member_popup->add_separator(); - member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE); + member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE); member_popup->popup(); return; } @@ -4131,7 +4131,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); member_popup->add_separator(); - member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE); + member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE); member_popup->popup(); return; } @@ -4141,7 +4141,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); member_popup->add_separator(); - member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE); + member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE); member_popup->popup(); return; } diff --git a/platform/javascript/js/libs/library_godot_fetch.js b/platform/javascript/js/libs/library_godot_fetch.js index de5ae2b1ae..04b90aea9c 100644 --- a/platform/javascript/js/libs/library_godot_fetch.js +++ b/platform/javascript/js/libs/library_godot_fetch.js @@ -29,7 +29,7 @@ /*************************************************************************/ const GodotFetch = { - $GodotFetch__deps: ['$GodotRuntime'], + $GodotFetch__deps: ['$IDHandler', '$GodotRuntime'], $GodotFetch: { onread: function (id, result) { diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index 5c7d65e3e0..1019f85c8a 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -36,10 +36,41 @@ const real_t DEFAULT_GIZMO_EXTENTS = 10.0; void Position2D::_draw_cross() { - real_t extents = get_gizmo_extents(); - // Colors taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`) - draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(0.96, 0.20, 0.32)); - draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01)); + const real_t extents = get_gizmo_extents(); + + // Add more points to create a "hard stop" in the color gradient. + PackedVector2Array points_x; + points_x.push_back(Point2(+extents, 0)); + points_x.push_back(Point2()); + points_x.push_back(Point2()); + points_x.push_back(Point2(-extents, 0)); + + PackedVector2Array points_y; + points_y.push_back(Point2(0, +extents)); + points_y.push_back(Point2()); + points_y.push_back(Point2()); + points_y.push_back(Point2(0, -extents)); + + // Use the axis color which is brighter for the positive axis. + // Use a darkened axis color for the negative axis. + // This makes it possible to see in which direction the Position3D node is rotated + // (which can be important depending on how it's used). + // Axis colors are taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`). + PackedColorArray colors_x; + const Color color_x = Color(0.96, 0.20, 0.32); + colors_x.push_back(color_x); + colors_x.push_back(color_x); + colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5)); + colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5)); + draw_multiline_colors(points_x, colors_x); + + PackedColorArray colors_y; + const Color color_y = Color(0.53, 0.84, 0.01); + colors_y.push_back(color_y); + colors_y.push_back(color_y); + colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5)); + colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5)); + draw_multiline_colors(points_y, colors_y); } #ifdef TOOLS_ENABLED diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index c5ad3dde39..8f1f5fadbc 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -787,7 +787,7 @@ void Skeleton2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_modification_stack", "modification_stack"), &Skeleton2D::set_modification_stack); ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton2D::get_modification_stack); - ClassDB::bind_method(D_METHOD("execute_modifications", "execution_mode", "execution_mode"), &Skeleton2D::execute_modifications); + ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton2D::execute_modifications); ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "override_pose", "strength", "persistent"), &Skeleton2D::set_bone_local_pose_override); ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton2D::get_bone_local_pose_override); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index c2f33accee..2c5634e6ef 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -505,9 +505,6 @@ void BaseMaterial3D::_update_shader() { case DIFFUSE_LAMBERT_WRAP: code += ",diffuse_lambert_wrap"; break; - case DIFFUSE_OREN_NAYAR: - code += ",diffuse_oren_nayar"; - break; case DIFFUSE_TOON: code += ",diffuse_toon"; break; @@ -2400,7 +2397,7 @@ void BaseMaterial3D::_bind_methods() { ADD_GROUP("Shading", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Toon"), "set_diffuse_mode", "get_diffuse_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); @@ -2654,7 +2651,6 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT); BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP); - BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR); BIND_ENUM_CONSTANT(DIFFUSE_TOON); BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX); diff --git a/scene/resources/material.h b/scene/resources/material.h index ad1b7b3e33..dc3ecdb5de 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -243,7 +243,6 @@ public: DIFFUSE_BURLEY, DIFFUSE_LAMBERT, DIFFUSE_LAMBERT_WRAP, - DIFFUSE_OREN_NAYAR, DIFFUSE_TOON, DIFFUSE_MAX }; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index ff6d179f5b..35430e4a46 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -164,8 +164,8 @@ public: Vector2 normal; RID rid; ObjectID collider_id; - Object *collider; - int shape; + Object *collider = nullptr; + int shape = 0; Variant metadata; }; @@ -174,8 +174,8 @@ public: struct ShapeResult { RID rid; ObjectID collider_id; - Object *collider; - int shape; + Object *collider = nullptr; + int shape = 0; Variant metadata; }; @@ -193,7 +193,7 @@ public: Vector2 normal; RID rid; ObjectID collider_id; - int shape; + int shape = 0; Vector2 linear_velocity; //velocity at contact point Variant metadata; }; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 4e76f7ce7e..ec4914641a 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -157,8 +157,8 @@ public: struct ShapeResult { RID rid; ObjectID collider_id; - Object *collider; - int shape; + Object *collider = nullptr; + int shape = 0; }; virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; @@ -168,8 +168,8 @@ public: Vector3 normal; RID rid; ObjectID collider_id; - Object *collider; - int shape; + Object *collider = nullptr; + int shape = 0; }; virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; @@ -181,7 +181,7 @@ public: Vector3 normal; RID rid; ObjectID collider_id; - int shape; + int shape = 0; Vector3 linear_velocity; //velocity at contact point }; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 6dbac0f7e1..dcfdf14784 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -721,7 +721,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; } - actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 37508d70af..0d9dfbc51b 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -737,7 +737,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; } - actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 7deedb80c3..b347197289 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -1504,7 +1504,6 @@ ShaderCompilerRD::ShaderCompilerRD() { actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; } - actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 32a86cb166..709ea45b88 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -144,12 +144,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, float metallic = unpackUnorm4x8(orms).z; if (metallic < 1.0) { float roughness = unpackUnorm4x8(orms).y; - -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif #if defined(DIFFUSE_LAMBERT_WRAP) // energy conserving lambert wrap shader @@ -243,7 +238,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #elif defined(SPECULAR_PHONG) vec3 R = normalize(-reflect(L, N)); +#ifdef USE_SOFT_SHADOWS float cRdotV = clamp(A + dot(R, V), 0.0, 1.0); +#else + float cRdotV = clamp(dot(R, V), 0.0, 1.0); +#endif float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float phong = pow(cRdotV, shininess); phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index a1e892498b..35f1b05796 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -204,7 +204,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert"); shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar"); shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley"); shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon"); |