summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_types.h2
-rw-r--r--editor/debugger/editor_debugger_node.h2
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/editor_file_system.cpp9
-rw-r--r--editor/editor_folding.cpp5
-rw-r--r--editor/editor_node.cpp62
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/editor_properties.cpp8
-rw-r--r--editor/editor_property_name_processor.cpp1
-rw-r--r--editor/editor_run.cpp12
-rw-r--r--editor/editor_run.h2
-rw-r--r--editor/editor_themes.cpp18
-rw-r--r--editor/icons/BaseButton.svg1
-rw-r--r--editor/icons/GeometryInstance3D.svg1
-rw-r--r--editor/icons/ImporterMeshInstance3D.svg1
-rw-r--r--editor/icons/MainMovieWrite.svg1
-rw-r--r--editor/icons/MainMovieWriteEnabled.svg1
-rw-r--r--editor/icons/MultiplayerSpawner.svg1
-rw-r--r--editor/icons/MultiplayerSynchronizer.svg1
-rw-r--r--editor/icons/NavigationAgent2D.svg2
-rw-r--r--editor/icons/NavigationAgent3D.svg2
-rw-r--r--editor/icons/NavigationObstacle2D.svg2
-rw-r--r--editor/icons/NavigationObstacle3D.svg2
-rw-r--r--editor/icons/Range.svg1
-rw-r--r--editor/icons/SkeletonIK3D.svg2
-rw-r--r--editor/icons/VideoStreamPlayer.svg (renamed from editor/icons/VideoPlayer.svg)0
-rw-r--r--editor/icons/VisualInstance3D.svg1
-rw-r--r--editor/import/resource_importer_scene.cpp4
-rw-r--r--editor/import/resource_importer_texture.cpp53
-rw-r--r--editor/import/resource_importer_texture.h5
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp6
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp210
-rw-r--r--editor/plugins/shader_editor_plugin.h42
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp6
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp3
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp17
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp42
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h17
-rw-r--r--editor/project_settings_editor.cpp4
-rw-r--r--editor/quick_open.cpp2
-rw-r--r--editor/scene_tree_dock.cpp8
-rw-r--r--editor/scene_tree_editor.cpp3
47 files changed, 401 insertions, 183 deletions
diff --git a/editor/debugger/debug_adapter/debug_adapter_types.h b/editor/debugger/debug_adapter/debug_adapter_types.h
index 4d77b6d51c..fd66905f9b 100644
--- a/editor/debugger/debug_adapter/debug_adapter_types.h
+++ b/editor/debugger/debug_adapter/debug_adapter_types.h
@@ -220,7 +220,7 @@ struct StackFrame {
int column;
static uint32_t hash(const StackFrame &p_frame) {
- return hash_djb2_one_32(p_frame.id);
+ return hash_murmur3_one_32(p_frame.id);
}
bool operator==(const StackFrame &p_other) const {
return id == p_other.id;
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 8dc53690eb..d50cbec291 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -72,7 +72,7 @@ private:
static uint32_t hash(const Breakpoint &p_val) {
uint32_t h = HashMapHasherDefault::hash(p_val.source);
- return hash_djb2_one_32(p_val.line, h);
+ return hash_murmur3_one_32(p_val.line, h);
}
bool operator==(const Breakpoint &p_b) const {
return (line == p_b.line && source == p_b.source);
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 97699d0349..9a1b2b5ff5 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -487,7 +487,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<
void DependencyRemoveDialog::ok_pressed() {
for (int i = 0; i < files_to_delete.size(); ++i) {
if (ResourceCache::has(files_to_delete[i])) {
- Resource *res = ResourceCache::get(files_to_delete[i]);
+ Ref<Resource> res = ResourceCache::get_ref(files_to_delete[i]);
res->set_path("");
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index f9a4c14c48..adbba98897 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1792,9 +1792,9 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
//if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
//to reload properly
- if (ResourceCache::has(file)) {
- Resource *r = ResourceCache::get(file);
+ Ref<Resource> r = ResourceCache::get_ref(file);
+ if (r.is_valid()) {
if (!r->get_import_path().is_empty()) {
String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(file);
r->set_import_path(dst_path);
@@ -2034,9 +2034,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const HashMap<String
//if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
//to reload properly
- if (ResourceCache::has(p_file)) {
- Resource *r = ResourceCache::get(p_file);
-
+ Ref<Resource> r = ResourceCache::get_ref(p_file);
+ if (r.is_valid()) {
if (!r->get_import_path().is_empty()) {
String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_file);
r->set_import_path(dst_path);
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 9e1b361f64..8c508494c0 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -193,10 +193,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) {
for (int i = 0; i < res_unfolds.size(); i += 2) {
String path2 = res_unfolds[i];
- Ref<Resource> res;
- if (ResourceCache::has(path2)) {
- res = Ref<Resource>(ResourceCache::get(path2));
- }
+ Ref<Resource> res = ResourceCache::get_ref(path2);
if (res.is_null()) {
continue;
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 67d0b83bd6..9b0ac305d1 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -582,9 +582,10 @@ void EditorNode::_notification(int p_what) {
opening_prev = false;
}
+ bool unsaved_cache_changed = false;
if (unsaved_cache != (saved_version != editor_data.get_undo_redo().get_version())) {
unsaved_cache = (saved_version != editor_data.get_undo_redo().get_version());
- _update_title();
+ unsaved_cache_changed = true;
}
if (last_checked_version != editor_data.get_undo_redo().get_version()) {
@@ -615,6 +616,10 @@ void EditorNode::_notification(int p_what) {
ResourceImporterTexture::get_singleton()->update_imports();
+ if (settings_changed || unsaved_cache_changed) {
+ _update_title();
+ }
+
if (settings_changed) {
_update_from_settings();
settings_changed = false;
@@ -876,7 +881,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
int rc = p_resources.size();
for (int i = 0; i < rc; i++) {
- Ref<Resource> res(ResourceCache::get(p_resources.get(i)));
+ Ref<Resource> res = ResourceCache::get_ref(p_resources.get(i));
if (res.is_null()) {
continue;
}
@@ -1006,8 +1011,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
continue;
}
// Reload normally.
- Resource *resource = ResourceCache::get(p_resources[i]);
- if (resource) {
+ Ref<Resource> resource = ResourceCache::get_ref(p_resources[i]);
+ if (resource.is_valid()) {
resource->reload_from_file();
}
}
@@ -1720,7 +1725,7 @@ void EditorNode::_save_scene(String p_file, int idx) {
// We must update it, but also let the previous scene state go, as
// old version still work for referencing changes in instantiated or inherited scenes.
- sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(p_file)));
+ sdata = ResourceCache::get_ref(p_file);
if (sdata.is_valid()) {
sdata->recreate_state();
} else {
@@ -2342,6 +2347,20 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
return;
}
+ String write_movie_file;
+ if (write_movie_button->is_pressed()) {
+ if (p_current && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->has_meta("movie_file")) {
+ // If the scene file has a movie_file metadata set, use this as file. Quick workaround if you want to have multiple scenes that write to multiple movies.
+ write_movie_file = get_tree()->get_edited_scene_root()->get_meta("movie_file");
+ } else {
+ write_movie_file = GLOBAL_GET("editor/movie_writer/movie_file");
+ }
+ if (write_movie_file == String()) {
+ show_accept(TTR("Movie Maker mode is enabled, but no movie file path has been specified.\nA default movie file path can be specified in the project settings under the 'Editor/Movie Writer' category.\nAlternatively, for running single scenes, a 'movie_path' metadata can be added to the root node,\nspecifying the path to a movie file that will be used when recording that scene."), TTR("OK"));
+ return;
+ }
+ }
+
play_button->set_pressed(false);
play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_scene_button->set_pressed(false);
@@ -2405,7 +2424,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
EditorDebuggerNode::get_singleton()->start();
- Error error = editor_run.run(run_filename);
+ Error error = editor_run.run(run_filename, write_movie_file);
if (error != OK) {
EditorDebuggerNode::get_singleton()->stop();
show_accept(TTR("Could not start subprocess(es)!"), TTR("OK"));
@@ -2788,6 +2807,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RUN_SETTINGS: {
project_settings_editor->popup_project_settings();
} break;
+ case RUN_WRITE_MOVIE: {
+ _update_write_movie_icon();
+ } break;
case FILE_INSTALL_ANDROID_SOURCE: {
if (p_confirmed) {
export_template_manager->install_android_template();
@@ -3695,7 +3717,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
if (ResourceCache::has(lpath)) {
// Used from somewhere else? No problem! Update state and replace sdata.
- Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath)));
+ Ref<PackedScene> ps = ResourceCache::get_ref(lpath);
if (ps.is_valid()) {
ps->replace_state(sdata->get_state());
ps->set_last_modified_time(sdata->get_last_modified_time());
@@ -4949,6 +4971,14 @@ String EditorNode::get_run_playing_scene() const {
return run_filename;
}
+void EditorNode::_update_write_movie_icon() {
+ if (write_movie_button->is_pressed()) {
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWriteEnabled"), SNAME("EditorIcons")));
+ } else {
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
+ }
+}
+
void EditorNode::_immediate_dialog_confirmed() {
immediate_dialog_confirmed = true;
}
@@ -6704,6 +6734,23 @@ EditorNode::EditorNode() {
ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R);
play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_custom_scene"));
+ write_movie_button = memnew(Button);
+ write_movie_button->set_flat(true);
+ write_movie_button->set_toggle_mode(true);
+ play_hb->add_child(write_movie_button);
+ write_movie_button->set_pressed(false);
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
+ write_movie_button->set_focus_mode(Control::FOCUS_NONE);
+ write_movie_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_WRITE_MOVIE));
+ write_movie_button->set_tooltip(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file."));
+ // Restore these values to something more useful so it ignores the theme
+ write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.4));
+ write_movie_button->add_theme_color_override("icon_pressed_color", Color(1, 1, 1, 1));
+ write_movie_button->add_theme_color_override("icon_hover_color", Color(1.2, 1.2, 1.2, 0.4));
+ write_movie_button->add_theme_color_override("icon_hover_pressed_color", Color(1.2, 1.2, 1.2, 1));
+ write_movie_button->add_theme_color_override("icon_focus_color", Color(1, 1, 1, 1));
+ write_movie_button->add_theme_color_override("icon_disabled_color", Color(1, 1, 1, 0.4));
+
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
menu_hb->add_child(right_menu_hb);
@@ -7054,7 +7101,6 @@ EditorNode::EditorNode() {
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
add_editor_plugin(memnew(ShaderEditorPlugin));
add_editor_plugin(memnew(ShaderFileEditorPlugin));
- add_editor_plugin(memnew(VisualShaderEditorPlugin));
add_editor_plugin(memnew(Camera3DEditorPlugin));
add_editor_plugin(memnew(ThemeEditorPlugin));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 48df767562..89f80baeb9 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -173,6 +173,7 @@ private:
RUN_PLAY_CUSTOM_SCENE,
RUN_SETTINGS,
RUN_USER_DATA_FOLDER,
+ RUN_WRITE_MOVIE,
RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_VCS_METADATA,
@@ -333,6 +334,7 @@ private:
Button *play_scene_button = nullptr;
Button *play_custom_scene_button = nullptr;
Button *search_button = nullptr;
+ Button *write_movie_button = nullptr;
TextureProgressBar *audio_vu = nullptr;
Timer *screenshot_timer = nullptr;
@@ -667,7 +669,7 @@ private:
void _pick_main_scene_custom_action(const String &p_custom_action_name);
void _immediate_dialog_confirmed();
-
+ void _update_write_movie_icon();
void _select_default_main_screen_plugin();
void _bottom_panel_switch(bool p_enable, int p_idx);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index a5c02c70d9..2562c740aa 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3601,7 +3601,7 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri
hint.greater = true;
} else if (slice == "or_lesser") {
hint.lesser = true;
- } else if (slice == "noslider") {
+ } else if (slice == "no_slider") {
hint.hide_slider = true;
} else if (slice == "exp") {
hint.exp_range = true;
@@ -3747,11 +3747,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
EditorPropertyLocale *editor = memnew(EditorPropertyLocale);
editor->setup(p_hint_text);
return editor;
- } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
+ } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
Vector<String> extensions = p_hint_text.split(",");
- bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE;
+ bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE;
bool folder = p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_GLOBAL_DIR;
- bool save = p_hint == PROPERTY_HINT_SAVE_FILE;
+ bool save = p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE;
EditorPropertyPath *editor = memnew(EditorPropertyPath);
editor->setup(extensions, folder, global);
if (save) {
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 397afc0653..09d2992e07 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -176,6 +176,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["lowpass"] = "Low-pass";
capitalize_string_remaps["macos"] = "macOS";
capitalize_string_remaps["mb"] = "(MB)"; // Unit.
+ capitalize_string_remaps["mjpeg"] = "MJPEG";
capitalize_string_remaps["mms"] = "MMS";
capitalize_string_remaps["ms"] = "(ms)"; // Unit
capitalize_string_remaps["msaa"] = "MSAA";
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 6a2ff50ee0..04a3bf2915 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -43,7 +43,7 @@ String EditorRun::get_running_scene() const {
return running_scene;
}
-Error EditorRun::run(const String &p_scene) {
+Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
List<String> args;
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
@@ -68,6 +68,16 @@ Error EditorRun::run(const String &p_scene) {
args.push_back("--debug-navigation");
}
+ if (p_write_movie != "") {
+ args.push_back("--write-movie");
+ args.push_back(p_write_movie);
+ args.push_back("--fixed-fps");
+ args.push_back(itos(GLOBAL_GET("editor/movie_writer/fps")));
+ if (bool(GLOBAL_GET("editor/movie_writer/disable_vsync"))) {
+ args.push_back("--disable-vsync");
+ }
+ }
+
int screen = EditorSettings::get_singleton()->get("run/window_placement/screen");
if (screen == 0) {
// Same as editor
diff --git a/editor/editor_run.h b/editor/editor_run.h
index 50604ff032..4cbc6838e4 100644
--- a/editor/editor_run.h
+++ b/editor/editor_run.h
@@ -50,7 +50,7 @@ private:
public:
Status get_status() const;
String get_running_scene() const;
- Error run(const String &p_scene);
+ Error run(const String &p_scene, const String &p_write_movie = "");
void run_native_notify() { status = STATUS_PLAY; }
void stop();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 7a80cf36a8..10412eac41 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -464,6 +464,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45);
icon_hover_color.a = 1.0;
Color icon_focus_color = icon_hover_color;
+ Color icon_disabled_color = Color(icon_normal_color, 0.4);
// Make the pressed icon color overbright because icons are not completely white on a dark theme.
// On a light theme, icons are dark, so we need to modulate them with an even brighter color.
Color icon_pressed_color = accent_color * (dark_theme ? 1.15 : 3.5);
@@ -738,10 +739,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "Button", font_focus_color);
theme->set_color("font_pressed_color", "Button", accent_color);
theme->set_color("font_disabled_color", "Button", font_disabled_color);
+
theme->set_color("icon_normal_color", "Button", icon_normal_color);
theme->set_color("icon_hover_color", "Button", icon_hover_color);
theme->set_color("icon_focus_color", "Button", icon_focus_color);
theme->set_color("icon_pressed_color", "Button", icon_pressed_color);
+ theme->set_color("icon_disabled_color", "Button", icon_disabled_color);
const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE;
@@ -768,7 +771,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// When pressed, don't tint the icons with the accent color, just leave them normal.
theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color);
// When unpressed, dim the icons.
- theme->set_color("icon_normal_color", "EditorLogFilterButton", font_disabled_color);
+ theme->set_color("icon_normal_color", "EditorLogFilterButton", icon_disabled_color);
// When pressed, add a small bottom border to the buttons to better show their active state,
// similar to active tabs.
Ref<StyleBoxFlat> editor_log_button_pressed = style_widget_pressed->duplicate();
@@ -805,8 +808,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "OptionButton", font_focus_color);
theme->set_color("font_pressed_color", "OptionButton", accent_color);
theme->set_color("font_disabled_color", "OptionButton", font_disabled_color);
+
+ theme->set_color("icon_normal_color", "OptionButton", icon_normal_color);
theme->set_color("icon_hover_color", "OptionButton", icon_hover_color);
theme->set_color("icon_focus_color", "OptionButton", icon_focus_color);
+ theme->set_color("icon_pressed_color", "OptionButton", icon_pressed_color);
+ theme->set_color("icon_disabled_color", "OptionButton", icon_disabled_color);
+
theme->set_icon("arrow", "OptionButton", theme->get_icon(SNAME("GuiOptionArrow"), SNAME("EditorIcons")));
theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE);
theme->set_constant("modulate_arrow", "OptionButton", true);
@@ -833,8 +841,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "CheckButton", font_focus_color);
theme->set_color("font_pressed_color", "CheckButton", accent_color);
theme->set_color("font_disabled_color", "CheckButton", font_disabled_color);
+
+ theme->set_color("icon_normal_color", "CheckButton", icon_normal_color);
theme->set_color("icon_hover_color", "CheckButton", icon_hover_color);
theme->set_color("icon_focus_color", "CheckButton", icon_focus_color);
+ theme->set_color("icon_pressed_color", "CheckButton", icon_pressed_color);
+ theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color);
theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE);
theme->set_constant("check_v_adjust", "CheckButton", 0 * EDSCALE);
@@ -864,8 +876,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "CheckBox", font_focus_color);
theme->set_color("font_pressed_color", "CheckBox", accent_color);
theme->set_color("font_disabled_color", "CheckBox", font_disabled_color);
+
+ theme->set_color("icon_normal_color", "CheckBox", icon_normal_color);
theme->set_color("icon_hover_color", "CheckBox", icon_hover_color);
theme->set_color("icon_focus_color", "CheckBox", icon_focus_color);
+ theme->set_color("icon_pressed_color", "CheckBox", icon_pressed_color);
+ theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color);
theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE);
theme->set_constant("check_v_adjust", "CheckBox", 0 * EDSCALE);
diff --git a/editor/icons/BaseButton.svg b/editor/icons/BaseButton.svg
new file mode 100644
index 0000000000..9aa0ae1c07
--- /dev/null
+++ b/editor/icons/BaseButton.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.5 9c-.831 0-1.5.669-1.5 1.5v1.5h-2v2h12v-2h-2v-1.5c0-.831-.669-1.5-1.5-1.5z" fill="#8eef97"/></svg>
diff --git a/editor/icons/GeometryInstance3D.svg b/editor/icons/GeometryInstance3D.svg
new file mode 100644
index 0000000000..759d5fe413
--- /dev/null
+++ b/editor/icons/GeometryInstance3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7304688v6.5410152a2 2 0 0 0 -1 1.728516 2 2 0 0 0 2 2 2 2 0 0 0 1.7304688-1h6.5410152a2 2 0 0 0 1.728516 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.03125-1.75h.03125v-6.5214844a2 2 0 0 0 1-1.7285156 2 2 0 0 0 -2-2 2 2 0 0 0 -1.730469 1h-6.5410154a2 2 0 0 0 -1.7285156-1zm1 3h1.4140625 3.5859375 2.271484a2 2 0 0 0 .728516.7304688v1.2695312 4.585938 1.414062h-1.414062-4.585938-1.2714844a2 2 0 0 0 -.7285156-.730469v-3.269531-2.5859375z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/ImporterMeshInstance3D.svg b/editor/icons/ImporterMeshInstance3D.svg
new file mode 100644
index 0000000000..7e7598ac2b
--- /dev/null
+++ b/editor/icons/ImporterMeshInstance3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7304688v6.5410152a2 2 0 0 0 -1 1.728516 2 2 0 0 0 2 2 2 2 0 0 0 1.7304688-1h6.5410152a2 2 0 0 0 1.728516 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.03125-1.75h.03125v-6.5214844a2 2 0 0 0 1-1.7285156 2 2 0 0 0 -2-2 2 2 0 0 0 -1.730469 1h-6.5410154a2 2 0 0 0 -1.7285156-1zm1 3h1.4140625 3.5859375 2.271484a2 2 0 0 0 .728516.7304688v1.2695312 4.585938 1.414062h-1.414062-4.585938-1.2714844a2 2 0 0 0 -.7285156-.730469v-3.269531-2.5859375z"/><path d="m7 7h2v4h-2z"/><path d="m7 5h2v1h-2z"/></g></svg>
diff --git a/editor/icons/MainMovieWrite.svg b/editor/icons/MainMovieWrite.svg
new file mode 100644
index 0000000000..21464bb57c
--- /dev/null
+++ b/editor/icons/MainMovieWrite.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 4-1.535V14h.002a2 2 0 0 0 .266 1A2 2 0 0 0 14 16h1v-2h-.5a.5.5 0 0 1-.5-.5V8a6 6 0 0 0-6-6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm3.441 2a1 1 0 0 1 .89.5 1 1 0 0 1-.366 1.365 1 1 0 0 1-1.367-.365 1 1 0 0 1 .367-1.365A1 1 0 0 1 11.44 5zm-6.953.002a1 1 0 0 1 .547.133A1 1 0 0 1 5.402 6.5a1 1 0 0 1-1.367.365A1 1 0 0 1 3.67 5.5a1 1 0 0 1 .818-.498zM4.512 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365A1 1 0 0 1 3.67 10.5a1 1 0 0 1 .365-1.365A1 1 0 0 1 4.512 9zm6.904.002a1 1 0 0 1 .549.133 1 1 0 0 1 .365 1.365 1 1 0 0 1-1.365.365 1 1 0 0 1-.367-1.365 1 1 0 0 1 .818-.498zM8 11a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MainMovieWriteEnabled.svg b/editor/icons/MainMovieWriteEnabled.svg
new file mode 100644
index 0000000000..b12ea38bed
--- /dev/null
+++ b/editor/icons/MainMovieWriteEnabled.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 4-1.535V14h.002a2 2 0 0 0 .266 1A2 2 0 0 0 14 16h1v-2h-.5a.5.5 0 0 1-.5-.5V8a6 6 0 0 0-6-6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm3.441 2a1 1 0 0 1 .89.5 1 1 0 0 1-.366 1.365 1 1 0 0 1-1.367-.365 1 1 0 0 1 .367-1.365A1 1 0 0 1 11.44 5zm-6.953.002a1 1 0 0 1 .547.133A1 1 0 0 1 5.402 6.5a1 1 0 0 1-1.367.365A1 1 0 0 1 3.67 5.5a1 1 0 0 1 .818-.498zM4.512 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365A1 1 0 0 1 3.67 10.5a1 1 0 0 1 .365-1.365A1 1 0 0 1 4.512 9zm6.904.002a1 1 0 0 1 .549.133 1 1 0 0 1 .365 1.365 1 1 0 0 1-1.365.365 1 1 0 0 1-.367-1.365 1 1 0 0 1 .818-.498zM8 11a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#e0e0e0" style="fill:#ee5353;fill-opacity:1"/></svg>
diff --git a/editor/icons/MultiplayerSpawner.svg b/editor/icons/MultiplayerSpawner.svg
new file mode 100644
index 0000000000..68ffd3aab4
--- /dev/null
+++ b/editor/icons/MultiplayerSpawner.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:none;fill-opacity:.996078;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;stroke-opacity:1;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/><path d="M7 9v2H5v2h2v2h2v-2h2v-2H9V9Z" fill="#5fff97"/></svg>
diff --git a/editor/icons/MultiplayerSynchronizer.svg b/editor/icons/MultiplayerSynchronizer.svg
new file mode 100644
index 0000000000..1547ec5a2b
--- /dev/null
+++ b/editor/icons/MultiplayerSynchronizer.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:#5fff97;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" d="M5 10h3l-2 4-2-4Z"/><path style="fill:#ff5f5f;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" d="M9 14h3l-2-4-2 4Z"/><path style="fill:none;fill-opacity:.996078;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;stroke-opacity:1;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/></svg>
diff --git a/editor/icons/NavigationAgent2D.svg b/editor/icons/NavigationAgent2D.svg
index 3f1d571a7e..05aeb95e12 100644
--- a/editor/icons/NavigationAgent2D.svg
+++ b/editor/icons/NavigationAgent2D.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3 0-5 2-5 5s3 6 5 9c2-3 5.007-6.03 5-9 0-3-2-5-5-5zm0 2.5c1.371 0 2.5 1.129 2.5 2.5s-1.129 2.5-2.5 2.5-2.5-1.129-2.5-2.5 1.129-2.5 2.5-2.5z" fill="#e0e0e0" fill-rule="nonzero"/></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2.5c1.371 0 2.5 1.129 2.5 2.5s-1.129 2.5-2.5 2.5v6.5c2-3 5.007-6.03 5-9 0-3-2-5-5-5z" fill="#8da5f3" fill-opacity=".988235"/><path d="m8 1c-3 0-5 2-5 5s3 6 5 9v-6.5c-1.371 0-2.5-1.129-2.5-2.5s1.129-2.5 2.5-2.5z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/NavigationAgent3D.svg b/editor/icons/NavigationAgent3D.svg
index 947b2129c3..5a2d8b3489 100644
--- a/editor/icons/NavigationAgent3D.svg
+++ b/editor/icons/NavigationAgent3D.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m9 1c-1.371 0-2.308.429-2.939 1.074-.668.663-1.34 1.324-2.01 1.985-.046 1.741.757 4.327 2.365 4.843.178.317.384.649.584.977v5.121l2-2c2-3 4-6 4-8s-1-4-4-4z" fill="#fff" fill-opacity=".39"/><path d="m7 3c-3 0-4 2-4 4s2 5 4 8c2-3 4-6 4-8s-1-4-4-4zm0 2c1.097 0 2 .903 2 2s-.903 2-2 2-2-.903-2-2 .903-2 2-2z" fill="#e0e0e0"/></g></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m8 1.0859375c-.8454344.1560829-1.4755929.5141293-1.9394531.9882813-.668.663-1.3397656 1.323375-2.0097657 1.984375-.046 1.7409999.7572344 4.32775 2.3652344 4.84375.178.317.3839844.6485624.5839844.9765624v5.1210938l1-1z" fill="#e0e0e0" fill-opacity=".501961"/><path d="m7 3c-3 0-4 2-4 4s2 5 4 8c.3378629-.506794.671779-1.011698 1-1.513672v-4.7597655c-.2952789.1727801-.6361816.2734375-1 .2734375-1.097 0-2-.903-2-2s.903-2 2-2c.3638184 0 .7047211.1006574 1 .2734375v-2.1894531c-.3055959-.054762-.6378835-.0839844-1-.0839844z" fill="#e0e0e0"/><g fill="#fc7f7f"><path d="m9 1c-.3631515 0-.6953702.0296972-1 .0859375v12.9140625l1-1c2-3 4-6 4-8s-1-4-4-4z" fill-opacity=".501961"/><path d="m8 3.0839844v2.1894531c.5950581.3481936 1 .9933809 1 1.7265625s-.4049419 1.3783689-1 1.7265625v4.7597655c1.6147033-2.469489 3-4.8241909 3-6.486328 0-1.758589-.773848-3.5170952-3-3.9160156z"/></g></g></svg>
diff --git a/editor/icons/NavigationObstacle2D.svg b/editor/icons/NavigationObstacle2D.svg
index 8fcb5617dd..a5073898f4 100644
--- a/editor/icons/NavigationObstacle2D.svg
+++ b/editor/icons/NavigationObstacle2D.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .875c-.625 0-1.25.375-1.5 1.125l-3 10h9l-3-10c-.25-.75-.875-1.125-1.5-1.125zm-1.5 4.125h3l1 4h-5zm-4.5 8c-1 0-1 2 0 2h12c1 0 1-2 0-2z" fill="#e0e0e0" fill-rule="nonzero"/></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .875c-.625 0-1.25.375-1.5 1.125l-3 10h4.5v-3h-2.5l1-4h1.5zm-6 12.125c-1 0-1 2 0 2h6v-2z" fill="#e0e0e0"/><path d="m8 .875v4.125h1.5l1 4h-2.5v3h4.5l-3-10c-.25-.75-.875-1.125-1.5-1.125zm0 12.125v2h6c1 0 1-2 0-2z" fill="#8da5f3" fill-opacity=".988235"/></svg>
diff --git a/editor/icons/NavigationObstacle3D.svg b/editor/icons/NavigationObstacle3D.svg
index c5e58eebf7..d8ccd3a646 100644
--- a/editor/icons/NavigationObstacle3D.svg
+++ b/editor/icons/NavigationObstacle3D.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m4.607 8.379c-1.798.928-3.607 2.072-3.607 2.621 0 1 6 4 7 4s7-3 7-4c0-.549-1.809-1.693-3.607-2.621l.607 1.621c2 4-10 4-8 0z" fill="#fff" fill-opacity=".39"/><path d="m8 .875c-.375 0-.75.375-1 1.125l-3 8c-2 4 10 4 8 0l-3-8c-.25-.75-.625-1.125-1-1.125zm-1.5 4.125c1 .5 2 .5 3 0l1 3.5c-1.5 1-3.5 1-5 0z" fill="#e0e0e0"/></g></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m4.6074219 8.3789062c-1.798.9280001-3.6074219 2.0720938-3.6074219 2.6210938 0 1 6 4 7 4v-2c-2.5 0-5-1-4-3z" fill="#e0e0e0" fill-opacity=".501961"/><path d="m8 .875c-.375 0-.75.375-1 1.125l-3 8c-1 2 1.5 3 4 3v-3.75c-.875 0-1.75-.25-2.5-.75l1-3.5c.5.25 1 .375 1.5.375z" fill="#e0e0e0"/><g fill="#fc7f7f"><path d="m11.392578 8.3789062.607422 1.6210938c1.002342 2.004685-1.511742 3.004696-4.0175781 3v1.998047c.0053893.000157.0124503.001953.0175781.001953 1 0 7-3 7-4 0-.549-1.809422-1.6930938-3.607422-2.6210938z" fill-opacity=".501961"/><path d="m8 .875c-.00585 0-.011729.001771-.017578.001953v4.498047c.5058535.0029611 1.0117243-.1220732 1.517578-.375l1 3.5c-.7550159.5033439-1.6367318.7533663-2.5175781.75v3.75c2.5058361.004696 5.0199201-.995315 4.0175781-3l-3-8c-.25-.75-.625-1.125-1-1.125z"/></g></g></svg>
diff --git a/editor/icons/Range.svg b/editor/icons/Range.svg
new file mode 100644
index 0000000000..49311546b0
--- /dev/null
+++ b/editor/icons/Range.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.8027344 2.7714844c-1.0905892.2029663-1.089037 1.7659969.00195 1.9667968l2.8808595.5761719.576172 2.8808594c.231158 1.3504655 2.264924.9453327 1.960937-.390625l-.7070279-3.5371094c-.039663-.1968491-.137665-.3771998-.28125-.5175781-.138135-.1351849-.312483-.2274468-.501953-.265625l-3.5371095-.7070312c-.1291868-.0278728-.262617-.0298643-.3925781-.0058594zm-3.9941406 4.2167968c-.6571498-.0349349-1.1683412.5633914-1.03125 1.2070313l.7070312 3.5371095c.079467.394998.3882047.703736.7832031.783203l3.5371094.707031c1.3359577.303987 1.7410905-1.729779.390625-1.960937l-2.8808594-.576172-.5761719-2.8808595c-.0369237-.1982539-.1329195-.3807141-.2753906-.5234375-.1744016-.1751556-.407488-.2795227-.6542968-.2929688z" fill="#8eef97"/></svg>
diff --git a/editor/icons/SkeletonIK3D.svg b/editor/icons/SkeletonIK3D.svg
index 45697a1b42..7210019749 100644
--- a/editor/icons/SkeletonIK3D.svg
+++ b/editor/icons/SkeletonIK3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.453125v3.546875a2 2 0 0 0 1 1.732422 2 2 0 0 0 1 .265625v.001953h2v-2h-1v-1h-1v1h-1v-3.1308594-.8691406h1v1h1v-1h1v-1h-1v-1h1v-5zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#e0e0e0"/><path d="m8 2v5h1v1h-1v1h1v1h1v-1h1v.8671875 3.1328125h-1v-1h-1v1h-1v2h2v-.001953a2 2 0 0 0 1-.265625 2 2 0 0 0 1-1.732422v-3.546875a4 4 0 0 0 2-3.453125 4 4 0 0 0 -4-4zm3 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/VideoPlayer.svg b/editor/icons/VideoStreamPlayer.svg
index 092a26b955..092a26b955 100644
--- a/editor/icons/VideoPlayer.svg
+++ b/editor/icons/VideoStreamPlayer.svg
diff --git a/editor/icons/VisualInstance3D.svg b/editor/icons/VisualInstance3D.svg
new file mode 100644
index 0000000000..e5e43b59dd
--- /dev/null
+++ b/editor/icons/VisualInstance3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><circle cx="3" cy="3" r="2"/><circle cx="13" cy="3" r="2"/><circle cx="13" cy="13" r="2"/><circle cx="3" cy="13" r="2"/></g></svg>
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index f2975b1d7a..171ef5bf4c 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1115,7 +1115,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani
}
if (ResourceCache::has(p_save_to_path)) {
- Ref<Animation> old_anim = Ref<Resource>(ResourceCache::get(p_save_to_path));
+ Ref<Animation> old_anim = ResourceCache::get_ref(p_save_to_path);
if (old_anim.is_valid()) {
old_anim->copy_from(anim);
anim = old_anim;
@@ -1711,7 +1711,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m
}
if (!save_to_file.is_empty()) {
- Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file));
+ Ref<Mesh> existing = ResourceCache::get_ref(save_to_file);
if (existing.is_valid()) {
//if somehow an existing one is useful, create
existing->reset_state();
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index a055dca8ad..deb3047864 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -65,15 +65,6 @@ void ResourceImporterTexture::_texture_reimport_3d(const Ref<CompressedTexture2D
}
singleton->make_flags[path].flags |= MAKE_3D_FLAG;
-
- // For small textures, don't use VRAM compression as it decreases quality too much compared to the memory saved.
- // The minimum size for VRAM compression is defined on each axis.
- // It is then squared to handle non-square input texture sizes in a more human-readable manner.
- const float minimum_size = float(GLOBAL_GET("rendering/textures/vram_compression/minimum_size"));
- if (p_tex->get_width() * p_tex->get_height() >= int(Math::pow(minimum_size, 2.0f) - CMP_EPSILON)) {
- // Texture is larger than `minimum_size × minimum_size` pixels (if square).
- singleton->make_flags[path].flags |= MAKE_VRAM_COMPRESS_FLAG;
- }
}
void ResourceImporterTexture::_texture_reimport_normal(const Ref<CompressedTexture2D> &p_tex) {
@@ -112,33 +103,7 @@ void ResourceImporterTexture::update_imports() {
bool changed = false;
- if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) {
- if (E.value.flags & MAKE_VRAM_COMPRESS_FLAG) {
- // Texture is large enough to benefit from VRAM compression.
- const int compress_to = cf->get_value("params", "detect_3d/compress_to");
- String compress_string;
- if (compress_to == 1) {
- cf->set_value("params", "compress/mode", COMPRESS_VRAM_COMPRESSED);
- compress_string = "VRAM Compressed (S3TC/ETC/BPTC)";
- } else if (compress_to == 2) {
- cf->set_value("params", "compress/mode", COMPRESS_BASIS_UNIVERSAL);
- compress_string = "Basis Universal";
- }
- print_line(vformat(TTR("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s."), String(E.key), compress_string));
- } else {
- print_line(vformat(TTR("%s: Small texture detected as used in 3D. Enabling mipmap generation but not VRAM compression."), String(E.key)));
- }
-
- cf->set_value("params", "mipmaps/generate", true);
- cf->set_value("params", "detect_3d/compress_to", 0);
-
- changed = true;
- }
-
- if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0 && int(cf->get_value("params", "compress/mode")) != COMPRESS_LOSSLESS) {
- // Normal map compression is not available for textures with Lossless compression.
- // This is ignored in the importer, but printing a message about normal map compression
- // being enabled in this case is misleading.
+ if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) {
print_line(vformat(TTR("%s: Texture detected as used as a normal map in 3D. Enabling red-green texture compression to reduce memory usage (blue channel is discarded)."), String(E.key)));
cf->set_value("params", "compress/normal_map", 1);
changed = true;
@@ -151,6 +116,22 @@ void ResourceImporterTexture::update_imports() {
changed = true;
}
+ if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) {
+ const int compress_to = cf->get_value("params", "detect_3d/compress_to");
+ String compress_string;
+ cf->set_value("params", "detect_3d/compress_to", 0);
+ if (compress_to == 1) {
+ cf->set_value("params", "compress/mode", COMPRESS_VRAM_COMPRESSED);
+ compress_string = "VRAM Compressed (S3TC/ETC/BPTC)";
+ } else if (compress_to == 2) {
+ cf->set_value("params", "compress/mode", COMPRESS_BASIS_UNIVERSAL);
+ compress_string = "Basis Universal";
+ }
+ print_line(vformat(TTR("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s."), String(E.key), compress_string));
+ cf->set_value("params", "mipmaps/generate", true);
+ changed = true;
+ }
+
if (changed) {
cf->save(src_path);
to_reimport.push_back(E.key);
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index e65c15ae78..7def2d4f77 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -54,9 +54,8 @@ public:
protected:
enum {
MAKE_3D_FLAG = 1,
- MAKE_VRAM_COMPRESS_FLAG = 2,
- MAKE_ROUGHNESS_FLAG = 4,
- MAKE_NORMAL_FLAG = 8,
+ MAKE_ROUGHNESS_FLAG = 2,
+ MAKE_NORMAL_FLAG = 4
};
Mutex mutex;
diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp
index aa338a6c0d..e5fe99890e 100644
--- a/editor/import/resource_importer_texture_atlas.cpp
+++ b/editor/import/resource_importer_texture_atlas.cpp
@@ -306,10 +306,8 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
//update cache if existing, else create
Ref<Texture2D> cache;
- if (ResourceCache::has(p_group_file)) {
- Resource *resptr = ResourceCache::get(p_group_file);
- cache.reference_ptr(resptr);
- } else {
+ cache = ResourceCache::get_ref(p_group_file);
+ if (!cache.is_valid()) {
Ref<ImageTexture> res_cache;
res_cache.instantiate();
res_cache->create_from_image(new_atlas);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 98ccc1fdbe..e5ca5d66e8 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1053,7 +1053,7 @@ void AnimationPlayerEditor::_animation_duplicate() {
_update_name_dialog_library_dropdown();
name_dialog_op = TOOL_DUPLICATE_ANIM;
- name_dialog->set_title("Duplicate Animation");
+ name_dialog->set_title(TTR("Duplicate Animation"));
name_title->set_text(TTR("Duplicated Animation Name:"));
name->set_text(new_name);
name_dialog->popup_centered(Size2(300, 90));
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 2ba2466646..00cc5a6ca0 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -817,11 +817,11 @@ bool AnimationNodeStateMachineEditor::_create_submenu(PopupMenu *p_menu, Ref<Ani
Vector<Ref<AnimationNodeStateMachine>> parents = p_parents;
if (from_root) {
- Ref<AnimationNodeStateMachine> prev = p_nodesm->get_prev_state_machine();
+ AnimationNodeStateMachine *prev = p_nodesm->get_prev_state_machine();
- while (prev.is_valid()) {
+ while (prev != nullptr) {
parents.push_back(prev);
- p_nodesm = prev;
+ p_nodesm = Ref<AnimationNodeStateMachine>(prev);
prev_path += "../";
prev = prev->get_prev_state_machine();
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 1ea0299d4e..dea4aaded7 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5455,7 +5455,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
}
child->set_name(name);
- Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(ResourceCache::get(path)));
+ Ref<Texture2D> texture = ResourceCache::get_ref(path);
if (parent) {
editor_data->get_undo_redo().add_do_method(parent, "add_child", child, true);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index d85087b5ea..d1f858315c 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -350,8 +350,8 @@ struct MeshInstance3DEditorEdgeSort {
Vector2 b;
static uint32_t hash(const MeshInstance3DEditorEdgeSort &p_edge) {
- uint32_t h = hash_djb2_one_32(HashMapHasherDefault::hash(p_edge.a));
- return hash_djb2_one_32(HashMapHasherDefault::hash(p_edge.b), h);
+ uint32_t h = hash_murmur3_one_32(HashMapHasherDefault::hash(p_edge.a));
+ return hash_fmix32(hash_murmur3_one_32(HashMapHasherDefault::hash(p_edge.b), h));
}
bool operator==(const MeshInstance3DEditorEdgeSort &p_b) const {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index b9d99fcc93..6ab2366a44 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -3547,7 +3547,7 @@ void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_numb
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader"));
shader_editor->edit(res.ptr());
shader_editor->make_visible(true);
- shader_editor->get_shader_editor()->goto_line_selection(line_number - 1, begin, end);
+ shader_editor->get_shader_editor(res)->goto_line_selection(line_number - 1, begin, end);
return;
} else if (fpath.get_extension() == "tscn") {
EditorNode::get_singleton()->load_scene(fpath);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index c13d0dc197..04b407ce65 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -38,8 +38,12 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/filesystem_dock.h"
+#include "editor/plugins/visual_shader_editor_plugin.h"
#include "editor/project_settings_editor.h"
#include "editor/property_editor.h"
+#include "editor/shader_create_dialog.h"
+#include "scene/gui/split_container.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
@@ -836,50 +840,216 @@ ShaderEditor::ShaderEditor() {
_editor_settings_changed();
}
+void ShaderEditorPlugin::_update_shader_list() {
+ shader_list->clear();
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ String text;
+ String path = edited_shaders[i].shader->get_path();
+ String _class = edited_shaders[i].shader->get_class();
+
+ if (path.is_resource_file()) {
+ text = path.get_file();
+ } else if (edited_shaders[i].shader->get_name() != "") {
+ text = edited_shaders[i].shader->get_name();
+ } else {
+ text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id());
+ }
+
+ if (!shader_list->has_theme_icon(_class, SNAME("EditorIcons"))) {
+ _class = "Resource";
+ }
+ Ref<Texture2D> icon = shader_list->get_theme_icon(_class, SNAME("EditorIcons"));
+
+ shader_list->add_item(text, icon);
+ shader_list->set_item_tooltip(shader_list->get_item_count() - 1, path);
+ }
+
+ if (shader_tabs->get_tab_count()) {
+ shader_list->select(shader_tabs->get_current_tab());
+ }
+
+ for (int i = 1; i < FILE_MAX; i++) {
+ file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.size() == 0);
+ }
+}
+
void ShaderEditorPlugin::edit(Object *p_object) {
Shader *s = Object::cast_to<Shader>(p_object);
- shader_editor->edit(s);
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader.ptr() == s) {
+ // Exists, select.
+ shader_tabs->set_current_tab(i);
+ shader_list->select(i);
+ return;
+ }
+ }
+ // Add.
+ EditedShader es;
+ es.shader = Ref<Shader>(s);
+ Ref<VisualShader> vs = es.shader;
+ if (vs.is_valid()) {
+ es.visual_shader_editor = memnew(VisualShaderEditor);
+ es.visual_shader_editor->edit(vs.ptr());
+ shader_tabs->add_child(es.visual_shader_editor);
+ } else {
+ es.shader_editor = memnew(ShaderEditor);
+ es.shader_editor->edit(s);
+ shader_tabs->add_child(es.shader_editor);
+ }
+ shader_tabs->set_current_tab(shader_tabs->get_tab_count() - 1);
+ edited_shaders.push_back(es);
+ _update_shader_list();
}
bool ShaderEditorPlugin::handles(Object *p_object) const {
- Shader *shader = Object::cast_to<Shader>(p_object);
- return shader != nullptr && shader->is_text_shader();
+ return Object::cast_to<Shader>(p_object) != nullptr;
}
void ShaderEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- button->show();
- EditorNode::get_singleton()->make_bottom_panel_item_visible(shader_editor);
-
- } else {
- button->hide();
- if (shader_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- shader_editor->apply_shaders();
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(main_split);
}
}
void ShaderEditorPlugin::selected_notify() {
- shader_editor->ensure_select_current();
+}
+
+ShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_shader) {
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader == p_for_shader) {
+ return edited_shaders[i].shader_editor;
+ }
+ }
+ return nullptr;
}
void ShaderEditorPlugin::save_external_data() {
- shader_editor->save_external_data();
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader_editor) {
+ edited_shaders[i].shader_editor->save_external_data();
+ }
+ }
}
void ShaderEditorPlugin::apply_changes() {
- shader_editor->apply_shaders();
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader_editor) {
+ edited_shaders[i].shader_editor->apply_shaders();
+ }
+ }
+}
+
+void ShaderEditorPlugin::_shader_selected(int p_index) {
+ shader_tabs->set_current_tab(p_index);
+}
+
+void ShaderEditorPlugin::_close_shader(int p_index) {
+ int index = shader_tabs->get_current_tab();
+ ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
+ Control *c = shader_tabs->get_tab_control(index);
+ memdelete(c);
+ edited_shaders.remove_at(index);
+ _update_shader_list();
+}
+
+void ShaderEditorPlugin::_resource_saved(Object *obj) {
+ // May have been renamed on save.
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader.ptr() == obj) {
+ _update_shader_list();
+ return;
+ }
+ }
+}
+
+void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
+ switch (p_index) {
+ case FILE_NEW: {
+ String base_path = FileSystemDock::get_singleton()->get_current_path();
+ shader_create_dialog->config(base_path.plus_file("new_shader"), false, false, 0);
+ shader_create_dialog->popup_centered();
+ } break;
+ case FILE_OPEN: {
+ InspectorDock::get_singleton()->open_resource("Shader");
+ } break;
+ case FILE_SAVE: {
+ int index = shader_tabs->get_current_tab();
+ ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
+ EditorNode::get_singleton()->save_resource(edited_shaders[index].shader);
+ } break;
+ case FILE_SAVE_AS: {
+ int index = shader_tabs->get_current_tab();
+ ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
+ String path = edited_shaders[index].shader->get_path();
+ if (!path.is_resource_file()) {
+ path = "";
+ }
+ EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader, path);
+ } break;
+ case FILE_INSPECT: {
+ int index = shader_tabs->get_current_tab();
+ ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
+ EditorNode::get_singleton()->push_item(edited_shaders[index].shader.ptr());
+ } break;
+ case FILE_CLOSE: {
+ _close_shader(shader_tabs->get_current_tab());
+ } break;
+ }
+}
+
+void ShaderEditorPlugin::_shader_created(Ref<Shader> p_shader) {
+ EditorNode::get_singleton()->push_item(p_shader.ptr());
}
ShaderEditorPlugin::ShaderEditorPlugin() {
- shader_editor = memnew(ShaderEditor);
+ main_split = memnew(HSplitContainer);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+
+ HBoxContainer *file_hb = memnew(HBoxContainer);
+ vb->add_child(file_hb);
+ file_menu = memnew(MenuButton);
+ file_menu->set_text(TTR("File"));
+ file_menu->get_popup()->add_item(TTR("New Shader"), FILE_NEW);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_item(TTR("Load Shader"), FILE_OPEN);
+ file_menu->get_popup()->add_item(TTR("Save Shader"), FILE_SAVE);
+ file_menu->get_popup()->add_item(TTR("Save Shader As"), FILE_SAVE_AS);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_item(TTR("Open Shader in Inspector"), FILE_INSPECT);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_item(TTR("Close Shader"), FILE_CLOSE);
+ file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed));
+ file_hb->add_child(file_menu);
+
+ for (int i = 1; i < FILE_MAX; i++) {
+ file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), true);
+ }
+
+ shader_list = memnew(ItemList);
+ shader_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ vb->add_child(shader_list);
+ shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected));
+
+ main_split->add_child(vb);
+ vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE);
+
+ shader_tabs = memnew(TabContainer);
+ shader_tabs->set_tabs_visible(false);
+ shader_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ main_split->add_child(shader_tabs);
+ Ref<StyleBoxEmpty> empty;
+ empty.instantiate();
+ shader_tabs->add_theme_style_override("panel", empty);
+
+ button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Shader Editor"), main_split);
- shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
- button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Shader"), shader_editor);
- button->hide();
+ // Defer connect because Editor class is not in the binding system yet.
+ EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), varray(), CONNECT_DEFERRED);
- _2d = false;
+ shader_create_dialog = memnew(ShaderCreateDialog);
+ vb->add_child(shader_create_dialog);
+ shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created));
}
ShaderEditorPlugin::~ShaderEditorPlugin() {
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index bd0c2db824..e1e815f939 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -42,6 +42,11 @@
#include "scene/resources/shader.h"
#include "servers/rendering/shader_warnings.h"
+class ItemList;
+class VisualShaderEditor;
+class HSplitContainer;
+class ShaderCreateDialog;
+
class ShaderTextEditor : public CodeTextEditor {
GDCLASS(ShaderTextEditor, CodeTextEditor);
@@ -160,9 +165,40 @@ public:
class ShaderEditorPlugin : public EditorPlugin {
GDCLASS(ShaderEditorPlugin, EditorPlugin);
- bool _2d;
- ShaderEditor *shader_editor = nullptr;
+ struct EditedShader {
+ Ref<Shader> shader;
+ ShaderEditor *shader_editor = nullptr;
+ VisualShaderEditor *visual_shader_editor = nullptr;
+ };
+
+ LocalVector<EditedShader> edited_shaders;
+
+ enum {
+ FILE_NEW,
+ FILE_OPEN,
+ FILE_SAVE,
+ FILE_SAVE_AS,
+ FILE_INSPECT,
+ FILE_CLOSE,
+ FILE_MAX
+ };
+
+ HSplitContainer *main_split = nullptr;
+ ItemList *shader_list = nullptr;
+ TabContainer *shader_tabs = nullptr;
+
Button *button = nullptr;
+ MenuButton *file_menu = nullptr;
+
+ ShaderCreateDialog *shader_create_dialog = nullptr;
+
+ void _update_shader_list();
+ void _shader_selected(int p_index);
+ void _menu_item_pressed(int p_index);
+ void _resource_saved(Object *obj);
+ void _close_shader(int p_index);
+
+ void _shader_created(Ref<Shader> p_shader);
public:
virtual String get_name() const override { return "Shader"; }
@@ -172,7 +208,7 @@ public:
virtual void make_visible(bool p_visible) override;
virtual void selected_notify() override;
- ShaderEditor *get_shader_editor() const { return shader_editor; }
+ ShaderEditor *get_shader_editor(const Ref<Shader> &p_for_shader);
virtual void save_external_data() override;
virtual void apply_changes() override;
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index ec45341970..468681c967 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -1147,7 +1147,7 @@ void TileDataDefaultEditor::setup_property_editor(Variant::Type p_type, String p
property_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, p_type, p_property, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT);
property_editor->set_object_and_property(dummy_object, p_property);
if (p_label.is_empty()) {
- property_editor->set_label(p_property);
+ property_editor->set_label(EditorPropertyNameProcessor::get_singleton()->process_name(p_property, EditorPropertyNameProcessor::get_default_inspector_style()));
} else {
property_editor->set_label(p_label);
}
@@ -1173,6 +1173,7 @@ TileDataDefaultEditor::TileDataDefaultEditor() {
label = memnew(Label);
label->set_text(TTR("Painting:"));
+ label->set_theme_type_variation("HeaderSmall");
add_child(label);
toolbar->add_child(memnew(VSeparator));
@@ -2566,7 +2567,8 @@ TileDataTerrainsEditor::TileDataTerrainsEditor() {
undo_redo = EditorNode::get_undo_redo();
label = memnew(Label);
- label->set_text("Painting:");
+ label->set_text(TTR("Painting:"));
+ label->set_theme_type_variation("HeaderSmall");
add_child(label);
// Toolbar
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 77a3c07548..d914b9c363 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -884,6 +884,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
if (atlas_source) {
// Get tile data.
TileData *tile_data = atlas_source->get_tile_data(E.value.get_atlas_coords(), E.value.alternative_tile);
+ if (!tile_data) {
+ continue;
+ }
// Compute the offset
Rect2i source_rect = atlas_source->get_tile_texture_region(E.value.get_atlas_coords());
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 66459d3ef9..37ccc6ad45 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -97,9 +97,9 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN
void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, ""));
p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "suffix:px"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "suffix:px"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "suffix:px"));
p_list->push_back(PropertyInfo(Variant::BOOL, "use_texture_padding", PROPERTY_HINT_NONE, ""));
}
@@ -401,15 +401,15 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
if (all_alternatve_id_zero) {
p_list->push_back(PropertyInfo(Variant::NIL, "Animation", PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP));
p_list->push_back(PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "animation_separation", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "animation_separation", PROPERTY_HINT_NONE, "suffix:px"));
p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, ""));
p_list->push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_"));
// Not optimal, but returns value for the first tile. This is similar to what MultiNodeEdit does.
if (tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile) == 1) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_frame_0/duration", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_frame_0/duration", PROPERTY_HINT_NONE, "suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
} else {
for (int i = 0; i < tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile); i++) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "suffix:s"));
}
}
}
@@ -2335,6 +2335,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
// Tile inspector.
tile_inspector_label = memnew(Label);
tile_inspector_label->set_text(TTR("Tile Properties:"));
+ tile_inspector_label->set_theme_type_variation("HeaderSmall");
middle_vbox_container->add_child(tile_inspector_label);
tile_proxy_object = memnew(AtlasTileProxyObject(this));
@@ -2350,7 +2351,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_inspector_no_tile_selected_label = memnew(Label);
tile_inspector_no_tile_selected_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- tile_inspector_no_tile_selected_label->set_text(TTR("No tile selected."));
+ tile_inspector_no_tile_selected_label->set_text(TTR("No tiles selected."));
middle_vbox_container->add_child(tile_inspector_no_tile_selected_label);
// Property values palette.
@@ -2358,6 +2359,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_data_editors_label = memnew(Label);
tile_data_editors_label->set_text(TTR("Paint Properties:"));
+ tile_data_editors_label->set_theme_type_variation("HeaderSmall");
middle_vbox_container->add_child(tile_data_editors_label);
tile_data_editor_dropdown_button = memnew(Button);
@@ -2381,6 +2383,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
// Atlas source inspector.
atlas_source_inspector_label = memnew(Label);
atlas_source_inspector_label->set_text(TTR("Atlas Properties:"));
+ atlas_source_inspector_label->set_theme_type_variation("HeaderSmall");
middle_vbox_container->add_child(atlas_source_inspector_label);
atlas_source_proxy_object = memnew(TileSetAtlasSourceProxyObject());
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 3491f8a468..8c72a886ea 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -5645,48 +5645,6 @@ VisualShaderEditor::VisualShaderEditor() {
property_editor->connect("variant_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
}
-/////////////////
-
-void VisualShaderEditorPlugin::edit(Object *p_object) {
- visual_shader_editor->edit(Object::cast_to<VisualShader>(p_object));
-}
-
-bool VisualShaderEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("VisualShader");
-}
-
-void VisualShaderEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- //editor->hide_animation_player_editors();
- //editor->animation_panel_make_visible(true);
- button->show();
- EditorNode::get_singleton()->make_bottom_panel_item_visible(visual_shader_editor);
- visual_shader_editor->update_nodes();
- visual_shader_editor->set_process_input(true);
- //visual_shader_editor->set_process(true);
- } else {
- if (visual_shader_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- visual_shader_editor->set_process_input(false);
- //visual_shader_editor->set_process(false);
- }
-}
-
-VisualShaderEditorPlugin::VisualShaderEditorPlugin() {
- visual_shader_editor = memnew(VisualShaderEditor);
- visual_shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
-
- button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("VisualShader"), visual_shader_editor);
- button->hide();
-}
-
-VisualShaderEditorPlugin::~VisualShaderEditorPlugin() {
-}
-
-////////////////
-
class VisualShaderNodePluginInputEditor : public OptionButton {
GDCLASS(VisualShaderNodePluginInputEditor, OptionButton);
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 1b56892ebf..b8da266ed7 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -493,23 +493,6 @@ public:
VisualShaderEditor();
};
-class VisualShaderEditorPlugin : public EditorPlugin {
- GDCLASS(VisualShaderEditorPlugin, EditorPlugin);
-
- VisualShaderEditor *visual_shader_editor = nullptr;
- Button *button = nullptr;
-
-public:
- virtual String get_name() const override { return "VisualShader"; }
- bool has_main_screen() const override { return false; }
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- VisualShaderEditorPlugin();
- ~VisualShaderEditorPlugin();
-};
-
class VisualShaderNodePluginDefault : public VisualShaderNodePlugin {
GDCLASS(VisualShaderNodePluginDefault, VisualShaderNodePlugin);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 404199d2da..1524993bd0 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "servers/movie_writer/movie_writer.h"
ProjectSettingsEditor *ProjectSettingsEditor::singleton = nullptr;
@@ -261,6 +262,7 @@ void ProjectSettingsEditor::_add_feature_overrides() {
presets.insert("standalone");
presets.insert("32");
presets.insert("64");
+ presets.insert("movie");
EditorExport *ee = EditorExport::get_singleton();
@@ -698,4 +700,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
import_defaults_editor->set_name(TTR("Import Defaults"));
tab_container->add_child(import_defaults_editor);
import_defaults_editor->connect("project_settings_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
+
+ MovieWriter::set_extensions_hint(); // ensure extensions are properly displayed.
}
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index 53da945868..4938699fc4 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -146,8 +146,8 @@ void EditorQuickOpen::_confirmed() {
return;
}
_cleanup();
- emit_signal(SNAME("quick_open"));
hide();
+ emit_signal(SNAME("quick_open"));
}
void EditorQuickOpen::cancel_pressed() {
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 08df4cdf3c..2e1090e6c0 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2418,8 +2418,8 @@ void SceneTreeDock::_new_scene_from(String p_file) {
Node *copy = base->duplicate_from_editor(duplimap);
if (copy) {
- for (int i = 0; i < copy->get_child_count(); i++) {
- _set_node_owner_recursive(copy->get_child(i), copy);
+ for (int i = 0; i < copy->get_child_count(false); i++) {
+ _set_node_owner_recursive(copy->get_child(i, false), copy);
}
Ref<PackedScene> sdata = memnew(PackedScene);
@@ -2456,8 +2456,8 @@ void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner) {
p_node->set_owner(p_owner);
}
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _set_node_owner_recursive(p_node->get_child(i), p_owner);
+ for (int i = 0; i < p_node->get_child_count(false); i++) {
+ _set_node_owner_recursive(p_node->get_child(i, false), p_owner);
}
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 5536e09da7..86fa9222c0 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1353,8 +1353,9 @@ void SceneTreeDialog::_cancel() {
void SceneTreeDialog::_select() {
if (tree->get_selected()) {
- emit_signal(SNAME("selected"), tree->get_selected()->get_path());
+ // The signal may cause another dialog to be displayed, so be sure to hide this one first.
hide();
+ emit_signal(SNAME("selected"), tree->get_selected()->get_path());
}
}