diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 829e1d8e5b..f158755a85 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -549,6 +549,15 @@ Ref GDExtensionResourceLoader::load(const String &p_path, const String return Ref(); } + // Handle icons if any are specified. + if (config->has_section("icons")) { + List keys; + config->get_section_keys("icons", &keys); + for (const String &key : keys) { + lib->class_icon_paths[key] = config->get_value("icons", key); + } + } + return lib; } diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 39523a142f..9d946ca7ba 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -67,6 +67,8 @@ protected: static void _bind_methods(); public: + HashMap class_icon_paths; + static String get_extension_list_config_file(); static String find_extension_library(const String &p_path, Ref p_config, std::function p_has_feature, PackedStringArray *r_tags = nullptr); diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp index 8701e6d77b..63e809bc7c 100644 --- a/core/extension/gdextension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -50,6 +50,11 @@ GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String & extension->initialize_library(GDExtension::InitializationLevel(i)); } } + + for (const KeyValue &kv : extension->class_icon_paths) { + gdextension_class_icon_paths[kv.key] = kv.value; + } + gdextension_map[p_path] = extension; return LOAD_STATUS_OK; } @@ -74,6 +79,11 @@ GDExtensionManager::LoadStatus GDExtensionManager::unload_extension(const String extension->deinitialize_library(GDExtension::InitializationLevel(i)); } } + + for (const KeyValue &kv : extension->class_icon_paths) { + gdextension_class_icon_paths.erase(kv.key); + } + gdextension_map.erase(p_path); return LOAD_STATUS_OK; } @@ -95,6 +105,19 @@ Ref GDExtensionManager::get_extension(const String &p_path) { return E->value; } +bool GDExtensionManager::class_has_icon_path(const String &p_class) const { + // TODO: Check that the icon belongs to a registered class somehow. + return gdextension_class_icon_paths.has(p_class); +} + +String GDExtensionManager::class_get_icon_path(const String &p_class) const { + // TODO: Check that the icon belongs to a registered class somehow. + if (gdextension_class_icon_paths.has(p_class)) { + return gdextension_class_icon_paths[p_class]; + } + return ""; +} + void GDExtensionManager::initialize_extensions(GDExtension::InitializationLevel p_level) { ERR_FAIL_COND(int32_t(p_level) - 1 != level); for (KeyValue> &E : gdextension_map) { diff --git a/core/extension/gdextension_manager.h b/core/extension/gdextension_manager.h index 456942af0d..3643f043d8 100644 --- a/core/extension/gdextension_manager.h +++ b/core/extension/gdextension_manager.h @@ -38,6 +38,7 @@ class GDExtensionManager : public Object { int32_t level = -1; HashMap> gdextension_map; + HashMap gdextension_class_icon_paths; static void _bind_methods(); @@ -59,6 +60,9 @@ public: Vector get_loaded_extensions() const; Ref get_extension(const String &p_path); + bool class_has_icon_path(const String &p_class) const; + String class_get_icon_path(const String &p_class) const; + void initialize_extensions(GDExtension::InitializationLevel p_level); void deinitialize_extensions(GDExtension::InitializationLevel p_level); diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index 9fce014125..ec2447dbbc 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -48,7 +48,7 @@ When this property is enabled, text that is too large to fit the button is clipped, when disabled the Button will always be wide enough to hold the text. - When enabled, the button's icon will expand/shrink to fit the button's size while keeping its aspect. + When enabled, the button's icon will expand/shrink to fit the button's size while keeping its aspect. See also [theme_item icon_max_width]. Flat buttons don't display decoration. @@ -116,6 +116,9 @@ The horizontal space between [Button]'s icon and text. Negative values will be treated as [code]0[/code] when used. + + The maximum allowed width of the [Button]'s icon. This limit is applied on top of the default size of the icon, or its expanded size if [member expand_icon] is [code]true[/code]. The height is adjusted according to the icon's ratio. + The size of the text outline. [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended. diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 6787b5d20a..6996061bd8 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -202,6 +202,13 @@ Returns the icon of the item at the given [param index]. + + + + + Returns the maximum allowed width of the icon for the item at the given [param index]. + + @@ -397,6 +404,14 @@ Replaces the [Texture2D] icon of the item at the given [param index]. + + + + + + Sets the maximum allowed width of the icon for the item at the given [param index]. This limit is applied on top of the default size of the icon and on top of [theme_item icon_max_width]. The height is adjusted according to the icon's ratio. + + @@ -573,6 +588,9 @@ The horizontal space between the item's elements. + + The maximum allowed width of the item's icon. This limit is applied on top of the default size of the icon, but before the value set with [method set_item_icon_max_width]. The height is adjusted according to the icon's ratio. + Width of the single indentation level. diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml index ae6d589339..7211fc2137 100644 --- a/doc/classes/TabBar.xml +++ b/doc/classes/TabBar.xml @@ -46,14 +46,21 @@ - Returns the [Texture2D] for the right button of the tab at index [param tab_idx] or [code]null[/code] if the button has no [Texture2D]. + Returns the icon for the right button of the tab at index [param tab_idx] or [code]null[/code] if the right button has no icon. - Returns the [Texture2D] for the tab at index [param tab_idx] or [code]null[/code] if the tab has no [Texture2D]. + Returns the icon for the tab at index [param tab_idx] or [code]null[/code] if the tab has no icon. + + + + + + + Returns the maximum allowed width of the icon for the tab at index [param tab_idx]. @@ -158,6 +165,14 @@ Sets an [param icon] for the tab at index [param tab_idx]. + + + + + + Sets the maximum allowed width of the icon for the tab at index [param tab_idx]. This limit is applied on top of the default size of the icon and on top of [theme_item icon_max_width]. The height is adjusted according to the icon's ratio. + + @@ -323,6 +338,9 @@ The horizontal separation between the elements inside tabs. + + The maximum allowed width of the tab's icon. This limit is applied on top of the default size of the icon, but before the value set with [method set_tab_icon_max_width]. The height is adjusted according to the icon's ratio. + The size of the tab text outline. [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended. diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index c34336353f..b0dcb932dc 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -209,6 +209,9 @@ Font color of the other, unselected tabs. + + The maximum allowed width of the tab's icon. This limit is applied on top of the default size of the icon, but before the value set with [method TabBar.set_tab_icon_max_width]. The height is adjusted according to the icon's ratio. + Space between tab's name and its icon. diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 95778f86c4..d09f61b8c8 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -518,6 +518,9 @@ The horizontal space between item cells. This is also used as the margin at the start of an item when folding is disabled. + + The maximum allowed width of the icon in item's cells. This limit is applied on top of the default size of the icon, but before the value set with [method TreeItem.set_icon_max_width]. The height is adjusted according to the icon's ratio. + The horizontal margin at the start of an item. This is used when folding is enabled for the item. diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 3ce434e069..49b4622aed 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -183,7 +183,7 @@ - Returns the column's icon's maximum width. + Returns the maximum allowed width of the icon in the given [param column]. @@ -545,7 +545,7 @@ - Sets the given column's icon's maximum width. + Sets the maximum allowed width of the icon in the given [param column]. This limit is applied on top of the default size of the icon and on top of [theme_item Tree.icon_max_width]. The height is adjusted according to the icon's ratio. diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index ee47ee5729..aaf106a1c7 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -462,6 +462,11 @@ void CreateDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { + const int icon_width = get_theme_constant(SNAME("class_icon_size"), SNAME("Editor")); + search_options->add_theme_constant_override("icon_max_width", icon_width); + favorites->add_theme_constant_override("icon_max_width", icon_width); + recent->set_fixed_icon_size(Size2(icon_width, icon_width)); + _update_theme(); } break; } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 3059ce445c..c381c8c322 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -31,10 +31,13 @@ #include "editor_data.h" #include "core/config/project_settings.h" +#include "core/extension/gdextension_manager.h" #include "core/io/file_access.h" +#include "core/io/image_loader.h" #include "core/io/resource_loader.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" +#include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/script_editor_plugin.h" #include "scene/resources/packed_scene.h" @@ -457,10 +460,10 @@ void EditorData::add_custom_type(const String &p_type, const String &p_inherits, ct.name = p_type; ct.icon = p_icon; ct.script = p_script; + if (!custom_types.has(p_inherits)) { custom_types[p_inherits] = Vector(); } - custom_types[p_inherits].push_back(ct); } @@ -1028,8 +1031,66 @@ void EditorData::script_class_load_icon_paths() { } } +Ref EditorData::extension_class_get_icon(const String &p_class) const { + if (GDExtensionManager::get_singleton()->class_has_icon_path(p_class)) { + String icon_path = GDExtensionManager::get_singleton()->class_get_icon_path(p_class); + Ref icon = _load_script_icon(icon_path); + if (icon.is_valid()) { + return icon; + } + } + return nullptr; +} + +Ref EditorData::_load_script_icon(const String &p_path) const { + if (!p_path.is_empty() && ResourceLoader::exists(p_path)) { + Ref icon = ResourceLoader::load(p_path); + if (icon.is_valid()) { + return icon; + } + } + return nullptr; +} + +Ref EditorData::get_script_icon(const Ref