summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/action_map_editor.cpp3
-rw-r--r--editor/connections_dialog.cpp2
-rw-r--r--editor/debugger/script_editor_debugger.cpp2
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/editor_about.cpp1
-rw-r--r--editor/editor_file_dialog.cpp21
-rw-r--r--editor/editor_fonts.cpp14
-rw-r--r--editor/editor_node.cpp74
-rw-r--r--editor/editor_plugin_settings.cpp4
-rw-r--r--editor/editor_properties.cpp158
-rw-r--r--editor/editor_properties.h25
-rw-r--r--editor/editor_resource_picker.cpp2
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/editor_themes.cpp3
-rw-r--r--editor/export_template_manager.cpp5
-rw-r--r--editor/groups_editor.cpp8
-rw-r--r--editor/localization_editor.cpp20
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp10
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp5
-rw-r--r--editor/plugins/theme_editor_plugin.cpp292
-rw-r--r--editor/plugins/theme_editor_plugin.h55
-rw-r--r--editor/plugins/theme_editor_preview.cpp2
-rw-r--r--editor/project_export.cpp5
-rw-r--r--editor/property_editor.cpp2
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--editor/scene_tree_editor.cpp1
26 files changed, 541 insertions, 181 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 7ed603410d..1c3ba89cd3 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -631,6 +631,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
additional_options_container->hide();
Label *opts_label = memnew(Label);
+ opts_label->set_theme_type_variation("HeaderSmall");
opts_label->set_text("Additional Options");
additional_options_container->add_child(opts_label);
@@ -639,6 +640,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *device_label = memnew(Label);
+ device_label->set_theme_type_variation("HeaderSmall");
device_label->set_text("Device:");
device_container->add_child(device_label);
@@ -858,6 +860,7 @@ Variant ActionMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
String name = selected->get_text(0);
Label *label = memnew(Label(name));
+ label->set_theme_type_variation("HeaderSmall");
label->set_modulate(Color(1, 1, 1, 1.0f));
action_tree->set_drag_preview(label);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index de6407da73..c79a8d9a0e 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -1121,7 +1121,7 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) {
add_child(slot_menu);
slot_menu->connect("id_pressed", callable_mp(this, &ConnectionsDock::_handle_slot_menu_option));
slot_menu->add_item(TTR("Edit..."), EDIT);
- slot_menu->add_item(TTR("Go To Method"), GO_TO_SCRIPT);
+ slot_menu->add_item(TTR("Go to Method"), GO_TO_SCRIPT);
slot_menu->add_item(TTR("Disconnect"), DISCONNECT);
connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection));
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 508b984b91..09bbf846fe 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1700,6 +1700,8 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
VBoxContainer *vmem_vb = memnew(VBoxContainer);
HBoxContainer *vmem_hb = memnew(HBoxContainer);
Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:") + " "));
+ vmlb->set_theme_type_variation("HeaderSmall");
+
vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
vmem_hb->add_child(vmlb);
vmem_hb->add_child(memnew(Label(TTR("Total:") + " ")));
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index ef571e5c7a..e26344f3ec 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -236,6 +236,8 @@ DependencyEditor::DependencyEditor() {
HBoxContainer *hbc = memnew(HBoxContainer);
Label *label = memnew(Label(TTR("Dependencies:")));
+ label->set_theme_type_variation("HeaderSmall");
+
hbc->add_child(label);
hbc->add_spacer();
fixdeps = memnew(Button(TTR("Fix Broken")));
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index e28ba9a184..1f1446a8a8 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -92,6 +92,7 @@ ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<St
const char *const *names_ptr = p_src[i];
if (*names_ptr) {
Label *lbl = memnew(Label);
+ lbl->set_theme_type_variation("HeaderSmall");
lbl->set_text(p_sections[i]);
vbc->add_child(lbl);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index fe4c6f490d..a07b3a7c19 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -1510,7 +1510,9 @@ EditorFileDialog::EditorFileDialog() {
dir_next->connect("pressed", callable_mp(this, &EditorFileDialog::_go_forward));
dir_up->connect("pressed", callable_mp(this, &EditorFileDialog::_go_up));
- pathhb->add_child(memnew(Label(TTR("Path:"))));
+ Label *l = memnew(Label(TTR("Path:")));
+ l->set_theme_type_variation("HeaderSmall");
+ pathhb->add_child(l);
drives_container = memnew(HBoxContainer);
pathhb->add_child(drives_container);
@@ -1591,7 +1593,11 @@ EditorFileDialog::EditorFileDialog() {
fav_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
HBoxContainer *fav_hb = memnew(HBoxContainer);
fav_vb->add_child(fav_hb);
- fav_hb->add_child(memnew(Label(TTR("Favorites:"))));
+
+ l = memnew(Label(TTR("Favorites:")));
+ l->set_theme_type_variation("HeaderSmall");
+ fav_hb->add_child(l);
+
fav_hb->add_spacer();
fav_up = memnew(Button);
fav_up->set_flat(true);
@@ -1626,7 +1632,10 @@ EditorFileDialog::EditorFileDialog() {
VBoxContainer *list_vb = memnew(VBoxContainer);
list_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- list_vb->add_child(memnew(Label(TTR("Directories & Files:"))));
+
+ l = memnew(Label(TTR("Directories & Files:")));
+ l->set_theme_type_variation("HeaderSmall");
+ list_vb->add_child(l);
preview_hb->add_child(list_vb);
// Item (files and folders) list with context menu.
@@ -1653,7 +1662,11 @@ EditorFileDialog::EditorFileDialog() {
preview_vb->hide();
file_box = memnew(HBoxContainer);
- file_box->add_child(memnew(Label(TTR("File:"))));
+
+ l = memnew(Label(TTR("File:")));
+ l->set_theme_type_variation("HeaderSmall");
+ file_box->add_child(l);
+
file = memnew(LineEdit);
file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index d548196a2d..8968e562c1 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -319,7 +319,19 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font_size("main_button_font_size", "EditorFonts", default_font_size + 1 * EDSCALE);
p_theme->set_font("main_button_font", "EditorFonts", df_bold);
- p_theme->set_font("font", "Label", df_bold);
+ p_theme->set_font("font", "Label", df);
+
+ p_theme->set_type_variation("HeaderSmall", "Label");
+ p_theme->set_font("font", "HeaderSmall", df_bold);
+ p_theme->set_font_size("font_size", "HeaderSmall", default_font_size);
+
+ p_theme->set_type_variation("HeaderMedium", "Label");
+ p_theme->set_font("font", "HeaderMedium", df_bold);
+ p_theme->set_font_size("font_size", "HeaderMedium", default_font_size + 1 * EDSCALE);
+
+ p_theme->set_type_variation("HeaderLarge", "Label");
+ p_theme->set_font("font", "HeaderLarge", df_bold);
+ p_theme->set_font_size("font_size", "HeaderLarge", default_font_size + 3 * EDSCALE);
// Documentation fonts
MAKE_SOURCE_FONT(df_code);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 4cfa2d7338..4d52414748 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3736,46 +3736,46 @@ void EditorNode::register_editor_types() {
ResourceLoader::set_timestamp_on_load(true);
ResourceSaver::set_timestamp_on_save(true);
- ClassDB::register_class<EditorPaths>();
- ClassDB::register_class<EditorPlugin>();
- ClassDB::register_class<EditorTranslationParserPlugin>();
- ClassDB::register_class<EditorImportPlugin>();
- ClassDB::register_class<EditorScript>();
- ClassDB::register_class<EditorSelection>();
- ClassDB::register_class<EditorFileDialog>();
- ClassDB::register_virtual_class<EditorSettings>();
- ClassDB::register_class<EditorNode3DGizmo>();
- ClassDB::register_class<EditorNode3DGizmoPlugin>();
- ClassDB::register_virtual_class<EditorResourcePreview>();
- ClassDB::register_class<EditorResourcePreviewGenerator>();
- ClassDB::register_virtual_class<EditorFileSystem>();
- ClassDB::register_class<EditorFileSystemDirectory>();
- ClassDB::register_class<EditorVCSInterface>();
- ClassDB::register_virtual_class<ScriptEditor>();
- ClassDB::register_virtual_class<ScriptEditorBase>();
- ClassDB::register_class<EditorSyntaxHighlighter>();
- ClassDB::register_virtual_class<EditorInterface>();
- ClassDB::register_class<EditorExportPlugin>();
- ClassDB::register_class<EditorResourceConversionPlugin>();
- ClassDB::register_class<EditorSceneImporter>();
- ClassDB::register_class<EditorInspector>();
- ClassDB::register_class<EditorInspectorPlugin>();
- ClassDB::register_class<EditorProperty>();
- ClassDB::register_class<AnimationTrackEditPlugin>();
- ClassDB::register_class<ScriptCreateDialog>();
- ClassDB::register_class<EditorFeatureProfile>();
- ClassDB::register_class<EditorSpinSlider>();
- ClassDB::register_class<EditorResourcePicker>();
- ClassDB::register_class<EditorScriptPicker>();
- ClassDB::register_class<EditorSceneImporterMesh>();
- ClassDB::register_class<EditorSceneImporterMeshNode3D>();
-
- ClassDB::register_virtual_class<FileSystemDock>();
+ GDREGISTER_CLASS(EditorPaths);
+ GDREGISTER_CLASS(EditorPlugin);
+ GDREGISTER_CLASS(EditorTranslationParserPlugin);
+ GDREGISTER_CLASS(EditorImportPlugin);
+ GDREGISTER_CLASS(EditorScript);
+ GDREGISTER_CLASS(EditorSelection);
+ GDREGISTER_CLASS(EditorFileDialog);
+ GDREGISTER_VIRTUAL_CLASS(EditorSettings);
+ GDREGISTER_CLASS(EditorNode3DGizmo);
+ GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
+ GDREGISTER_VIRTUAL_CLASS(EditorResourcePreview);
+ GDREGISTER_CLASS(EditorResourcePreviewGenerator);
+ GDREGISTER_VIRTUAL_CLASS(EditorFileSystem);
+ GDREGISTER_CLASS(EditorFileSystemDirectory);
+ GDREGISTER_CLASS(EditorVCSInterface);
+ GDREGISTER_VIRTUAL_CLASS(ScriptEditor);
+ GDREGISTER_VIRTUAL_CLASS(ScriptEditorBase);
+ GDREGISTER_CLASS(EditorSyntaxHighlighter);
+ GDREGISTER_VIRTUAL_CLASS(EditorInterface);
+ GDREGISTER_CLASS(EditorExportPlugin);
+ GDREGISTER_CLASS(EditorResourceConversionPlugin);
+ GDREGISTER_CLASS(EditorSceneImporter);
+ GDREGISTER_CLASS(EditorInspector);
+ GDREGISTER_CLASS(EditorInspectorPlugin);
+ GDREGISTER_CLASS(EditorProperty);
+ GDREGISTER_CLASS(AnimationTrackEditPlugin);
+ GDREGISTER_CLASS(ScriptCreateDialog);
+ GDREGISTER_CLASS(EditorFeatureProfile);
+ GDREGISTER_CLASS(EditorSpinSlider);
+ GDREGISTER_CLASS(EditorResourcePicker);
+ GDREGISTER_CLASS(EditorScriptPicker);
+ GDREGISTER_CLASS(EditorSceneImporterMesh);
+ GDREGISTER_CLASS(EditorSceneImporterMeshNode3D);
+
+ GDREGISTER_VIRTUAL_CLASS(FileSystemDock);
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
- ClassDB::register_class<EditorScenePostImport>();
+ GDREGISTER_CLASS(EditorScenePostImport);
//ClassDB::register_type<EditorImportExport>();
- ClassDB::register_class<EditorDebuggerPlugin>();
+ GDREGISTER_CLASS(EditorDebuggerPlugin);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
}
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index b4e5a58c21..a16a2f327e 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -192,7 +192,9 @@ EditorPluginSettings::EditorPluginSettings() {
add_child(plugin_config_dialog);
HBoxContainer *title_hb = memnew(HBoxContainer);
- title_hb->add_child(memnew(Label(TTR("Installed Plugins:"))));
+ Label *l = memnew(Label(TTR("Installed Plugins:")));
+ l->set_theme_type_variation("HeaderSmall");
+ title_hb->add_child(l);
title_hb->add_spacer();
create_plugin = memnew(Button(TTR("Create")));
create_plugin->connect("pressed", callable_mp(this, &EditorPluginSettings::_create_clicked));
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 84105f0cb7..ebd8d6427b 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -180,44 +180,150 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() {
///////////////////// TEXT ENUM /////////////////////////
-void EditorPropertyTextEnum::_option_selected(int p_which) {
+void EditorPropertyTextEnum::_emit_changed_value(String p_string) {
if (string_name) {
- emit_changed(get_edited_property(), StringName(options->get_item_text(p_which)));
+ emit_changed(get_edited_property(), StringName(p_string));
} else {
- emit_changed(get_edited_property(), options->get_item_text(p_which));
+ emit_changed(get_edited_property(), p_string);
}
}
+void EditorPropertyTextEnum::_option_selected(int p_which) {
+ _emit_changed_value(option_button->get_item_text(p_which));
+}
+
+void EditorPropertyTextEnum::_edit_custom_value() {
+ default_layout->hide();
+ edit_custom_layout->show();
+ custom_value_edit->grab_focus();
+}
+
+void EditorPropertyTextEnum::_custom_value_submitted(String p_value) {
+ edit_custom_layout->hide();
+ default_layout->show();
+
+ _emit_changed_value(p_value.strip_edges());
+}
+
+void EditorPropertyTextEnum::_custom_value_accepted() {
+ String new_value = custom_value_edit->get_text().strip_edges();
+ _custom_value_submitted(new_value);
+}
+
+void EditorPropertyTextEnum::_custom_value_cancelled() {
+ custom_value_edit->set_text(get_edited_object()->get(get_edited_property()));
+
+ edit_custom_layout->hide();
+ default_layout->show();
+}
+
void EditorPropertyTextEnum::update_property() {
- String which = get_edited_object()->get(get_edited_property());
- for (int i = 0; i < options->get_item_count(); i++) {
- String t = options->get_item_text(i);
- if (t == which) {
- options->select(i);
- return;
+ String current_value = get_edited_object()->get(get_edited_property());
+ int default_option = options.find(current_value);
+
+ // The list can change in the loose mode.
+ if (loose_mode) {
+ custom_value_edit->set_text(current_value);
+ option_button->clear();
+
+ // Manually entered value.
+ if (default_option < 0 && !current_value.is_empty()) {
+ option_button->add_item(current_value, options.size() + 1001);
+ option_button->select(0);
+
+ option_button->add_separator();
}
+
+ // Add an explicit empty value for clearing the property.
+ option_button->add_item("", options.size() + 1000);
+
+ for (int i = 0; i < options.size(); i++) {
+ option_button->add_item(options[i], i);
+ if (options[i] == current_value) {
+ option_button->select(option_button->get_item_count() - 1);
+ }
+ }
+ } else {
+ option_button->select(default_option);
}
}
-void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name) {
+void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name, bool p_loose_mode) {
+ string_name = p_string_name;
+ loose_mode = p_loose_mode;
+
+ options.clear();
+
+ if (loose_mode) {
+ // Add an explicit empty value for clearing the property in the loose mode.
+ option_button->add_item("", options.size() + 1000);
+ }
+
for (int i = 0; i < p_options.size(); i++) {
- options->add_item(p_options[i], i);
+ options.append(p_options[i]);
+ option_button->add_item(p_options[i], i);
+ }
+
+ if (loose_mode) {
+ edit_button->show();
}
- string_name = p_string_name;
}
void EditorPropertyTextEnum::_bind_methods() {
}
-EditorPropertyTextEnum::EditorPropertyTextEnum() {
- options = memnew(OptionButton);
- options->set_clip_text(true);
- options->set_flat(true);
- string_name = false;
+void EditorPropertyTextEnum::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ edit_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
+ accept_button->set_icon(get_theme_icon("ImportCheck", "EditorIcons"));
+ cancel_button->set_icon(get_theme_icon("ImportFail", "EditorIcons"));
+ break;
+ }
+}
- add_child(options);
- add_focusable(options);
- options->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected));
+EditorPropertyTextEnum::EditorPropertyTextEnum() {
+ default_layout = memnew(HBoxContainer);
+ add_child(default_layout);
+
+ edit_custom_layout = memnew(HBoxContainer);
+ edit_custom_layout->hide();
+ add_child(edit_custom_layout);
+
+ option_button = memnew(OptionButton);
+ option_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ option_button->set_clip_text(true);
+ option_button->set_flat(true);
+ default_layout->add_child(option_button);
+ option_button->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected));
+
+ edit_button = memnew(Button);
+ edit_button->set_flat(true);
+ edit_button->hide();
+ default_layout->add_child(edit_button);
+ edit_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_edit_custom_value));
+
+ custom_value_edit = memnew(LineEdit);
+ custom_value_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_custom_layout->add_child(custom_value_edit);
+ custom_value_edit->connect("text_submitted", callable_mp(this, &EditorPropertyTextEnum::_custom_value_submitted));
+
+ accept_button = memnew(Button);
+ accept_button->set_flat(true);
+ edit_custom_layout->add_child(accept_button);
+ accept_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_accepted));
+
+ cancel_button = memnew(Button);
+ cancel_button->set_flat(true);
+ edit_custom_layout->add_child(cancel_button);
+ cancel_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_cancelled));
+
+ add_focusable(option_button);
+ add_focusable(edit_button);
+ add_focusable(custom_value_edit);
+ add_focusable(accept_button);
+ add_focusable(cancel_button);
}
///////////////////// PATH /////////////////////////
@@ -2902,10 +3008,10 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
}
} break;
case Variant::STRING: {
- if (p_hint == PROPERTY_HINT_ENUM) {
+ if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) {
EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum);
- Vector<String> options = p_hint_text.split(",");
- editor->setup(options);
+ Vector<String> options = p_hint_text.split(",", false);
+ editor->setup(options, false, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION));
return editor;
} else if (p_hint == PROPERTY_HINT_MULTILINE_TEXT) {
EditorPropertyMultilineText *editor = memnew(EditorPropertyMultilineText);
@@ -3063,10 +3169,10 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
return editor;
} break;
case Variant::STRING_NAME: {
- if (p_hint == PROPERTY_HINT_ENUM) {
+ if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) {
EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum);
- Vector<String> options = p_hint_text.split(",");
- editor->setup(options, true);
+ Vector<String> options = p_hint_text.split(",", false);
+ editor->setup(options, true, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION));
return editor;
} else {
EditorPropertyText *editor = memnew(EditorPropertyText);
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index d880017cc1..0cb21bb391 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -91,16 +91,35 @@ public:
class EditorPropertyTextEnum : public EditorProperty {
GDCLASS(EditorPropertyTextEnum, EditorProperty);
- OptionButton *options;
+ HBoxContainer *default_layout;
+ HBoxContainer *edit_custom_layout;
+
+ OptionButton *option_button;
+ Button *edit_button;
+
+ LineEdit *custom_value_edit;
+ Button *accept_button;
+ Button *cancel_button;
+
+ Vector<String> options;
+ bool string_name = false;
+ bool loose_mode = false;
+
+ void _emit_changed_value(String p_string);
void _option_selected(int p_which);
- bool string_name;
+
+ void _edit_custom_value();
+ void _custom_value_submitted(String p_value);
+ void _custom_value_accepted();
+ void _custom_value_cancelled();
protected:
static void _bind_methods();
+ void _notification(int p_what);
public:
- void setup(const Vector<String> &p_options, bool p_string_name = false);
+ void setup(const Vector<String> &p_options, bool p_string_name = false, bool p_loose_mode = false);
virtual void update_property() override;
EditorPropertyTextEnum();
};
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 350fc5eccb..4d9865622c 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -205,7 +205,7 @@ void EditorResourcePicker::_update_menu_items() {
icon = get_theme_icon(what, "Resource");
}
- edit_menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ edit_menu->add_icon_item(icon, vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
}
}
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 080563f375..b6f889268f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -884,7 +884,7 @@ void EditorSettings::create() {
return;
}
- ClassDB::register_class<EditorSettings>(); // Otherwise it can't be unserialized.
+ GDREGISTER_CLASS(EditorSettings); // Otherwise it can't be unserialized.
String config_file_path;
Ref<ConfigFile> extra_config = memnew(ConfigFile);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 131a77e52f..986fc147f9 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1004,6 +1004,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// LineEdit
Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate();
+ // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
+ // so this compensates for that.
+ style_line_edit->set_default_margin(SIDE_TOP, style_line_edit->get_default_margin(SIDE_TOP) - 1 * EDSCALE);
// Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
// such as the Project Settings.
style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index dd4ce74406..112a9e92a8 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -812,6 +812,7 @@ ExportTemplateManager::ExportTemplateManager() {
main_vb->add_child(current_hb);
Label *current_label = memnew(Label);
+ current_label->set_theme_type_variation("HeaderSmall");
current_label->set_text(TTR("Current Version:"));
current_hb->add_child(current_label);
@@ -821,6 +822,8 @@ ExportTemplateManager::ExportTemplateManager() {
// Current version statuses.
// Status: Current version is missing.
current_missing_label = memnew(Label);
+ current_missing_label->set_theme_type_variation("HeaderSmall");
+
current_missing_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_missing_label->set_align(Label::ALIGN_RIGHT);
current_missing_label->set_text(TTR("Export templates are missing. Download them or install from a file."));
@@ -828,6 +831,7 @@ ExportTemplateManager::ExportTemplateManager() {
// Status: Current version is installed.
current_installed_label = memnew(Label);
+ current_installed_label->set_theme_type_variation("HeaderSmall");
current_installed_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_installed_label->set_align(Label::ALIGN_RIGHT);
current_installed_label->set_text(TTR("Export templates are installed and ready to be used."));
@@ -947,6 +951,7 @@ ExportTemplateManager::ExportTemplateManager() {
HBoxContainer *installed_versions_hb = memnew(HBoxContainer);
main_vb->add_child(installed_versions_hb);
Label *installed_label = memnew(Label);
+ installed_label->set_theme_type_variation("HeaderSmall");
installed_label->set_text(TTR("Other Installed Versions:"));
installed_versions_hb->add_child(installed_label);
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 1be7a5336a..76fbee7490 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -424,6 +424,8 @@ GroupDialog::GroupDialog() {
vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *group_title = memnew(Label);
+ group_title->set_theme_type_variation("HeaderSmall");
+
group_title->set_text(TTR("Groups"));
vbc_left->add_child(group_title);
@@ -458,6 +460,8 @@ GroupDialog::GroupDialog() {
vbc_add->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *out_of_group_title = memnew(Label);
+ out_of_group_title->set_theme_type_variation("HeaderSmall");
+
out_of_group_title->set_text(TTR("Nodes Not in Group"));
vbc_add->add_child(out_of_group_title);
@@ -506,6 +510,8 @@ GroupDialog::GroupDialog() {
vbc_remove->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *in_group_title = memnew(Label);
+ in_group_title->set_theme_type_variation("HeaderSmall");
+
in_group_title->set_text(TTR("Nodes in Group"));
vbc_remove->add_child(in_group_title);
@@ -528,6 +534,8 @@ GroupDialog::GroupDialog() {
remove_filter->connect("text_changed", callable_mp(this, &GroupDialog::_remove_filter_changed));
group_empty = memnew(Label());
+ group_empty->set_theme_type_variation("HeaderSmall");
+
group_empty->set_text(TTR("Empty groups will be automatically removed."));
group_empty->set_valign(Label::VALIGN_CENTER);
group_empty->set_align(Label::ALIGN_CENTER);
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 208d4437d3..977ca83671 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -656,7 +656,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Translations:"))));
+ Label *l = memnew(Label(TTR("Translations:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -684,7 +686,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Resources:"))));
+ Label *l = memnew(Label(TTR("Resources:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -708,7 +712,9 @@ LocalizationEditor::LocalizationEditor() {
add_child(translation_res_file_open_dialog);
thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Remaps by Locale:"))));
+ l = memnew(Label(TTR("Remaps by Locale:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -758,7 +764,9 @@ LocalizationEditor::LocalizationEditor() {
translation_locale_filter_mode->connect("item_selected", callable_mp(this, &LocalizationEditor::_translation_filter_mode_changed));
tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode);
- tmc->add_child(memnew(Label(TTR("Locales:"))));
+ Label *l = memnew(Label(TTR("Locales:")));
+ l->set_theme_type_variation("HeaderSmall");
+ tmc->add_child(l);
translation_filter = memnew(Tree);
translation_filter->set_v_size_flags(Control::SIZE_EXPAND_FILL);
translation_filter->set_columns(1);
@@ -772,7 +780,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Files with translation strings:"))));
+ Label *l = memnew(Label(TTR("Files with translation strings:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 94cd8ce17d..bd9847ea95 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5630,11 +5630,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
// those shortcuts one by one.
// Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`,
// but it ensures both 1 and Ctrl + 0 can be used to reset zoom.
- ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom To 100%"), KEY_1);
- ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom To 200%"), KEY_2);
- ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom To 400%"), KEY_3);
- ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom To 800%"), KEY_4);
- ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom To 1600%"), KEY_5);
+ ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom to 100%"), KEY_1);
+ ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom to 200%"), KEY_2);
+ ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom to 400%"), KEY_3);
+ ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), KEY_4);
+ ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), KEY_5);
set_process_unhandled_key_input(true);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 72a63539b3..3532473e17 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -6181,7 +6181,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() {
}
if (snapped_to_floor) {
- undo_redo->create_action(TTR("Snap Nodes To Floor"));
+ undo_redo->create_action(TTR("Snap Nodes to Floor"));
// Perform snapping if at least one node can be snapped
for (int i = 0; i < keys.size(); i++) {
@@ -7137,6 +7137,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
sun_vb->hide();
sun_title = memnew(Label);
+ sun_title->set_theme_type_variation("HeaderSmall");
sun_vb->add_child(sun_title);
sun_title->set_text(TTR("Preview Sun"));
sun_title->set_align(Label::ALIGN_CENTER);
@@ -7228,6 +7229,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
environ_vb->hide();
environ_title = memnew(Label);
+ environ_title->set_theme_type_variation("HeaderSmall");
+
environ_vb->add_child(environ_title);
environ_title->set_text(TTR("Preview Environment"));
environ_title->set_align(Label::ALIGN_CENTER);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 5523333fa5..0a8a0dcdce 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -1943,6 +1943,117 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
+void ThemeTypeDialog::_dialog_about_to_show() {
+ add_type_filter->set_text("");
+ add_type_filter->grab_focus();
+
+ _update_add_type_options();
+}
+
+void ThemeTypeDialog::ok_pressed() {
+ emit_signal("type_selected", add_type_filter->get_text().strip_edges());
+}
+
+void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
+ add_type_options->clear();
+
+ List<StringName> names;
+ Theme::get_default()->get_type_list(&names);
+ if (include_own_types) {
+ edited_theme->get_type_list(&names);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+
+ Vector<StringName> unique_names;
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ // Filter out undesired values.
+ if (!p_filter.is_subsequence_ofi(String(E->get()))) {
+ continue;
+ }
+
+ // Skip duplicate values.
+ if (unique_names.has(E->get())) {
+ continue;
+ }
+ unique_names.append(E->get());
+
+ Ref<Texture2D> item_icon;
+ if (E->get() == "") {
+ item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ } else {
+ item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ }
+
+ add_type_options->add_item(E->get(), item_icon);
+ }
+}
+
+void ThemeTypeDialog::_add_type_filter_cbk(const String &p_value) {
+ _update_add_type_options(p_value);
+}
+
+void ThemeTypeDialog::_add_type_options_cbk(int p_index) {
+ add_type_filter->set_text(add_type_options->get_item_text(p_index));
+}
+
+void ThemeTypeDialog::_add_type_dialog_entered(const String &p_value) {
+ emit_signal("type_selected", p_value.strip_edges());
+ hide();
+}
+
+void ThemeTypeDialog::_add_type_dialog_activated(int p_index) {
+ emit_signal("type_selected", add_type_options->get_item_text(p_index));
+ hide();
+}
+
+void ThemeTypeDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ connect("about_to_popup", callable_mp(this, &ThemeTypeDialog::_dialog_about_to_show));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_add_type_options();
+ } break;
+ }
+}
+
+void ThemeTypeDialog::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("type_selected", PropertyInfo(Variant::STRING, "type_name")));
+}
+
+void ThemeTypeDialog::set_edited_theme(const Ref<Theme> &p_theme) {
+ edited_theme = p_theme;
+}
+
+void ThemeTypeDialog::set_include_own_types(bool p_enable) {
+ include_own_types = p_enable;
+}
+
+ThemeTypeDialog::ThemeTypeDialog() {
+ VBoxContainer *add_type_vb = memnew(VBoxContainer);
+ add_child(add_type_vb);
+
+ Label *add_type_filter_label = memnew(Label);
+ add_type_filter_label->set_text(TTR("Name:"));
+ add_type_vb->add_child(add_type_filter_label);
+
+ add_type_filter = memnew(LineEdit);
+ add_type_vb->add_child(add_type_filter);
+ add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeDialog::_add_type_filter_cbk));
+ add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_entered));
+
+ Label *add_type_options_label = memnew(Label);
+ add_type_options_label->set_text(TTR("Node Types:"));
+ add_type_vb->add_child(add_type_options_label);
+
+ add_type_options = memnew(ItemList);
+ add_type_options->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_type_vb->add_child(add_type_options);
+ add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeDialog::_add_type_options_cbk));
+ add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_activated));
+}
+
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
VBoxContainer *items_tab = memnew(VBoxContainer);
items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
@@ -2048,36 +2159,18 @@ void ThemeTypeEditor::_update_type_list_debounced() {
update_debounce_timer->start();
}
-void ThemeTypeEditor::_update_add_type_options(const String &p_filter) {
- add_type_options->clear();
-
- List<StringName> names;
- Theme::get_default()->get_type_list(&names);
- names.sort_custom<StringName::AlphCompare>();
-
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!p_filter.is_subsequence_ofi(String(E->get()))) {
- continue;
- }
-
- Ref<Texture2D> item_icon;
- if (E->get() == "") {
- item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
- } else {
- item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
- }
-
- add_type_options->add_item(E->get(), item_icon);
- }
-}
-
OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
OrderedHashMap<StringName, bool> items;
List<StringName> names;
if (include_default) {
names.clear();
- (Theme::get_default().operator->()->*get_list_func)(p_type_name, &names);
+ String default_type = p_type_name;
+ if (edited_theme->get_type_variation_base(p_type_name) != StringName()) {
+ default_type = edited_theme->get_type_variation_base(p_type_name);
+ }
+
+ (Theme::get_default().operator->()->*get_list_func)(default_type, &names);
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
items[E->get()] = false;
@@ -2435,6 +2528,20 @@ void ThemeTypeEditor::_update_type_items() {
stylebox_items_list->add_child(item_control);
}
}
+
+ // Various type settings.
+ if (ClassDB::class_exists(edited_type)) {
+ type_variation_edit->set_editable(false);
+ type_variation_edit->set_tooltip(TTR("A type associated with a built-in class cannot be marked as a variation of another type."));
+ type_variation_edit->set_text("");
+ type_variation_button->hide();
+ } else {
+ type_variation_edit->set_editable(true);
+ type_variation_edit->set_tooltip("");
+ type_variation_edit->set_text(edited_theme->get_type_variation_base(edited_type));
+ _add_focusable(type_variation_edit);
+ type_variation_button->show();
+ }
}
void ThemeTypeEditor::_list_type_selected(int p_index) {
@@ -2443,34 +2550,18 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
}
void ThemeTypeEditor::_add_type_button_cbk() {
+ add_type_mode = ADD_THEME_TYPE;
+ add_type_dialog->set_title(TTR("Add Item Type"));
+ add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
- add_type_filter->grab_focus();
-}
-
-void ThemeTypeEditor::_add_type_filter_cbk(const String &p_value) {
- _update_add_type_options(p_value);
-}
-
-void ThemeTypeEditor::_add_type_options_cbk(int p_index) {
- add_type_filter->set_text(add_type_options->get_item_text(p_index));
-}
-
-void ThemeTypeEditor::_add_type_dialog_confirmed() {
- select_type(add_type_filter->get_text().strip_edges());
-}
-
-void ThemeTypeEditor::_add_type_dialog_entered(const String &p_value) {
- select_type(p_value.strip_edges());
- add_type_dialog->hide();
-}
-
-void ThemeTypeEditor::_add_type_dialog_activated(int p_index) {
- select_type(add_type_options->get_item_text(p_index));
- add_type_dialog->hide();
}
void ThemeTypeEditor::_add_default_type_items() {
List<StringName> names;
+ String default_type = edited_type;
+ if (edited_theme->get_type_variation_base(edited_type) != StringName()) {
+ default_type = edited_theme->get_type_variation_base(edited_type);
+ }
updating = true;
// Prevent changes from immediatelly being reported while the operation is still ongoing.
@@ -2478,7 +2569,7 @@ void ThemeTypeEditor::_add_default_type_items() {
{
names.clear();
- Theme::get_default()->get_icon_list(edited_type, &names);
+ Theme::get_default()->get_icon_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_icon(E->get(), edited_type)) {
edited_theme->set_icon(E->get(), edited_type, Ref<Texture2D>());
@@ -2487,7 +2578,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_stylebox_list(edited_type, &names);
+ Theme::get_default()->get_stylebox_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_stylebox(E->get(), edited_type)) {
edited_theme->set_stylebox(E->get(), edited_type, Ref<StyleBox>());
@@ -2496,7 +2587,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_font_list(edited_type, &names);
+ Theme::get_default()->get_font_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font(E->get(), edited_type)) {
edited_theme->set_font(E->get(), edited_type, Ref<Font>());
@@ -2505,28 +2596,28 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_font_size_list(edited_type, &names);
+ Theme::get_default()->get_font_size_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font_size(E->get(), edited_type)) {
- edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), edited_type));
+ edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), default_type));
}
}
}
{
names.clear();
- Theme::get_default()->get_color_list(edited_type, &names);
+ Theme::get_default()->get_color_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_color(E->get(), edited_type)) {
- edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), edited_type));
+ edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), default_type));
}
}
}
{
names.clear();
- Theme::get_default()->get_constant_list(edited_type, &names);
+ Theme::get_default()->get_constant_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_constant(E->get(), edited_type)) {
- edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), edited_type));
+ edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), default_type));
}
}
}
@@ -2817,6 +2908,30 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
edited_theme->_unfreeze_and_propagate_changes();
}
+void ThemeTypeEditor::_type_variation_changed(const String p_value) {
+ if (p_value.is_empty()) {
+ edited_theme->clear_type_variation(edited_type);
+ } else {
+ edited_theme->set_type_variation(edited_type, StringName(p_value));
+ }
+}
+
+void ThemeTypeEditor::_add_type_variation_cbk() {
+ add_type_mode = ADD_VARIATION_BASE;
+ add_type_dialog->set_title(TTR("Add Variation Base Type"));
+ add_type_dialog->set_include_own_types(true);
+ add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
+}
+
+void ThemeTypeEditor::_add_type_dialog_selected(const String p_type_name) {
+ if (add_type_mode == ADD_THEME_TYPE) {
+ select_type(p_type_name);
+ } else if (add_type_mode == ADD_VARIATION_BASE) {
+ _type_variation_changed(p_type_name);
+ _update_type_items();
+ }
+}
+
void ThemeTypeEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
@@ -2829,11 +2944,12 @@ void ThemeTypeEditor::_notification(int p_what) {
data_type_tabs->set_tab_icon(3, get_theme_icon("FontSize", "EditorIcons"));
data_type_tabs->set_tab_icon(4, get_theme_icon("ImageTexture", "EditorIcons"));
data_type_tabs->set_tab_icon(5, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ data_type_tabs->set_tab_icon(6, get_theme_icon("Tools", "EditorIcons"));
data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("tab_selected_odd", "TabContainer"));
data_type_tabs->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
- _update_add_type_options();
+ type_variation_button->set_icon(get_theme_icon("Add", "EditorIcons"));
} break;
}
}
@@ -2846,6 +2962,8 @@ void ThemeTypeEditor::set_edited_theme(const Ref<Theme> &p_theme) {
edited_theme = p_theme;
edited_theme->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_type_list_debounced));
_update_type_list();
+
+ add_type_dialog->set_edited_theme(edited_theme);
}
void ThemeTypeEditor::select_type(String p_type_name) {
@@ -2892,34 +3010,10 @@ ThemeTypeEditor::ThemeTypeEditor() {
theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected));
add_type_button = memnew(Button);
- add_type_button->set_tooltip(TTR("Add Type"));
+ add_type_button->set_tooltip(TTR("Add a type from a list of available types or create a new one."));
type_list_hb->add_child(add_type_button);
add_type_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk));
- add_type_dialog = memnew(ConfirmationDialog);
- add_type_dialog->set_title(TTR("Add Item Type"));
- type_list_hb->add_child(add_type_dialog);
- add_type_dialog->connect("confirmed", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_confirmed));
-
- VBoxContainer *add_type_vb = memnew(VBoxContainer);
- add_type_dialog->add_child(add_type_vb);
-
- Label *add_type_filter_label = memnew(Label);
- add_type_filter_label->set_text(TTR("Name:"));
- add_type_vb->add_child(add_type_filter_label);
- add_type_filter = memnew(LineEdit);
- add_type_vb->add_child(add_type_filter);
- add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_add_type_filter_cbk));
- add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_entered));
- Label *add_type_options_label = memnew(Label);
- add_type_options_label->set_text(TTR("Node Types:"));
- add_type_vb->add_child(add_type_options_label);
- add_type_options = memnew(ItemList);
- add_type_options->set_v_size_flags(SIZE_EXPAND_FILL);
- add_type_vb->add_child(add_type_options);
- add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_add_type_options_cbk));
- add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_activated));
-
HBoxContainer *type_controls = memnew(HBoxContainer);
main_vb->add_child(type_controls);
@@ -2950,6 +3044,39 @@ ThemeTypeEditor::ThemeTypeEditor() {
icon_items_list = _create_item_list(Theme::DATA_TYPE_ICON);
stylebox_items_list = _create_item_list(Theme::DATA_TYPE_STYLEBOX);
+ VBoxContainer *type_settings_tab = memnew(VBoxContainer);
+ type_settings_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
+ data_type_tabs->add_child(type_settings_tab);
+ data_type_tabs->set_tab_title(data_type_tabs->get_tab_count() - 1, "");
+
+ ScrollContainer *type_settings_sc = memnew(ScrollContainer);
+ type_settings_sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ type_settings_sc->set_enable_h_scroll(false);
+ type_settings_tab->add_child(type_settings_sc);
+ VBoxContainer *type_settings_list = memnew(VBoxContainer);
+ type_settings_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ type_settings_sc->add_child(type_settings_list);
+
+ HBoxContainer *type_variation_hb = memnew(HBoxContainer);
+ type_settings_list->add_child(type_variation_hb);
+ Label *type_variation_label = memnew(Label);
+ type_variation_hb->add_child(type_variation_label);
+ type_variation_label->set_text(TTR("Base Type"));
+ type_variation_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ type_variation_edit = memnew(LineEdit);
+ type_variation_hb->add_child(type_variation_edit);
+ type_variation_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ type_variation_edit->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_type_variation_changed));
+ type_variation_edit->connect("focus_exited", callable_mp(this, &ThemeTypeEditor::_update_type_items));
+ type_variation_button = memnew(Button);
+ type_variation_hb->add_child(type_variation_button);
+ type_variation_button->set_tooltip(TTR("Select the variation base type from a list of available types."));
+ type_variation_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_variation_cbk));
+
+ add_type_dialog = memnew(ThemeTypeDialog);
+ add_child(add_type_dialog);
+ add_type_dialog->connect("type_selected", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_selected));
+
update_debounce_timer = memnew(Timer);
update_debounce_timer->set_one_shot(true);
update_debounce_timer->set_wait_time(0.5);
@@ -3094,6 +3221,7 @@ ThemeEditor::ThemeEditor() {
theme_name = memnew(Label);
theme_name->set_text(TTR("Theme") + ": ");
+ theme_name->set_theme_type_variation("HeaderSmall");
top_menu->add_child(theme_name);
top_menu->add_spacer(false);
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index cdedbbec8d..3c114a375a 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -263,6 +263,36 @@ public:
ThemeItemEditorDialog();
};
+class ThemeTypeDialog : public ConfirmationDialog {
+ GDCLASS(ThemeTypeDialog, ConfirmationDialog);
+
+ Ref<Theme> edited_theme;
+ bool include_own_types = false;
+
+ LineEdit *add_type_filter;
+ ItemList *add_type_options;
+
+ void _dialog_about_to_show();
+ void ok_pressed() override;
+
+ void _update_add_type_options(const String &p_filter = "");
+
+ void _add_type_filter_cbk(const String &p_value);
+ void _add_type_options_cbk(int p_index);
+ void _add_type_dialog_entered(const String &p_value);
+ void _add_type_dialog_activated(int p_index);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_edited_theme(const Ref<Theme> &p_theme);
+ void set_include_own_types(bool p_enable);
+
+ ThemeTypeDialog();
+};
+
class ThemeTypeEditor : public MarginContainer {
GDCLASS(ThemeTypeEditor, MarginContainer);
@@ -281,9 +311,6 @@ class ThemeTypeEditor : public MarginContainer {
OptionButton *theme_type_list;
Button *add_type_button;
- ConfirmationDialog *add_type_dialog;
- LineEdit *add_type_filter;
- ItemList *add_type_options;
CheckButton *show_default_items_button;
@@ -295,13 +322,23 @@ class ThemeTypeEditor : public MarginContainer {
VBoxContainer *icon_items_list;
VBoxContainer *stylebox_items_list;
+ LineEdit *type_variation_edit;
+ Button *type_variation_button;
+
+ enum TypeDialogMode {
+ ADD_THEME_TYPE,
+ ADD_VARIATION_BASE,
+ };
+
+ TypeDialogMode add_type_mode = ADD_THEME_TYPE;
+ ThemeTypeDialog *add_type_dialog;
+
Vector<Control *> focusables;
Timer *update_debounce_timer;
VBoxContainer *_create_item_list(Theme::DataType p_data_type);
void _update_type_list();
void _update_type_list_debounced();
- void _update_add_type_options(const String &p_filter = "");
OrderedHashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default);
HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
void _add_focusable(Control *p_control);
@@ -310,11 +347,6 @@ class ThemeTypeEditor : public MarginContainer {
void _list_type_selected(int p_index);
void _select_type(String p_type_name);
void _add_type_button_cbk();
- void _add_type_filter_cbk(const String &p_value);
- void _add_type_options_cbk(int p_index);
- void _add_type_dialog_confirmed();
- void _add_type_dialog_entered(const String &p_value);
- void _add_type_dialog_activated(int p_index);
void _add_default_type_items();
void _item_add_cbk(int p_data_type, Control *p_control);
@@ -337,6 +369,11 @@ class ThemeTypeEditor : public MarginContainer {
void _unpin_leading_stylebox();
void _update_stylebox_from_leading();
+ void _type_variation_changed(const String p_value);
+ void _add_type_variation_cbk();
+
+ void _add_type_dialog_selected(const String p_type_name);
+
protected:
void _notification(int p_what);
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index 0b02150444..5ea46771ba 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -123,7 +123,7 @@ void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_even
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (hovered_control) {
- StringName theme_type = hovered_control->get_theme_custom_type();
+ StringName theme_type = hovered_control->get_theme_type_variation();
if (theme_type == StringName()) {
theme_type = hovered_control->get_class_name();
}
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index ad88e1b45b..b639a74132 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -1013,8 +1013,11 @@ ProjectExportDialog::ProjectExportDialog() {
preset_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hbox->add_child(preset_vb);
+ Label *l = memnew(Label(TTR("Presets")));
+ l->set_theme_type_variation("HeaderSmall");
+
HBoxContainer *preset_hb = memnew(HBoxContainer);
- preset_hb->add_child(memnew(Label(TTR("Presets"))));
+ preset_hb->add_child(l);
preset_hb->add_spacer();
preset_vb->add_child(preset_hb);
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 7414c2d8e6..ab710a1c21 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -975,7 +975,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
for (int i = 0; i < conversions.size(); i++) {
String what = conversions[i]->converts_to();
- menu->add_item(vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ menu->add_item(vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
}
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index a9dcbc9f09..166b82d744 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1210,7 +1210,9 @@ void SceneTreeDock::_notification(int p_what) {
HBoxContainer *top_row = memnew(HBoxContainer);
top_row->set_name("NodeShortcutsTopRow");
top_row->set_h_size_flags(SIZE_EXPAND_FILL);
- top_row->add_child(memnew(Label(TTR("Create Root Node:"))));
+ Label *l = memnew(Label(TTR("Create Root Node:")));
+ l->set_theme_type_variation("HeaderSmall");
+ top_row->add_child(l);
top_row->add_spacer();
Button *node_shortcuts_toggle = memnew(Button);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index ee66f28045..b2c66ee1e7 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1172,6 +1172,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
if (p_label) {
Label *label = memnew(Label);
+ label->set_theme_type_variation("HeaderSmall");
label->set_position(Point2(10, 0));
label->set_text(TTR("Scene Tree (Nodes):"));