summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/math_funcs.cpp12
-rw-r--r--core/script_debugger_remote.cpp11
-rw-r--r--doc/classes/EditorSettings.xml8
-rw-r--r--drivers/gles3/shaders/canvas.glsl10
-rw-r--r--editor/connections_dialog.cpp3
-rw-r--r--editor/dependency_editor.cpp28
-rw-r--r--editor/editor_file_dialog.cpp20
-rw-r--r--editor/editor_file_dialog.h4
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/editor_node.cpp248
-rw-r--r--editor/editor_node.h17
-rw-r--r--editor/editor_plugin.cpp30
-rw-r--r--editor/editor_plugin.h8
-rw-r--r--editor/editor_resource_preview.cpp109
-rw-r--r--editor/editor_resource_preview.h11
-rw-r--r--editor/editor_settings.cpp32
-rw-r--r--editor/editor_settings.h6
-rw-r--r--editor/filesystem_dock.cpp1468
-rw-r--r--editor/filesystem_dock.h90
-rw-r--r--editor/inspector_dock.cpp1
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp12
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.h4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp25
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h4
-rw-r--r--editor/plugins/editor_preview_plugins.cpp151
-rw-r--r--editor/plugins/editor_preview_plugins.h26
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.cpp8
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.h4
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/path_2d_editor_plugin.h4
-rw-r--r--editor/plugins/script_text_editor.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp4
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp12
-rw-r--r--editor/plugins/spatial_editor_plugin.h1
-rw-r--r--editor/plugins/text_editor.cpp3
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp40
-rw-r--r--editor/plugins/tile_map_editor_plugin.h8
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp11
-rw-r--r--editor/scene_tree_dock.cpp2
-rw-r--r--editor/script_editor_debugger.cpp26
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp2
-rw-r--r--modules/opensimplex/doc_classes/SimplexNoise.xml2
-rw-r--r--scene/gui/tree.cpp4
-rw-r--r--scene/main/node.cpp12
-rw-r--r--scene/resources/font.cpp1
-rw-r--r--scene/resources/shader.cpp11
-rw-r--r--scene/resources/shader.h2
-rw-r--r--scene/resources/visual_shader.cpp4
-rw-r--r--scene/resources/visual_shader.h2
-rw-r--r--servers/visual/shader_language.cpp3
54 files changed, 1486 insertions, 1034 deletions
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 5c8512d8bd..0c06d2a2b5 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -57,7 +57,7 @@ uint32_t Math::rand() {
}
int Math::step_decimals(double p_step) {
- static const int maxn = 9;
+ static const int maxn = 10;
static const double sd[maxn] = {
0.9999, // somehow compensate for floating point error
0.09999,
@@ -67,17 +67,19 @@ int Math::step_decimals(double p_step) {
0.000009999,
0.0000009999,
0.00000009999,
- 0.000000009999
+ 0.000000009999,
+ 0.0000000009999
};
- double as = Math::abs(p_step);
+ double abs = Math::abs(p_step);
+ double decs = abs - (int)abs; // Strip away integer part
for (int i = 0; i < maxn; i++) {
- if (as >= sd[i]) {
+ if (decs >= sd[i]) {
return i;
}
}
- return maxn;
+ return 0;
}
double Math::dectime(double p_value, double p_amount, double p_step) {
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 704b4d1fdc..fe1dc2cdd1 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -662,11 +662,14 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
prop.push_back(Variant());
} else {
prop.push_back(pi.hint);
- if (res.is_null() || res->get_path().empty())
- prop.push_back(pi.hint_string);
- else
- prop.push_back(String("RES:") + res->get_path());
+ prop.push_back(pi.hint_string);
prop.push_back(pi.usage);
+ if (!res.is_null()) {
+ var = String("PATH") + res->get_path();
+ } else if (var.get_type() == Variant::STRING) {
+ var = String("DATA") + var;
+ }
+
prop.push_back(var);
}
send_props.push_back(prop);
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index bd85075b7e..9d48669a6b 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -48,11 +48,11 @@
Erase a given setting (pass full property path).
</description>
</method>
- <method name="get_favorite_dirs" qualifiers="const">
+ <method name="get_favorites" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
- Get the list of favorite directories for this project.
+ Get the list of favorite files and directories for this project.
</description>
</method>
<method name="get_project_metadata" qualifiers="const">
@@ -122,13 +122,13 @@
<description>
</description>
</method>
- <method name="set_favorite_dirs">
+ <method name="set_favorites">
<return type="void">
</return>
<argument index="0" name="dirs" type="PoolStringArray">
</argument>
<description>
- Set the list of favorite directories for this project.
+ Set the list of favorite files and directories for this project.
</description>
</method>
<method name="set_initial_value">
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 53f563303a..5203f53fa2 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -120,12 +120,12 @@ void main() {
vec4 color = color_attrib;
#ifdef USE_INSTANCING
- mat4 extra_matrix2 = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
+ mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
color *= instance_color;
vec4 instance_custom = instance_custom_data;
#else
- mat4 extra_matrix2 = extra_matrix;
+ mat4 extra_matrix_instance = extra_matrix;
vec4 instance_custom = vec4(0.0);
#endif
@@ -157,7 +157,7 @@ void main() {
#endif
-#define extra_matrix extra_matrix2
+#define extra_matrix extra_matrix_instance
{
/* clang-format off */
@@ -246,8 +246,8 @@ VERTEX_SHADER_CODE
pos = outvec.xy;
#endif
- local_rot.xy = normalize((modelview_matrix * (extra_matrix * vec4(1.0, 0.0, 0.0, 0.0))).xy);
- local_rot.zw = normalize((modelview_matrix * (extra_matrix * vec4(0.0, 1.0, 0.0, 0.0))).xy);
+ local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy);
+ local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy);
#ifdef USE_TEXTURE_RECT
local_rot.xy *= sign(src_rect.z);
local_rot.zw *= sign(src_rect.w);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 456e2fa1f0..a1337268ba 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -432,6 +432,9 @@ void ConnectionsDock::_make_or_edit_connection() {
if (add_script_function) {
// pick up args here before "it" is deleted by update_tree
script_function_args = it->get_metadata(0).operator Dictionary()["args"];
+ for (int i = 0; i < cToMake.binds.size(); i++) {
+ script_function_args.append("extra_arg_" + itos(i));
+ }
}
if (connect_dialog->is_editing()) {
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 037543f45c..d64b02a605 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -504,7 +504,7 @@ void DependencyRemoveDialog::ok_pressed() {
}
if (dirs_to_delete.size() == 0) {
- //If we only deleted files we should only need to tell the file system about the files we touched.
+ // If we only deleted files we should only need to tell the file system about the files we touched.
for (int i = 0; i < files_to_delete.size(); ++i)
EditorFileSystem::get_singleton()->update_file(files_to_delete[i]);
} else {
@@ -518,21 +518,25 @@ void DependencyRemoveDialog::ok_pressed() {
}
}
- // if some dirs would be deleted, favorite dirs need to be updated
- Vector<String> previous_favorite_dirs = EditorSettings::get_singleton()->get_favorite_dirs();
- Vector<String> new_favorite_dirs;
+ EditorFileSystem::get_singleton()->scan_changes();
+ }
- for (int i = 0; i < previous_favorite_dirs.size(); ++i) {
- if (dirs_to_delete.find(previous_favorite_dirs[i] + "/") < 0) {
- new_favorite_dirs.push_back(previous_favorite_dirs[i]);
- }
- }
+ // If some files/dirs would be deleted, favorite dirs need to be updated
+ Vector<String> previous_favorites = EditorSettings::get_singleton()->get_favorites();
+ Vector<String> new_favorites;
- if (new_favorite_dirs.size() < previous_favorite_dirs.size()) {
- EditorSettings::get_singleton()->set_favorite_dirs(new_favorite_dirs);
+ for (int i = 0; i < previous_favorites.size(); ++i) {
+ if (previous_favorites[i].ends_with("/")) {
+ if (dirs_to_delete.find(previous_favorites[i]) < 0)
+ new_favorites.push_back(previous_favorites[i]);
+ } else {
+ if (files_to_delete.find(previous_favorites[i]) < 0)
+ new_favorites.push_back(previous_favorites[i]);
}
+ }
- EditorFileSystem::get_singleton()->scan_changes();
+ if (new_favorites.size() < previous_favorites.size()) {
+ EditorSettings::get_singleton()->set_favorites(new_favorites);
}
}
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 3659a06bb7..f11a30bb86 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -269,7 +269,7 @@ void EditorFileDialog::_post_popup() {
set_process_unhandled_input(true);
}
-void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) {
+void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
if (display_mode == DISPLAY_LIST || p_preview.is_null())
return;
@@ -284,7 +284,7 @@ void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture
}
}
-void EditorFileDialog::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) {
+void EditorFileDialog::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
set_process(false);
preview_waiting = false;
@@ -1115,7 +1115,7 @@ void EditorFileDialog::_update_drives() {
void EditorFileDialog::_favorite_selected(int p_idx) {
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorites();
ERR_FAIL_INDEX(p_idx, favorited.size());
dir_access->change_dir(favorited[p_idx]);
@@ -1130,7 +1130,7 @@ void EditorFileDialog::_favorite_move_up() {
int current = favorites->get_current();
if (current > 0 && current < favorites->get_item_count()) {
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorites();
int a_idx = favorited.find(String(favorites->get_item_metadata(current - 1)));
int b_idx = favorited.find(String(favorites->get_item_metadata(current)));
@@ -1139,7 +1139,7 @@ void EditorFileDialog::_favorite_move_up() {
return;
SWAP(favorited.write[a_idx], favorited.write[b_idx]);
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+ EditorSettings::get_singleton()->set_favorites(favorited);
_update_favorites();
update_file_list();
@@ -1150,7 +1150,7 @@ void EditorFileDialog::_favorite_move_down() {
int current = favorites->get_current();
if (current >= 0 && current < favorites->get_item_count() - 1) {
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorites();
int a_idx = favorited.find(String(favorites->get_item_metadata(current + 1)));
int b_idx = favorited.find(String(favorites->get_item_metadata(current)));
@@ -1159,7 +1159,7 @@ void EditorFileDialog::_favorite_move_down() {
return;
SWAP(favorited.write[a_idx], favorited.write[b_idx]);
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+ EditorSettings::get_singleton()->set_favorites(favorited);
_update_favorites();
update_file_list();
@@ -1176,7 +1176,7 @@ void EditorFileDialog::_update_favorites() {
favorite->set_pressed(false);
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < favorited.size(); i++) {
bool cres = favorited[i].begins_with("res://");
if (cres != res)
@@ -1206,7 +1206,7 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) {
String cd = get_current_dir();
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorites();
bool found = false;
for (int i = 0; i < favorited.size(); i++) {
@@ -1228,7 +1228,7 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) {
favorite->set_pressed(true);
}
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+ EditorSettings::get_singleton()->set_favorites(favorited);
_update_favorites();
}
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 61eeff9162..56cefb9a47 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -190,8 +190,8 @@ private:
void _save_to_recent();
//callback function is callback(String p_path,Ref<Texture> preview,Variant udata) preview null if could not load
- void _thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
- void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
+ void _thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
+ void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
void _request_single_thumbnail(const String &p_path);
void _unhandled_input(const Ref<InputEvent> &p_event);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 728c4affbd..60040f641b 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -752,6 +752,8 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
}
void EditorHelp::_update_doc() {
+ if (!doc->class_list.has(edited_class))
+ return;
scroll_locked = true;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 0ba1ef3b18..03746fb8b7 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2039,6 +2039,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
emit_signal("stop_pressed");
} break;
+
+ case FILE_SHOW_IN_FILESYSTEM: {
+ String path = editor_data.get_scene_path(editor_data.get_edited_scene());
+ if (path != String()) {
+ filesystem_dock->navigate_to_path(path);
+ }
+ } break;
+
case RUN_PLAY_SCENE: {
_save_default_environment();
@@ -3357,19 +3365,12 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
dock_slot[nrect]->show();
dock_select->update();
- VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
if (in_use)
- splits[i]->show();
+ vsplits[i]->show();
else
- splits[i]->hide();
+ vsplits[i]->hide();
}
if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
@@ -3541,30 +3542,16 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p
p_layout->set_value(p_section, "dock_filesystem_split", filesystem_dock->get_split_offset());
- VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
- if (splits[i]->is_visible_in_tree()) {
- p_layout->set_value(p_section, "dock_split_" + itos(i + 1), splits[i]->get_split_offset());
+ if (vsplits[i]->is_visible_in_tree()) {
+ p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
}
}
- HSplitContainer *h_splits[4] = {
- left_l_hsplit,
- left_r_hsplit,
- main_hsplit,
- right_hsplit,
- };
+ for (int i = 0; i < hsplits.size(); i++) {
- for (int i = 0; i < 4; i++) {
-
- p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), h_splits[i]->get_split_offset());
+ p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset());
}
}
@@ -3610,21 +3597,14 @@ void EditorNode::_load_docks() {
void EditorNode::_update_dock_slots_visibility() {
- VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
if (!docks_visible) {
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
dock_slot[i]->hide();
}
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
- splits[i]->hide();
+ for (int i = 0; i < vsplits.size(); i++) {
+ vsplits[i]->hide();
}
right_hsplit->hide();
@@ -3638,12 +3618,12 @@ void EditorNode::_update_dock_slots_visibility() {
dock_slot[i]->hide();
}
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
if (in_use)
- splits[i]->show();
+ vsplits[i]->show();
else
- splits[i]->hide();
+ vsplits[i]->hide();
}
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
@@ -3664,12 +3644,6 @@ void EditorNode::_update_dock_slots_visibility() {
void EditorNode::_dock_tab_changed(int p_tab) {
// update visibility but don't set current tab
- VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
if (!docks_visible) {
@@ -3677,8 +3651,8 @@ void EditorNode::_dock_tab_changed(int p_tab) {
dock_slot[i]->hide();
}
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
- splits[i]->hide();
+ for (int i = 0; i < vsplits.size(); i++) {
+ vsplits[i]->hide();
}
right_hsplit->hide();
@@ -3692,12 +3666,12 @@ void EditorNode::_dock_tab_changed(int p_tab) {
dock_slot[i]->hide();
}
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
if (in_use)
- splits[i]->show();
+ vsplits[i]->show();
else
- splits[i]->hide();
+ vsplits[i]->hide();
}
bottom_panel->show();
@@ -3756,42 +3730,28 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
}
filesystem_dock->set_split_offset(fs_split_ofs);
- VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1)))
continue;
int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
- splits[i]->set_split_offset(ofs);
+ vsplits[i]->set_split_offset(ofs);
}
- HSplitContainer *h_splits[4] = {
- left_l_hsplit,
- left_r_hsplit,
- main_hsplit,
- right_hsplit,
- };
-
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < hsplits.size(); i++) {
if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1)))
continue;
int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
- h_splits[i]->set_split_offset(ofs);
+ hsplits[i]->set_split_offset(ofs);
}
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
+ for (int i = 0; i < vsplits.size(); i++) {
bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
if (in_use)
- splits[i]->show();
+ vsplits[i]->show();
else
- splits[i]->hide();
+ vsplits[i]->hide();
}
if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
@@ -3975,6 +3935,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) {
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES);
if (scene_tabs->get_hovered_tab() >= 0) {
scene_tabs_context_menu->add_separator();
+ scene_tabs_context_menu->add_item(TTR("Show in filesystem"), FILE_SHOW_IN_FILESYSTEM);
scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE);
scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE);
}
@@ -3989,7 +3950,7 @@ void EditorNode::_reposition_active_tab(int idx_to) {
_update_scene_tabs();
}
-void EditorNode::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) {
+void EditorNode::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
int p_tab = p_udata.operator signed int();
if (p_preview.is_valid()) {
Rect2 rect = scene_tabs->get_tab_rect(p_tab);
@@ -4925,9 +4886,6 @@ EditorNode::EditorNode() {
left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
- left_l_vsplit->hide();
- dock_slot[DOCK_SLOT_LEFT_UL]->hide();
- dock_slot[DOCK_SLOT_LEFT_BL]->hide();
left_r_hsplit = memnew(HSplitContainer);
left_l_hsplit->add_child(left_r_hsplit);
@@ -4965,19 +4923,22 @@ EditorNode::EditorNode() {
right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
- right_r_vsplit->hide();
- dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
- dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
- left_l_vsplit->connect("dragged", this, "_dock_split_dragged");
- left_r_vsplit->connect("dragged", this, "_dock_split_dragged");
- right_l_vsplit->connect("dragged", this, "_dock_split_dragged");
- right_r_vsplit->connect("dragged", this, "_dock_split_dragged");
+ // Store them for easier access
+ vsplits.push_back(left_l_vsplit);
+ vsplits.push_back(left_r_vsplit);
+ vsplits.push_back(right_l_vsplit);
+ vsplits.push_back(right_r_vsplit);
- left_l_hsplit->connect("dragged", this, "_dock_split_dragged");
- left_r_hsplit->connect("dragged", this, "_dock_split_dragged");
- main_hsplit->connect("dragged", this, "_dock_split_dragged");
- right_hsplit->connect("dragged", this, "_dock_split_dragged");
+ hsplits.push_back(left_l_hsplit);
+ hsplits.push_back(left_r_hsplit);
+ hsplits.push_back(main_hsplit);
+ hsplits.push_back(right_hsplit);
+
+ for (int i = 0; i < vsplits.size(); i++) {
+ vsplits[i]->connect("dragged", this, "_dock_split_dragged");
+ hsplits[i]->connect("dragged", this, "_dock_split_dragged");
+ }
dock_select_popup = memnew(PopupPanel);
gui_base->add_child(dock_select_popup);
@@ -5487,63 +5448,72 @@ EditorNode::EditorNode() {
_menu_option(SETTINGS_UPDATE_SPINNER_HIDE);
}
- scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data));
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(scene_tree_dock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
- dock_slot[DOCK_SLOT_LEFT_BR]->hide();
+ // Instantiate and place editor docks
+ scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data));
inspector_dock = memnew(InspectorDock(this, editor_data));
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(inspector_dock);
- dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
-
- Button *property_editable_warning;
-
import_dock = memnew(ImportDock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(import_dock->get_index(), TTR("Import"));
-
- bool use_single_dock_column = (OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x < 1200);
-
node_dock = memnew(NodeDock);
- if (use_single_dock_column) {
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node"));
- } else {
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
- dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(node_dock->get_index(), TTR("Node"));
- }
filesystem_dock = memnew(FileSystemDock(this));
- filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
-
- if (use_single_dock_column) {
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock);
- dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
- left_r_vsplit->hide();
- dock_slot[DOCK_SLOT_LEFT_UR]->hide();
- dock_slot[DOCK_SLOT_LEFT_BR]->hide();
- } else {
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(filesystem_dock);
- dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
- }
+ filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/files_display_mode")));
filesystem_dock->connect("open", this, "open_request");
filesystem_dock->connect("instance", this, "_instance_request");
- const String docks_section = "docks";
+ // Scene: Top left
+ dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock);
+ dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
+
+ // Import: Top left, behind Scene
+ dock_slot[DOCK_SLOT_LEFT_UR]->add_child(import_dock);
+ dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(import_dock->get_index(), TTR("Import"));
+
+ // FileSystem: Bottom left
+ dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock);
+ dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
+
+ // Inspector: Full height right
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock);
+ dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
+
+ // Node: Full height right, behind Inspector
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
+ dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node"));
+
+ // Hide unused dock slots and vsplits
+ dock_slot[DOCK_SLOT_LEFT_UL]->hide();
+ dock_slot[DOCK_SLOT_LEFT_BL]->hide();
+ dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
+ dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
+ dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
+ left_l_vsplit->hide();
+ right_r_vsplit->hide();
+
+ // Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize
+ left_r_hsplit->set_split_offset(40 * EDSCALE);
+ main_hsplit->set_split_offset(-40 * EDSCALE);
+ // Define corresponding default layout
+
+ const String docks_section = "docks";
overridden_default_layout = -1;
default_layout.instance();
- default_layout->set_value(docks_section, "dock_3", "FileSystem");
- default_layout->set_value(docks_section, "dock_5", "Scene,Import");
- default_layout->set_value(docks_section, "dock_6", "Inspector,Node");
+ // Dock numbers are based on DockSlot enum value + 1
+ default_layout->set_value(docks_section, "dock_3", "Scene,Import");
+ default_layout->set_value(docks_section, "dock_4", "FileSystem");
+ default_layout->set_value(docks_section, "dock_5", "Inspector,Node");
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++)
- default_layout->set_value(docks_section, "dock_hsplit_" + itos(i + 1), 0);
- for (int i = 0; i < DOCK_SLOT_MAX / 2; i++)
+ for (int i = 0; i < vsplits.size(); i++)
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
+ default_layout->set_value(docks_section, "dock_hsplit_1", 0);
+ default_layout->set_value(docks_section, "dock_hsplit_2", 40 * EDSCALE);
+ default_layout->set_value(docks_section, "dock_hsplit_3", -40 * EDSCALE);
+ default_layout->set_value(docks_section, "dock_hsplit_4", 0);
_update_layouts_menu();
+ // Bottom panels
+
bottom_panel = memnew(PanelContainer);
bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
center_split->add_child(bottom_panel);
@@ -5928,17 +5898,31 @@ bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
return discard;
}
-void EditorPluginList::forward_draw_over_viewport(Control *p_overlay) {
+void EditorPluginList::forward_canvas_draw_over_viewport(Control *p_overlay) {
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ plugins_list[i]->forward_canvas_draw_over_viewport(p_overlay);
+ }
+}
+
+void EditorPluginList::forward_canvas_force_draw_over_viewport(Control *p_overlay) {
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ plugins_list[i]->forward_canvas_force_draw_over_viewport(p_overlay);
+ }
+}
+
+void EditorPluginList::forward_spatial_draw_over_viewport(Control *p_overlay) {
for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->forward_draw_over_viewport(p_overlay);
+ plugins_list[i]->forward_spatial_draw_over_viewport(p_overlay);
}
}
-void EditorPluginList::forward_force_draw_over_viewport(Control *p_overlay) {
+void EditorPluginList::forward_spatial_force_draw_over_viewport(Control *p_overlay) {
for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->forward_force_draw_over_viewport(p_overlay);
+ plugins_list[i]->forward_spatial_force_draw_over_viewport(p_overlay);
}
}
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 7409c64a64..bdbe0a245b 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -125,6 +125,7 @@ private:
FILE_SAVE_ALL_SCENES,
FILE_SAVE_BEFORE_RUN,
FILE_SAVE_AND_RUN,
+ FILE_SHOW_IN_FILESYSTEM,
FILE_IMPORT_SUBSCENE,
FILE_EXPORT_PROJECT,
FILE_EXPORT_MESH_LIBRARY,
@@ -208,7 +209,7 @@ private:
String video_driver_request;
void _video_driver_selected(int);
- //split
+ // Split containers
HSplitContainer *left_l_hsplit;
VSplitContainer *left_l_vsplit;
@@ -221,7 +222,11 @@ private:
VSplitContainer *center_split;
- //main tabs
+ // To access those easily by index
+ Vector<VSplitContainer *> vsplits;
+ Vector<HSplitContainer *> hsplits;
+
+ // Main tabs
Tabs *scene_tabs;
PopupMenu *scene_tabs_context_menu;
@@ -535,7 +540,7 @@ private:
void _scene_tab_exit();
void _scene_tab_input(const Ref<InputEvent> &p_input);
void _reposition_active_tab(int idx_to);
- void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
+ void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
void _scene_tab_script_edited(int p_tab);
Dictionary _get_main_scene_state();
@@ -812,9 +817,11 @@ public:
void make_visible(bool p_visible);
void edit(Object *p_object);
bool forward_gui_input(const Ref<InputEvent> &p_event);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_force_draw_over_viewport(Control *p_overlay);
bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled);
- void forward_draw_over_viewport(Control *p_overlay);
- void forward_force_draw_over_viewport(Control *p_overlay);
+ void forward_spatial_draw_over_viewport(Control *p_overlay);
+ void forward_spatial_force_draw_over_viewport(Control *p_overlay);
void add_plugin(EditorPlugin *p_plugin);
void clear();
bool empty();
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 1f2e73654c..1ad23963a9 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -503,17 +503,17 @@ bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void EditorPlugin::forward_draw_over_viewport(Control *p_overlay) {
+void EditorPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_viewport")) {
- get_script_instance()->call("forward_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("forward_canvas_draw_over_viewport")) {
+ get_script_instance()->call("forward_canvas_draw_over_viewport", p_overlay);
}
}
-void EditorPlugin::forward_force_draw_over_viewport(Control *p_overlay) {
+void EditorPlugin::forward_canvas_force_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_force_draw_over_viewport")) {
- get_script_instance()->call("forward_force_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("forward_canvas_force_draw_over_viewport")) {
+ get_script_instance()->call("forward_canvas_force_draw_over_viewport", p_overlay);
}
}
@@ -545,6 +545,20 @@ bool EditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEv
return false;
}
+
+void EditorPlugin::forward_spatial_draw_over_viewport(Control *p_overlay) {
+
+ if (get_script_instance() && get_script_instance()->has_method("forward_spatial_draw_over_viewport")) {
+ get_script_instance()->call("forward_spatial_draw_over_viewport", p_overlay);
+ }
+}
+
+void EditorPlugin::forward_spatial_force_draw_over_viewport(Control *p_overlay) {
+
+ if (get_script_instance() && get_script_instance()->has_method("forward_spatial_force_draw_over_viewport")) {
+ get_script_instance()->call("forward_spatial_force_draw_over_viewport", p_overlay);
+ }
+}
String EditorPlugin::get_name() const {
if (get_script_instance() && get_script_instance()->has_method("get_plugin_name")) {
@@ -769,8 +783,8 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_script_create_dialog"), &EditorPlugin::get_script_create_dialog);
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name"));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::OBJECT, "get_plugin_icon"));
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 6c385abf9b..e03aeb5d30 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -174,9 +174,13 @@ public:
void notify_resource_saved(const Ref<Resource> &p_resource);
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
- virtual void forward_draw_over_viewport(Control *p_overlay);
- virtual void forward_force_draw_over_viewport(Control *p_overlay);
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay);
+ virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay);
+
virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event);
+ virtual void forward_spatial_draw_over_viewport(Control *p_overlay);
+ virtual void forward_spatial_force_draw_over_viewport(Control *p_overlay);
+
virtual String get_name() const;
virtual const Ref<Texture> get_icon() const;
virtual bool has_main_screen() const;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index edfee595ea..310c3b3a52 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -30,11 +30,14 @@
#include "editor_resource_preview.h"
+#include "core/method_bind_ext.gen.inc"
+
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/message_queue.h"
#include "core/os/file_access.h"
#include "core/project_settings.h"
+#include "editor_node.h"
#include "editor_scale.h"
#include "editor_settings.h"
@@ -46,32 +49,37 @@ bool EditorResourcePreviewGenerator::handles(const String &p_type) const {
ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overridden");
ERR_FAIL_V(false);
}
-Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from) const {
+
+Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from, const Size2 p_size) const {
if (get_script_instance() && get_script_instance()->has_method("generate")) {
- return get_script_instance()->call("generate", p_from);
+ return get_script_instance()->call("generate", p_from, p_size);
}
ERR_EXPLAIN("EditorResourcePreviewGenerator::generate needs to be overridden");
ERR_FAIL_V(Ref<Texture>());
}
-Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path) const {
+Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 p_size) const {
if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) {
- return get_script_instance()->call("generate_from_path", p_path);
+ return get_script_instance()->call("generate_from_path", p_path, p_size);
}
RES res = ResourceLoader::load(p_path);
if (!res.is_valid())
return res;
- return generate(res);
+ return generate(res, p_size);
+}
+
+bool EditorResourcePreviewGenerator::should_generate_small_preview() const {
+ return false;
}
void EditorResourcePreviewGenerator::_bind_methods() {
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles", PropertyInfo(Variant::STRING, "type")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE)));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::VECTOR2, "size")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE), PropertyInfo(Variant::VECTOR2, "size")));
}
EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
@@ -85,7 +93,7 @@ void EditorResourcePreview::_thread_func(void *ud) {
erp->_thread();
}
-void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) {
+void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, const Ref<Texture> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) {
preview_mutex->lock();
@@ -103,6 +111,7 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur
Item item;
item.order = order++;
item.preview = p_texture;
+ item.small_preview = p_small_texture;
item.last_hash = hash;
item.modified_time = modified_time;
@@ -110,11 +119,10 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur
preview_mutex->unlock();
- MessageQueue::get_singleton()->push_call(id, p_func, path, p_texture, p_ud);
+ MessageQueue::get_singleton()->push_call(id, p_func, path, p_texture, p_small_texture, p_ud);
}
-Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, const String &cache_base) {
-
+void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base) {
String type;
if (p_item.resource.is_valid())
@@ -122,40 +130,59 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
else
type = ResourceLoader::get_resource_type(p_item.path);
- if (type == "")
- return Ref<Texture>(); //could not guess type
+ if (type == "") {
+ r_texture = Ref<ImageTexture>();
+ r_small_texture = Ref<ImageTexture>();
+ return; //could not guess type
+ }
- Ref<Texture> generated;
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size *= EDSCALE;
- for (int i = 0; i < preview_generators.size(); i++) {
+ r_texture = Ref<ImageTexture>();
+ r_small_texture = Ref<ImageTexture>();
+ for (int i = 0; i < preview_generators.size(); i++) {
if (!preview_generators[i]->handles(type))
continue;
+
+ Ref<Texture> generated;
if (p_item.resource.is_valid()) {
- generated = preview_generators[i]->generate(p_item.resource);
+ generated = preview_generators[i]->generate(p_item.resource, Vector2(thumbnail_size, thumbnail_size));
} else {
- generated = preview_generators[i]->generate_from_path(p_item.path);
+ generated = preview_generators[i]->generate_from_path(p_item.path, Vector2(thumbnail_size, thumbnail_size));
}
+ r_texture = generated;
+ if (r_texture.is_valid() && preview_generators[i]->should_generate_small_preview()) {
+ int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retreive the default icon size
+ small_thumbnail_size *= EDSCALE;
+
+ Ref<Image> small_image = r_texture->get_data();
+ small_image->resize(small_thumbnail_size, small_thumbnail_size, Image::INTERPOLATE_CUBIC);
+ r_small_texture.instance();
+ r_small_texture->create_from_image(small_image);
+ }
break;
}
if (!p_item.resource.is_valid()) {
// cache the preview in case it's a resource on disk
- if (generated.is_valid()) {
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
+ if (r_texture.is_valid()) {
//wow it generated a preview... save cache
- ResourceSaver::save(cache_base + ".png", generated);
+ bool has_small_texture = r_small_texture.is_valid();
+ ResourceSaver::save(cache_base + ".png", r_texture);
+ if (has_small_texture) {
+ ResourceSaver::save(cache_base + "_small.png", r_small_texture);
+ }
FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
f->store_line(itos(thumbnail_size));
+ f->store_line(itos(has_small_texture));
f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
f->store_line(FileAccess::get_md5(p_item.path));
memdelete(f);
}
}
-
- return generated;
}
void EditorResourcePreview::_thread() {
@@ -177,7 +204,7 @@ void EditorResourcePreview::_thread() {
path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below)
}
- _preview_ready(path, cache[item.path].preview, item.id, item.function, item.userdata);
+ _preview_ready(path, cache[item.path].preview, cache[item.path].small_preview, item.id, item.function, item.userdata);
preview_mutex->unlock();
} else {
@@ -185,15 +212,17 @@ void EditorResourcePreview::_thread() {
preview_mutex->unlock();
Ref<ImageTexture> texture;
+ Ref<ImageTexture> small_texture;
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE;
if (item.resource.is_valid()) {
- texture = _generate_preview(item, String());
+ _generate_preview(texture, small_texture, item, String());
+
//adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred
- _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, item.id, item.function, item.userdata);
+ _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, small_texture, item.id, item.function, item.userdata);
} else {
@@ -207,12 +236,13 @@ void EditorResourcePreview::_thread() {
FileAccess *f = FileAccess::open(file, FileAccess::READ);
if (!f) {
- //generate
- texture = _generate_preview(item, cache_base);
+ // No cache found, generate
+ _generate_preview(texture, small_texture, item, cache_base);
} else {
uint64_t modtime = FileAccess::get_modified_time(item.path);
int tsize = f->get_line().to_int64();
+ bool has_small_texture = f->get_line().to_int();
uint64_t last_modtime = f->get_line().to_int64();
bool cache_valid = true;
@@ -236,6 +266,7 @@ void EditorResourcePreview::_thread() {
f = FileAccess::open(file, FileAccess::WRITE);
f->store_line(itos(modtime));
+ f->store_line(itos(has_small_texture));
f->store_line(md5);
memdelete(f);
}
@@ -243,12 +274,12 @@ void EditorResourcePreview::_thread() {
memdelete(f);
}
- //cache_valid = false;
-
if (cache_valid) {
Ref<Image> img;
img.instance();
+ Ref<Image> small_img;
+ small_img.instance();
if (img->load(cache_base + ".png") != OK) {
cache_valid = false;
@@ -256,16 +287,24 @@ void EditorResourcePreview::_thread() {
texture.instance();
texture->create_from_image(img, Texture::FLAG_FILTER);
+
+ if (has_small_texture) {
+ if (small_img->load(cache_base + "_small.png") != OK) {
+ cache_valid = false;
+ } else {
+ small_texture.instance();
+ small_texture->create_from_image(small_img, Texture::FLAG_FILTER);
+ }
+ }
}
}
if (!cache_valid) {
- texture = _generate_preview(item, cache_base);
+ _generate_preview(texture, small_texture, item, cache_base);
}
}
-
- _preview_ready(item.path, texture, item.id, item.function, item.userdata);
+ _preview_ready(item.path, texture, small_texture, item.id, item.function, item.userdata);
}
}
@@ -287,7 +326,7 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p
if (cache.has(path_id) && cache[path_id].last_hash == p_res->hash_edited_version()) {
cache[path_id].order = order++;
- p_receiver->call_deferred(p_receiver_func, path_id, cache[path_id].preview, p_userdata);
+ p_receiver->call_deferred(p_receiver_func, path_id, cache[path_id].preview, cache[path_id].small_preview, p_userdata);
preview_mutex->unlock();
return;
}
@@ -312,7 +351,7 @@ void EditorResourcePreview::queue_resource_preview(const String &p_path, Object
preview_mutex->lock();
if (cache.has(p_path)) {
cache[p_path].order = order++;
- p_receiver->call_deferred(p_receiver_func, p_path, cache[p_path].preview, p_userdata);
+ p_receiver->call_deferred(p_receiver_func, p_path, cache[p_path].preview, cache[p_path].small_preview, p_userdata);
preview_mutex->unlock();
return;
}
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index 434b26e901..a3417cdf60 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -63,8 +63,10 @@ protected:
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
- virtual Ref<Texture> generate_from_path(const String &p_path) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
+ virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const;
+
+ virtual bool should_generate_small_preview() const;
EditorResourcePreviewGenerator();
};
@@ -92,6 +94,7 @@ class EditorResourcePreview : public Node {
struct Item {
Ref<Texture> preview;
+ Ref<Texture> small_preview;
int order;
uint32_t last_hash;
uint64_t modified_time;
@@ -101,8 +104,8 @@ class EditorResourcePreview : public Node {
Map<String, Item> cache;
- void _preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud);
- Ref<Texture> _generate_preview(const QueueItem &p_item, const String &cache_base);
+ void _preview_ready(const String &p_str, const Ref<Texture> &p_texture, const Ref<Texture> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud);
+ void _generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base);
static void _thread_func(void *ud);
void _thread();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 3e959731fc..f778c733d8 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -511,17 +511,17 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("filesystem/file_dialog/show_hidden_files", false);
_initial_set("filesystem/file_dialog/display_mode", 0);
hints["filesystem/file_dialog/display_mode"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
+
_initial_set("filesystem/file_dialog/thumbnail_size", 64);
hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
- _initial_set("docks/filesystem/disable_split", false);
- _initial_set("docks/filesystem/split_mode_minimum_height", 600);
_initial_set("docks/filesystem/display_mode", 0);
- hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
+ hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Tree only, Split");
+ _initial_set("docks/filesystem/split_mode_minimum_height", 600);
_initial_set("docks/filesystem/thumbnail_size", 64);
hints["docks/filesystem/thumbnail_size"] = PropertyInfo(Variant::INT, "docks/filesystem/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
- _initial_set("docks/filesystem/display_mode", 0);
- hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
+ _initial_set("docks/filesystem/files_display_mode", 0);
+ hints["docks/filesystem/files_display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/files_display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
_initial_set("docks/filesystem/always_show_folders", true);
_initial_set("editors/animation/autorename_animation_tracks", true);
@@ -1152,20 +1152,20 @@ Variant EditorSettings::get_project_metadata(const String &p_section, const Stri
return cf->get_value(p_section, p_key, p_default);
}
-void EditorSettings::set_favorite_dirs(const Vector<String> &p_favorites_dirs) {
+void EditorSettings::set_favorites(const Vector<String> &p_favorites) {
- favorite_dirs = p_favorites_dirs;
- FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::WRITE);
+ favorites = p_favorites;
+ FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorites"), FileAccess::WRITE);
if (f) {
- for (int i = 0; i < favorite_dirs.size(); i++)
- f->store_line(favorite_dirs[i]);
+ for (int i = 0; i < favorites.size(); i++)
+ f->store_line(favorites[i]);
memdelete(f);
}
}
-Vector<String> EditorSettings::get_favorite_dirs() const {
+Vector<String> EditorSettings::get_favorites() const {
- return favorite_dirs;
+ return favorites;
}
void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
@@ -1186,11 +1186,11 @@ Vector<String> EditorSettings::get_recent_dirs() const {
void EditorSettings::load_favorites() {
- FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::READ);
+ FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorites"), FileAccess::READ);
if (f) {
String line = f->get_line().strip_edges();
while (line != "") {
- favorite_dirs.push_back(line);
+ favorites.push_back(line);
line = f->get_line().strip_edges();
}
memdelete(f);
@@ -1471,8 +1471,8 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata);
ClassDB::bind_method(D_METHOD("get_project_metadata", "section", "key", "default"), &EditorSettings::get_project_metadata, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs);
- ClassDB::bind_method(D_METHOD("get_favorite_dirs"), &EditorSettings::get_favorite_dirs);
+ ClassDB::bind_method(D_METHOD("set_favorites", "dirs"), &EditorSettings::set_favorites);
+ ClassDB::bind_method(D_METHOD("get_favorites"), &EditorSettings::get_favorites);
ClassDB::bind_method(D_METHOD("set_recent_dirs", "dirs"), &EditorSettings::set_recent_dirs);
ClassDB::bind_method(D_METHOD("get_recent_dirs"), &EditorSettings::get_recent_dirs);
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 8165c36e67..7b0de9617c 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -107,7 +107,7 @@ private:
String config_file_path;
String project_config_dir;
- Vector<String> favorite_dirs;
+ Vector<String> favorites;
Vector<String> recent_dirs;
bool save_changed_setting;
@@ -173,8 +173,8 @@ public:
void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const;
- void set_favorite_dirs(const Vector<String> &p_favorites_dirs);
- Vector<String> get_favorite_dirs() const;
+ void set_favorites(const Vector<String> &p_favorites);
+ Vector<String> get_favorites() const;
void set_recent_dirs(const Vector<String> &p_recent_dirs);
Vector<String> get_recent_dirs() const;
void load_favorites();
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 3a55966e7b..bd1d355fb3 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -40,27 +40,38 @@
#include "editor_settings.h"
#include "scene/main/viewport.h"
+Ref<Texture> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx) {
+ Ref<Texture> file_icon;
+ if (!p_dir->get_file_import_is_valid(p_idx)) {
+ file_icon = get_icon("ImportFail", "EditorIcons");
+ } else {
+ String file_type = p_dir->get_file_type(p_idx);
+ file_icon = (has_icon(file_type, "EditorIcons")) ? get_icon(file_type, "EditorIcons") : get_icon("File", "EditorIcons");
+ }
+ return file_icon;
+}
+
bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths) {
- TreeItem *item = tree->create_item(p_parent);
+ bool parent_should_expand = false;
+
+ // Create a tree item for the subdirectory
+ TreeItem *subdirectory_item = tree->create_item(p_parent);
String dname = p_dir->get_name();
if (dname == "")
dname = "res://";
- item->set_text(0, dname);
- item->set_icon(0, get_icon("Folder", "EditorIcons"));
- item->set_selectable(0, true);
+ subdirectory_item->set_text(0, dname);
+ subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons"));
+ subdirectory_item->set_selectable(0, true);
String lpath = p_dir->get_path();
- if (lpath != "res://" && lpath.ends_with("/")) {
- lpath = lpath.substr(0, lpath.length() - 1);
- }
- item->set_metadata(0, lpath);
- if (lpath == path) {
- item->select(0);
+ subdirectory_item->set_metadata(0, lpath);
+ if (path == lpath || ((display_mode_setting == DISPLAY_MODE_SETTING_SPLIT) && path.get_base_dir() == lpath)) {
+ subdirectory_item->select(0);
}
if ((path.begins_with(lpath) && path != lpath)) {
- item->set_collapsed(false);
+ subdirectory_item->set_collapsed(false);
} else {
bool is_collapsed = true;
for (int i = 0; i < uncollapsed_paths.size(); i++) {
@@ -69,23 +80,65 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
break;
}
}
- item->set_collapsed(is_collapsed);
+ subdirectory_item->set_collapsed(is_collapsed);
+ }
+ if (searched_string.length() > 0 && dname.to_lower().find(searched_string) >= 0) {
+ parent_should_expand = true;
}
+ // Create items for all subdirectories
for (int i = 0; i < p_dir->get_subdir_count(); i++)
- _create_tree(item, p_dir->get_subdir(i), uncollapsed_paths);
+ parent_should_expand = (_create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths) || parent_should_expand);
- return true;
-}
+ // Create all items for the files in the subdirectory
+ if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) {
+ for (int i = 0; i < p_dir->get_file_count(); i++) {
+ String file_name = p_dir->get_file(i);
+
+ if (searched_string.length() > 0) {
+ if (file_name.to_lower().find(searched_string) < 0) {
+ // The seached string is not in the file name, we skip it
+ continue;
+ } else {
+ // We expand all parents
+ parent_should_expand = true;
+ }
+ }
-void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_root) {
+ TreeItem *file_item = tree->create_item(subdirectory_item);
+ file_item->set_text(0, file_name);
+ file_item->set_icon(0, _get_tree_item_icon(p_dir, i));
+ String file_metadata = lpath.plus_file(file_name);
+ file_item->set_metadata(0, file_metadata);
+ if (path == file_metadata) {
+ file_item->select(0);
+ file_item->set_as_cursor(0);
+ }
+ Array udata;
+ udata.push_back(tree_update_id);
+ udata.push_back(file_item);
+ EditorResourcePreview::get_singleton()->queue_resource_preview(file_metadata, this, "_tree_thumbnail_done", udata);
+ }
+ }
- Vector<String> uncollapsed_paths;
- if (keep_collapse_state) {
- TreeItem *root = tree->get_root();
- if (root) {
- TreeItem *resTree = root->get_children()->get_next();
+ if (searched_string.length() > 0) {
+ if (parent_should_expand) {
+ subdirectory_item->set_collapsed(false);
+ } else if (dname != "res://") {
+ subdirectory_item->get_parent()->remove_child(subdirectory_item);
+ }
+ }
+
+ return parent_should_expand;
+}
+Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
+ // Register currently collapsed paths
+ Vector<String> uncollapsed_paths;
+ TreeItem *root = tree->get_root();
+ if (root) {
+ TreeItem *resTree = root->get_children()->get_next();
+ if (resTree) {
Vector<TreeItem *> needs_check;
needs_check.push_back(resTree);
@@ -102,84 +155,123 @@ void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_ro
}
}
}
+ return uncollapsed_paths;
+}
+
+void FileSystemDock::_update_tree(const Vector<String> p_uncollapsed_paths, bool p_uncollapse_root) {
+ // Recreate the tree
tree->clear();
+ tree_update_id++;
updating_tree = true;
-
TreeItem *root = tree->create_item();
+
+ // Handles the favorites
TreeItem *favorites = tree->create_item(root);
favorites->set_icon(0, get_icon("Favorites", "EditorIcons"));
favorites->set_text(0, TTR("Favorites:"));
favorites->set_selectable(0, false);
- Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorite_dirs();
- String res_path = "res://";
- Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons");
+ Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < favorite_paths.size(); i++) {
String fave = favorite_paths[i];
- if (!fave.begins_with(res_path))
+ if (!fave.begins_with("res://"))
+ continue;
+ if (display_mode_setting == DISPLAY_MODE_SETTING_SPLIT && !fave.ends_with("/"))
continue;
- TreeItem *ti = tree->create_item(favorites);
- if (fave == res_path)
- ti->set_text(0, "/");
- else
- ti->set_text(0, fave.get_file());
- ti->set_icon(0, folder_icon);
- ti->set_selectable(0, true);
- ti->set_metadata(0, fave);
+ Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons");
+
+ String text;
+ Ref<Texture> icon;
+ if (fave == "res://") {
+ text = "/";
+ icon = folder_icon;
+ } else if (fave.ends_with("/")) {
+ text = fave.substr(0, fave.length() - 1).get_file();
+ icon = folder_icon;
+ } else {
+ text = fave.get_file();
+ int index;
+ EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->find_file(fave, &index);
+ if (dir) {
+ icon = _get_tree_item_icon(dir, index);
+ } else {
+ icon = get_icon("File", "EditorIcons");
+ }
+ }
+
+ if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) {
+ TreeItem *ti = tree->create_item(favorites);
+ ti->set_text(0, text);
+ ti->set_icon(0, icon);
+ ti->set_tooltip(0, fave);
+ ti->set_selectable(0, true);
+ ti->set_metadata(0, fave);
+ }
}
+ Vector<String> uncollapsed_paths = p_uncollapsed_paths;
if (p_uncollapse_root) {
uncollapsed_paths.push_back("res://");
}
+ // Create the remaining of the tree
_create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths);
tree->ensure_cursor_is_visible();
updating_tree = false;
}
void FileSystemDock::_update_display_mode() {
-
- bool disable_split = bool(EditorSettings::get_singleton()->get("docks/filesystem/disable_split"));
bool compact_mode = get_size().height < int(EditorSettings::get_singleton()->get("docks/filesystem/split_mode_minimum_height"));
- DisplayMode new_mode;
- if (disable_split || compact_mode) {
- new_mode = file_list_view ? DISPLAY_FILE_LIST_ONLY : DISPLAY_TREE_ONLY;
+
+ // Compute the new display mode
+ DisplayMode new_display_mode;
+ if ((display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) || compact_mode) {
+ new_display_mode = file_list_view ? DISPLAY_MODE_FILE_LIST_ONLY : DISPLAY_MODE_TREE_ONLY;
} else {
- new_mode = DISPLAY_SPLIT;
+ new_display_mode = DISPLAY_MODE_SPLIT;
}
- if (new_mode != display_mode) {
- switch (new_mode) {
- case DISPLAY_TREE_ONLY:
+ if (new_display_mode != display_mode || old_display_mode_setting != display_mode_setting) {
+ display_mode = new_display_mode;
+ old_display_mode_setting = display_mode_setting;
+ button_toggle_display_mode->set_pressed(display_mode_setting == DISPLAY_MODE_SETTING_SPLIT ? true : false);
+ switch (display_mode) {
+ case DISPLAY_MODE_TREE_ONLY:
tree->show();
tree->set_v_size_flags(SIZE_EXPAND_FILL);
- _update_tree(true);
+ if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) {
+ tree_search_box->show();
+ } else {
+ tree_search_box->hide();
+ }
+ _update_tree(_compute_uncollapsed_paths());
file_list_vb->hide();
break;
- case DISPLAY_FILE_LIST_ONLY:
+ case DISPLAY_MODE_FILE_LIST_ONLY:
tree->hide();
+ tree_search_box->hide();
button_tree->show();
file_list_vb->show();
_update_files(true);
break;
- case DISPLAY_SPLIT:
+ case DISPLAY_MODE_SPLIT:
tree->show();
tree->set_v_size_flags(SIZE_EXPAND_FILL);
button_tree->hide();
tree->ensure_cursor_is_visible();
- _update_tree(true);
+ tree_search_box->hide();
+ _update_tree(_compute_uncollapsed_paths());
file_list_vb->show();
_update_files(true);
break;
}
- display_mode = new_mode;
}
}
@@ -201,34 +293,35 @@ void FileSystemDock::_notification(int p_what) {
String ei = "EditorIcons";
button_reload->set_icon(get_icon("Reload", ei));
- button_favorite->set_icon(get_icon("Favorites", ei));
- //button_instance->set_icon(get_icon("Add", ei));
- //button_open->set_icon(get_icon("Folder", ei));
+ button_toggle_display_mode->set_icon(get_icon("Panels2", ei));
button_tree->set_icon(get_icon("Filesystem", ei));
_update_file_list_display_mode_button();
button_file_list_display_mode->connect("pressed", this, "_change_file_display");
- //file_options->set_icon( get_icon("Tools","ei"));
- files->connect("item_activated", this, "_select_file");
+
+ files->connect("item_activated", this, "_file_list_activate_file");
button_hist_next->connect("pressed", this, "_fw_history");
button_hist_prev->connect("pressed", this, "_bw_history");
- search_box->set_right_icon(get_icon("Search", ei));
- search_box->set_clear_button_enabled(true);
+ tree_search_box->set_right_icon(get_icon("Search", ei));
+ tree_search_box->set_clear_button_enabled(true);
+ file_list_search_box->set_right_icon(get_icon("Search", ei));
+ file_list_search_box->set_clear_button_enabled(true);
button_hist_next->set_icon(get_icon("Forward", ei));
button_hist_prev->set_icon(get_icon("Back", ei));
- button_show->set_icon(get_icon("GuiVisibilityVisible", "EditorIcons"));
- file_options->connect("id_pressed", this, "_file_option");
- folder_options->connect("id_pressed", this, "_folder_option");
+ file_list_popup->connect("id_pressed", this, "_file_list_rmb_option");
+ tree_popup->connect("id_pressed", this, "_tree_rmb_option");
button_tree->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED);
current_path->connect("text_entered", this, "navigate_to_path");
_update_display_mode();
+ always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
+
if (EditorFileSystem::get_singleton()->is_scanning()) {
_set_scanning_mode();
} else {
- _update_tree(false, true);
+ _update_tree(Vector<String>(), true);
}
} break;
@@ -245,7 +338,7 @@ void FileSystemDock::_notification(int p_what) {
Dictionary dd = get_viewport()->gui_get_drag_data();
if (tree->is_visible_in_tree() && dd.has("type")) {
if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) {
- tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
+ tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN);
} else if ((String(dd["type"]) == "favorite")) {
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
}
@@ -261,20 +354,37 @@ void FileSystemDock::_notification(int p_what) {
// Update icons
String ei = "EditorIcons";
button_reload->set_icon(get_icon("Reload", ei));
- button_favorite->set_icon(get_icon("Favorites", ei));
+ button_toggle_display_mode->set_icon(get_icon("Panels2", ei));
button_tree->set_icon(get_icon("Filesystem", ei));
button_hist_next->set_icon(get_icon("Forward", ei));
button_hist_prev->set_icon(get_icon("Back", ei));
- search_box->set_right_icon(get_icon("Search", ei));
- search_box->set_clear_button_enabled(true);
+ tree_search_box->set_right_icon(get_icon("Search", ei));
+ tree_search_box->set_clear_button_enabled(true);
+ file_list_search_box->set_right_icon(get_icon("Search", ei));
+ file_list_search_box->set_clear_button_enabled(true);
- // Change size mode
- int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"));
+ bool should_update_files = false;
+
+ // Update file list display mode
+ int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/files_display_mode"));
if (new_file_list_mode != file_list_display_mode) {
set_file_list_display_mode(new_file_list_mode);
- } else {
_update_file_list_display_mode_button();
+ should_update_files = true;
+ }
+
+ // Update display of files in tree
+ display_mode_setting = DisplayModeSetting(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
+
+ // Update allways showfolders
+ bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
+ if (new_always_show_folders != always_show_folders) {
+ always_show_folders = new_always_show_folders;
+ should_update_files = true;
+ }
+
+ if (should_update_files) {
_update_files(true);
}
@@ -285,74 +395,33 @@ void FileSystemDock::_notification(int p_what) {
}
}
-void FileSystemDock::_dir_selected() {
+void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_selected) {
+
+ // Return if we don't select something new
+ if (!p_selected)
+ return;
+ // Tree item selected
TreeItem *sel = tree->get_selected();
if (!sel)
return;
path = sel->get_metadata(0);
- bool found = false;
- Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
- for (int i = 0; i < favorites.size(); i++) {
-
- if (favorites[i] == path) {
- found = true;
- break;
- }
- }
-
- button_favorite->set_pressed(found);
+ // Set the current path
current_path->set_text(path);
_push_to_history();
- if (display_mode == DISPLAY_SPLIT) {
+ // Update the file list
+ if (!updating_tree && display_mode == DISPLAY_MODE_SPLIT) {
_update_files(false);
}
}
-void FileSystemDock::_favorites_pressed() {
-
- TreeItem *sel = tree->get_selected();
- if (!sel)
- return;
- path = sel->get_metadata(0);
-
- int idx = -1;
- Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
- for (int i = 0; i < favorites.size(); i++) {
-
- if (favorites[i] == path) {
- idx = i;
- break;
- }
- }
-
- if (idx == -1) {
- favorites.push_back(path);
- } else {
- favorites.remove(idx);
- }
- EditorSettings::get_singleton()->set_favorite_dirs(favorites);
- _update_tree(true);
-}
-
-void FileSystemDock::_show_current_scene_file() {
-
- int index = EditorNode::get_editor_data().get_edited_scene();
- String path = EditorNode::get_editor_data().get_scene_path(index);
- if (path != String()) {
- navigate_to_path(path);
- }
-}
-
String FileSystemDock::get_selected_path() const {
-
- TreeItem *sel = tree->get_selected();
- if (!sel)
- return "";
-
- return sel->get_metadata(0);
+ if (path.ends_with("/"))
+ return path;
+ else
+ return path.get_base_dir();
}
String FileSystemDock::get_current_path() const {
@@ -361,14 +430,17 @@ String FileSystemDock::get_current_path() const {
}
void FileSystemDock::navigate_to_path(const String &p_path) {
+
+ String target_path = p_path;
// If the path is a file, do not only go to the directory in the tree, also select the file in the file list.
- String file_name = "";
+ if (target_path.ends_with("/")) {
+ target_path = target_path.substr(0, target_path.length() - 1);
+ }
DirAccess *dirAccess = DirAccess::open("res://");
if (dirAccess->file_exists(p_path)) {
- path = p_path.get_base_dir();
- file_name = p_path.get_file();
+ path = target_path;
} else if (dirAccess->dir_exists(p_path)) {
- path = p_path;
+ path = target_path + "/";
} else {
ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path));
ERR_FAIL();
@@ -377,13 +449,20 @@ void FileSystemDock::navigate_to_path(const String &p_path) {
current_path->set_text(path);
_push_to_history();
- if (display_mode == DISPLAY_SPLIT) {
- _update_tree(true);
+ if (display_mode == DISPLAY_MODE_SPLIT) {
+ _update_tree(_compute_uncollapsed_paths());
_update_files(false);
- } else {
- _go_to_file_list();
+ } else if (display_mode == DISPLAY_MODE_TREE_ONLY) {
+ if (path.ends_with("/")) {
+ _go_to_file_list();
+ } else {
+ _update_tree(_compute_uncollapsed_paths());
+ }
+ } else { // DISPLAY_MODE_FILE_LIST_ONLY
+ _update_files(true);
}
+ String file_name = p_path.get_file();
if (!file_name.empty()) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->get_item_text(i) == file_name) {
@@ -395,10 +474,9 @@ void FileSystemDock::navigate_to_path(const String &p_path) {
}
}
-void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) {
+void FileSystemDock::_file_list_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
if ((file_list_vb->is_visible_in_tree() || path == p_path.get_base_dir()) && p_preview.is_valid()) {
-
Array uarr = p_udata;
int idx = uarr[0];
String file = uarr[1];
@@ -407,6 +485,27 @@ void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p
}
}
+void FileSystemDock::_tree_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
+ if (p_small_preview.is_valid()) {
+ Array uarr = p_udata;
+ if (tree_update_id == (int)uarr[0]) {
+ TreeItem *file_item = Object::cast_to<TreeItem>(uarr[1]);
+ if (file_item) {
+ file_item->set_icon(0, p_small_preview);
+
+ // Update the favorite icon if needed
+ TreeItem *favorite = tree->get_root()->get_children()->get_children();
+ while (favorite) {
+ if (favorite->get_metadata(0) == file_item->get_metadata(0)) {
+ favorite->set_icon(0, p_small_preview);
+ }
+ favorite = favorite->get_next();
+ }
+ }
+ }
+ }
+}
+
void FileSystemDock::_update_file_list_display_mode_button() {
if (button_file_list_display_mode->is_pressed()) {
@@ -424,7 +523,7 @@ void FileSystemDock::_change_file_display() {
_update_file_list_display_mode_button();
- EditorSettings::get_singleton()->set("docks/filesystem/display_mode", file_list_display_mode);
+ EditorSettings::get_singleton()->set("docks/filesystem/files_display_mode", file_list_display_mode);
_update_files(true);
}
@@ -438,12 +537,10 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
_search(p_path->get_subdir(i), matches, p_max_items);
}
- String match = search_box->get_text().to_lower();
-
for (int i = 0; i < p_path->get_file_count(); i++) {
String file = p_path->get_file(i);
- if (file.to_lower().find(match) != -1) {
+ if (file.to_lower().find(searched_string) != -1) {
FileInfo fi;
fi.name = file;
@@ -461,12 +558,10 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
void FileSystemDock::_update_files(bool p_keep_selection) {
+ // Register the previously selected items
Set<String> cselection;
-
if (p_keep_selection) {
-
for (int i = 0; i < files->get_item_count(); i++) {
-
if (files->is_selected(i))
cselection.insert(files->get_item_text(i));
}
@@ -476,7 +571,17 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
current_path->set_text(path);
- EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(path);
+ String directory = path;
+ if (directory.ends_with("/") && directory != "res://") {
+ directory = directory.substr(0, directory.length() - 1);
+ }
+ String file = "";
+ EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(directory);
+ if (!efd) {
+ directory = path.get_base_dir();
+ file = path.get_file();
+ efd = EditorFileSystem::get_singleton()->get_filesystem_path(directory);
+ }
if (!efd)
return;
@@ -487,10 +592,8 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
Ref<Texture> file_thumbnail;
Ref<Texture> file_thumbnail_broken;
- bool always_show_folders = EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders");
-
bool use_thumbnails = (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS);
- bool use_folders = search_box->get_text().length() == 0 && ((display_mode == DISPLAY_FILE_LIST_ONLY || display_mode == DISPLAY_TREE_ONLY) || always_show_folders);
+ bool use_folders = searched_string.length() == 0 && ((display_mode == DISPLAY_MODE_FILE_LIST_ONLY || display_mode == DISPLAY_MODE_TREE_ONLY) || always_show_folders);
if (use_thumbnails) {
@@ -521,14 +624,15 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
if (use_folders) {
Ref<Texture> folderIcon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog");
- if (path != "res://") {
+ if (directory != "res://") {
files->add_item("..", folderIcon, true);
- String bd = path.get_base_dir();
+ String bd = directory.get_base_dir();
if (bd != "res://" && !bd.ends_with("/"))
bd += "/";
files->set_item_metadata(files->get_item_count() - 1, bd);
+ files->set_item_selectable(files->get_item_count() - 1, false);
}
for (int i = 0; i < efd->get_subdir_count(); i++) {
@@ -536,16 +640,17 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
String dname = efd->get_subdir(i)->get_name();
files->add_item(dname, folderIcon, true);
- files->set_item_metadata(files->get_item_count() - 1, path.plus_file(dname) + "/");
+ files->set_item_metadata(files->get_item_count() - 1, directory.plus_file(dname) + "/");
- if (cselection.has(dname))
+ if (cselection.has(dname)) {
files->select(files->get_item_count() - 1, false);
+ }
}
}
List<FileInfo> filelist;
- if (search_box->get_text().length() > 0) {
+ if (searched_string.length() > 0) {
_search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128);
filelist.sort();
@@ -555,7 +660,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
FileInfo fi;
fi.name = efd->get_file(i);
- fi.path = path.plus_file(fi.name);
+ fi.path = directory.plus_file(fi.name);
fi.type = efd->get_file_type(i);
fi.import_broken = !efd->get_file_import_is_valid(i);
fi.import_status = 0;
@@ -598,7 +703,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
udata.resize(2);
udata[0] = item_index;
udata[1] = fname;
- EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_thumbnail_done", udata);
+ EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_file_list_thumbnail_done", udata);
}
} else {
files->add_item(fname, type_icon, true);
@@ -609,6 +714,11 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
if (cselection.has(fname))
files->select(item_index, false);
+ if (!p_keep_selection && file != "" && fname == file) {
+ files->select(item_index, true);
+ files->ensure_current_is_visible();
+ }
+
if (finfo->sources.size()) {
for (int j = 0; j < finfo->sources.size(); j++) {
tooltip += "\nSource: " + finfo->sources[j];
@@ -618,8 +728,8 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
}
}
-void FileSystemDock::_select_file(int p_idx) {
- String fpath = files->get_item_metadata(p_idx);
+void FileSystemDock::_select_file(const String p_path) {
+ String fpath = p_path;
if (fpath.ends_with("/")) {
if (fpath != "res://") {
fpath = fpath.substr(0, fpath.length() - 1);
@@ -634,9 +744,21 @@ void FileSystemDock::_select_file(int p_idx) {
}
}
+void FileSystemDock::_tree_activate_file() {
+ TreeItem *selected = tree->get_selected();
+ if (selected) {
+ call_deferred("_select_file", selected->get_metadata(0));
+ }
+}
+
+void FileSystemDock::_file_list_activate_file(int p_idx) {
+ _select_file(files->get_item_metadata(p_idx));
+}
+
void FileSystemDock::_go_to_file_list() {
- if (display_mode == DISPLAY_TREE_ONLY) {
+ if (display_mode == DISPLAY_MODE_TREE_ONLY) {
+
file_list_view = true;
_update_display_mode();
} else {
@@ -645,6 +767,7 @@ void FileSystemDock::_go_to_file_list() {
_update_files(false);
}
}
+
void FileSystemDock::_go_to_tree() {
file_list_view = false;
@@ -655,7 +778,7 @@ void FileSystemDock::_go_to_tree() {
void FileSystemDock::_preview_invalidated(const String &p_path) {
- if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) {
+ if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && searched_string.length() == 0 && file_list_vb->is_visible_in_tree()) {
for (int i = 0; i < files->get_item_count(); i++) {
@@ -665,7 +788,7 @@ void FileSystemDock::_preview_invalidated(const String &p_path) {
udata.resize(2);
udata[0] = i;
udata[1] = files->get_item_text(i);
- EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_thumbnail_done", udata);
+ EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_file_list_thumbnail_done", udata);
break;
}
}
@@ -680,7 +803,7 @@ void FileSystemDock::_fs_changed() {
split_box->show();
if (tree->is_visible()) {
- _update_tree(true);
+ _update_tree(_compute_uncollapsed_paths());
}
if (file_list_vb->is_visible()) {
@@ -724,7 +847,7 @@ void FileSystemDock::_update_history() {
current_path->set_text(path);
if (tree->is_visible()) {
- _update_tree(true);
+ _update_tree(_compute_uncollapsed_paths());
tree->grab_focus();
tree->ensure_cursor_is_visible();
}
@@ -968,23 +1091,23 @@ void FileSystemDock::_update_project_settings_after_move(const Map<String, Strin
ProjectSettings::get_singleton()->save();
}
-void FileSystemDock::_update_favorite_dirs_list_after_move(const Map<String, String> &p_renames) const {
+void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const {
- Vector<String> favorite_dirs = EditorSettings::get_singleton()->get_favorite_dirs();
- Vector<String> new_favorite_dirs;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
+ Vector<String> new_favorites;
- for (int i = 0; i < favorite_dirs.size(); i++) {
- String old_path = favorite_dirs[i] + "/";
-
- if (p_renames.has(old_path)) {
- String new_path = p_renames[old_path];
- new_favorite_dirs.push_back(new_path.substr(0, new_path.length() - 1));
+ for (int i = 0; i < favorites.size(); i++) {
+ String old_path = favorites[i];
+ if (p_folders_renames.has(old_path)) {
+ new_favorites.push_back(p_folders_renames[old_path]);
+ } else if (p_files_renames.has(old_path)) {
+ new_favorites.push_back(p_files_renames[old_path]);
} else {
- new_favorite_dirs.push_back(favorite_dirs[i]);
+ new_favorites.push_back(old_path);
}
}
- EditorSettings::get_singleton()->set_favorite_dirs(new_favorite_dirs);
+ EditorSettings::get_singleton()->set_favorites(new_favorites);
}
void FileSystemDock::_make_dir_confirm() {
@@ -998,9 +1121,13 @@ void FileSystemDock::_make_dir_confirm() {
return;
}
- print_verbose("Making folder " + dir_name + " in " + path);
+ String directory = path;
+ if (!directory.ends_with("/")) {
+ directory = directory.get_base_dir();
+ }
+ print_verbose("Making folder " + dir_name + " in " + directory);
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- Error err = da->change_dir(path);
+ Error err = da->change_dir(directory);
if (err == OK) {
err = da->make_dir(dir_name);
}
@@ -1051,7 +1178,7 @@ void FileSystemDock::_rename_operation_confirm() {
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
- _update_favorite_dirs_list_after_move(folder_renames);
+ _update_favorites_list_after_move(file_renames, folder_renames);
//Rescan everything
print_verbose("FileSystem: calling rescan.");
@@ -1144,111 +1271,209 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
- _update_favorite_dirs_list_after_move(folder_renames);
+ _update_favorites_list_after_move(file_renames, folder_renames);
print_verbose("FileSystem: calling rescan.");
_rescan();
}
}
-void FileSystemDock::_file_option(int p_option) {
+Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
+ // Build a list of selected items with the active one at the first position
+ Vector<String> selected_strings;
+
+ TreeItem *active_selected = tree->get_selected();
+ if (active_selected) {
+ selected_strings.push_back(active_selected->get_metadata(0));
+ }
+
+ TreeItem *selected = tree->get_root();
+ selected = tree->get_next_selected(selected);
+ while (selected) {
+ if (selected != active_selected) {
+ selected_strings.push_back(selected->get_metadata(0));
+ }
+ selected = tree->get_next_selected(selected);
+ }
+
+ // Remove paths or files that are included into another
+ if (remove_self_inclusion && selected_strings.size() > 1) {
+ selected_strings.sort_custom<NaturalNoCaseComparator>();
+ String last_path = "";
+ for (int i = 0; i < selected_strings.size(); i++) {
+ if (last_path != "" && selected_strings[i].begins_with(last_path)) {
+ selected_strings.remove(i);
+ i--;
+ }
+ if (selected_strings[i].ends_with("/")) {
+ last_path = selected_strings[i];
+ }
+ }
+ }
+ return selected_strings;
+}
+
+void FileSystemDock::_tree_rmb_option(int p_option) {
+
+ Vector<String> selected_strings = _tree_get_selected();
+
+ // Execute the current option
switch (p_option) {
- case FILE_SHOW_IN_EXPLORER: {
+ case FOLDER_EXPAND_ALL:
+ case FOLDER_COLLAPSE_ALL: {
+ // Expand or collapse the folder
+ if (selected_strings.size() == 1) {
+ bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL);
+
+ Vector<TreeItem *> needs_check;
+ needs_check.push_back(tree->get_selected());
- String path = this->path;
+ while (needs_check.size()) {
+ needs_check[0]->set_collapsed(is_collapsed);
- // first try to grab directory from selected file, so that it works for searched files
- int idx = files->get_current();
+ TreeItem *child = needs_check[0]->get_children();
+ while (child) {
+ needs_check.push_back(child);
+ child = child->get_next();
+ }
- if (idx >= 0 && idx < files->get_item_count()) {
- path = files->get_item_metadata(idx);
- path = path.get_base_dir();
+ needs_check.remove(0);
+ }
}
+ } break;
+ default: {
+ _file_option(p_option, selected_strings);
+ } break;
+ }
+}
- path = ProjectSettings::get_singleton()->globalize_path(path);
- OS::get_singleton()->shell_open(String("file://") + path);
+void FileSystemDock::_file_list_rmb_option(int p_option) {
+ Vector<int> selected_id = files->get_selected_items();
+ Vector<String> selected;
+ for (int i = 0; i < selected_id.size(); i++) {
+ selected.push_back(files->get_item_metadata(selected_id[i]));
+ }
+ _file_option(p_option, selected);
+}
+
+void FileSystemDock::_file_option(int p_option, const Vector<String> p_selected) {
+ // The first one should be the active item
+
+ switch (p_option) {
+ case FILE_SHOW_IN_EXPLORER: {
+ // Show the file / folder in the OS explorer
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
+ }
+ String dir = ProjectSettings::get_singleton()->globalize_path(fpath);
+ OS::get_singleton()->shell_open(String("file://") + dir);
} break;
+
case FILE_OPEN: {
- for (int i = 0; i < files->get_item_count(); i++) {
- if (files->is_selected(i)) {
- _select_file(i);
- }
+ // Open the file
+ for (int i = 0; i < p_selected.size(); i++) {
+ _select_file(p_selected[i]);
}
} break;
- case FILE_INSTANCE: {
+ case FILE_INSTANCE: {
+ // Instance all selected scenes
Vector<String> paths;
-
- for (int i = 0; i < files->get_item_count(); i++) {
- if (!files->is_selected(i))
- continue;
- String fpath = files->get_item_metadata(i);
+ for (int i = 0; i < p_selected.size(); i++) {
+ String fpath = p_selected[i];
if (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene") {
paths.push_back(fpath);
}
}
-
if (!paths.empty()) {
emit_signal("instance", paths);
}
} break;
- case FILE_DEPENDENCIES: {
- int idx = files->get_current();
- if (idx < 0 || idx >= files->get_item_count())
- break;
- String fpath = files->get_item_metadata(idx);
- deps_editor->edit(fpath);
+ case FILE_ADD_FAVORITE: {
+ // Add the files from favorites
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
+ for (int i = 0; i < p_selected.size(); i++) {
+ if (favorites.find(p_selected[i]) == -1) {
+ favorites.push_back(p_selected[i]);
+ }
+ }
+ EditorSettings::get_singleton()->set_favorites(favorites);
+ _update_tree(_compute_uncollapsed_paths());
} break;
- case FILE_OWNERS: {
- int idx = files->get_current();
- if (idx < 0 || idx >= files->get_item_count())
- break;
- String fpath = files->get_item_metadata(idx);
- owners_editor->show(fpath);
+ case FILE_REMOVE_FAVORITE: {
+ // Remove the files from favorites
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
+ for (int i = 0; i < p_selected.size(); i++) {
+ favorites.erase(p_selected[i]);
+ }
+ EditorSettings::get_singleton()->set_favorites(favorites);
+ _update_tree(_compute_uncollapsed_paths());
} break;
+
+ case FILE_DEPENDENCIES: {
+ // Checkout the file dependencies
+ if (!p_selected.empty()) {
+ String fpath = p_selected[0];
+ deps_editor->edit(fpath);
+ }
+ } break;
+
+ case FILE_OWNERS: {
+ // Checkout the file owners
+ if (!p_selected.empty()) {
+ String fpath = p_selected[0];
+ owners_editor->show(fpath);
+ }
+ } break;
+
case FILE_MOVE: {
+ // Move the files to a given location
to_move.clear();
- for (int i = 0; i < files->get_item_count(); i++) {
- if (!files->is_selected(i))
- continue;
-
- String fpath = files->get_item_metadata(i);
- to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/")));
+ for (int i = 0; i < p_selected.size(); i++) {
+ String fpath = p_selected[i];
+ if (fpath != "res://") {
+ to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/")));
+ }
}
if (to_move.size() > 0) {
move_dialog->popup_centered_ratio();
}
} break;
- case FILE_RENAME: {
- int idx = files->get_current();
- if (idx < 0 || idx >= files->get_item_count())
- break;
- to_rename.path = files->get_item_metadata(idx);
- to_rename.is_file = !to_rename.path.ends_with("/");
- if (to_rename.is_file) {
- String name = to_rename.path.get_file();
- rename_dialog->set_title(TTR("Renaming file:") + " " + name);
- rename_dialog_text->set_text(name);
- rename_dialog_text->select(0, name.find_last("."));
- } else {
- String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file();
- rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
- rename_dialog_text->set_text(name);
- rename_dialog_text->select(0, name.length());
+ case FILE_RENAME: {
+ // Rename the active file
+ if (!p_selected.empty()) {
+ to_rename.path = p_selected[0];
+ if (to_rename.path != "res://") {
+ to_rename.is_file = !to_rename.path.ends_with("/");
+ if (to_rename.is_file) {
+ String name = to_rename.path.get_file();
+ rename_dialog->set_title(TTR("Renaming file:") + " " + name);
+ rename_dialog_text->set_text(name);
+ rename_dialog_text->select(0, name.find_last("."));
+ } else {
+ String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file();
+ rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
+ rename_dialog_text->set_text(name);
+ rename_dialog_text->select(0, name.length());
+ }
+ rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ rename_dialog_text->grab_focus();
+ }
}
- rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
- rename_dialog_text->grab_focus();
} break;
+
case FILE_REMOVE: {
+ // Remove the selected files
Vector<String> remove_files;
Vector<String> remove_folders;
- for (int i = 0; i < files->get_item_count(); i++) {
- String fpath = files->get_item_metadata(i);
- if (files->is_selected(i) && fpath != "res://") {
+ for (int i = 0; i < p_selected.size(); i++) {
+ String fpath = p_selected[i];
+ if (fpath != "res://") {
if (fpath.ends_with("/")) {
remove_folders.push_back(fpath);
} else {
@@ -1259,166 +1484,77 @@ void FileSystemDock::_file_option(int p_option) {
if (remove_files.size() + remove_folders.size() > 0) {
remove_dialog->show(remove_folders, remove_files);
- //1) find if used
- //2) warn
}
} break;
- case FILE_DUPLICATE: {
- int idx = files->get_current();
- if (idx < 0 || idx >= files->get_item_count())
- break;
- to_duplicate.path = files->get_item_metadata(idx);
- to_duplicate.is_file = !to_duplicate.path.ends_with("/");
- if (to_duplicate.is_file) {
- String name = to_duplicate.path.get_file();
- duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name);
- duplicate_dialog_text->set_text(name);
- duplicate_dialog_text->select(0, name.find_last("."));
- } else {
- String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file();
- duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name);
- duplicate_dialog_text->set_text(name);
- duplicate_dialog_text->select(0, name.length());
+ case FILE_DUPLICATE: {
+ // Duplicate the selected files
+ for (int i = 0; i < p_selected.size(); i++) {
+ to_duplicate.path = p_selected[i];
+ to_duplicate.is_file = !to_duplicate.path.ends_with("/");
+ if (to_duplicate.is_file) {
+ String name = to_duplicate.path.get_file();
+ duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name);
+ duplicate_dialog_text->set_text(name);
+ duplicate_dialog_text->select(0, name.find_last("."));
+ } else {
+ String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file();
+ duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name);
+ duplicate_dialog_text->set_text(name);
+ duplicate_dialog_text->select(0, name.length());
+ }
+ duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ duplicate_dialog_text->grab_focus();
}
- duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
- duplicate_dialog_text->grab_focus();
} break;
+
case FILE_INFO: {
} break;
- case FILE_REIMPORT: {
+ case FILE_REIMPORT: {
+ // Reimport all selected files
Vector<String> reimport;
- for (int i = 0; i < files->get_item_count(); i++) {
-
- if (!files->is_selected(i))
- continue;
-
- String fpath = files->get_item_metadata(i);
- reimport.push_back(fpath);
+ for (int i = 0; i < p_selected.size(); i++) {
+ reimport.push_back(p_selected[i]);
}
ERR_FAIL_COND(reimport.size() == 0);
- /*
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(reimport[0]);
- ERR_FAIL_COND(!rimd.is_valid());
- String editor=rimd->get_editor();
-
- if (editor.begins_with("texture_")) { //compatibility fix for old texture format
- editor="texture";
- }
-
- Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor);
- ERR_FAIL_COND(!rimp.is_valid());
-
- if (reimport.size()==1) {
- rimp->import_dialog(reimport[0]);
- } else {
- rimp->reimport_multiple_files(reimport);
-
- }
- */
} break;
+
case FILE_NEW_FOLDER: {
+ // Create a new folder
make_dir_dialog_text->set_text("new folder");
make_dir_dialog_text->select_all();
make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
make_dir_dialog_text->grab_focus();
} break;
+
case FILE_NEW_SCRIPT: {
- String tarDir = path;
- if (tarDir != "res://" && !tarDir.ends_with("/")) {
- tarDir += "/";
+ // Create a new script
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
}
-
- make_script_dialog_text->config("Node", tarDir + "new_script.gd");
+ make_script_dialog_text->config("Node", fpath + "new_script.gd");
make_script_dialog_text->popup_centered(Size2(300, 300) * EDSCALE);
} break;
+
case FILE_COPY_PATH: {
- int idx = files->get_current();
- if (idx < 0 || idx >= files->get_item_count())
- break;
- String fpath = files->get_item_metadata(idx);
- OS::get_singleton()->set_clipboard(fpath);
+ // Copy the file path
+ if (!p_selected.empty()) {
+ String fpath = p_selected[0];
+ OS::get_singleton()->set_clipboard(fpath);
+ }
} break;
+
case FILE_NEW_RESOURCE: {
+ // Create a new resource
new_resource_dialog->popup_create(true);
} break;
}
}
-void FileSystemDock::_folder_option(int p_option) {
-
- TreeItem *selected = tree->get_selected();
-
- switch (p_option) {
- case FOLDER_EXPAND_ALL:
- case FOLDER_COLLAPSE_ALL: {
- bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL);
- Vector<TreeItem *> needs_check;
- needs_check.push_back(selected);
-
- while (needs_check.size()) {
- needs_check[0]->set_collapsed(is_collapsed);
-
- TreeItem *child = needs_check[0]->get_children();
- while (child) {
- needs_check.push_back(child);
- child = child->get_next();
- }
-
- needs_check.remove(0);
- }
- } break;
- case FOLDER_MOVE: {
- to_move.clear();
- String fpath = selected->get_metadata(tree->get_selected_column());
- if (fpath != "res://") {
- fpath = fpath.ends_with("/") ? fpath.substr(0, fpath.length() - 1) : fpath;
- to_move.push_back(FileOrFolder(fpath, false));
- move_dialog->popup_centered_ratio();
- }
- } break;
- case FOLDER_RENAME: {
- to_rename.path = selected->get_metadata(tree->get_selected_column());
- to_rename.is_file = false;
- if (to_rename.path != "res://") {
- String name = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1).get_file() : to_rename.path.get_file();
- rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
- rename_dialog_text->set_text(name);
- rename_dialog_text->select(0, name.length());
- rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
- rename_dialog_text->grab_focus();
- }
- } break;
- case FOLDER_REMOVE: {
- Vector<String> remove_folders;
- Vector<String> remove_files;
- String fpath = selected->get_metadata(tree->get_selected_column());
- if (fpath != "res://") {
- remove_folders.push_back(fpath);
- remove_dialog->show(remove_folders, remove_files);
- }
- } break;
- case FOLDER_NEW_FOLDER: {
- make_dir_dialog_text->set_text("new folder");
- make_dir_dialog_text->select_all();
- make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
- make_dir_dialog_text->grab_focus();
- } break;
- case FOLDER_COPY_PATH: {
- String fpath = selected->get_metadata(tree->get_selected_column());
- OS::get_singleton()->set_clipboard(fpath);
- } break;
- case FOLDER_SHOW_IN_EXPLORER: {
- String fpath = selected->get_metadata(tree->get_selected_column());
- String dir = ProjectSettings::get_singleton()->globalize_path(fpath);
- OS::get_singleton()->shell_open(String("file://") + dir);
- } break;
- }
-}
-
void FileSystemDock::_resource_created() const {
Object *c = new_resource_dialog->instance_selected();
@@ -1431,38 +1567,39 @@ void FileSystemDock::_resource_created() const {
RES current_res = RES(r);
- editor->save_resource_as(current_res, path);
-}
-
-void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) {
- folder_options->clear();
- folder_options->set_size(Size2(1, 1));
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
+ }
- folder_options->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL);
- folder_options->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL);
+ editor->save_resource_as(current_res, fpath);
+}
- TreeItem *item = tree->get_selected();
- if (item) {
- String fpath = item->get_metadata(tree->get_selected_column());
- folder_options->add_separator();
- folder_options->add_item(TTR("Copy Path"), FOLDER_COPY_PATH);
- if (fpath != "res://") {
- folder_options->add_item(TTR("Rename..."), FOLDER_RENAME);
- folder_options->add_item(TTR("Move To..."), FOLDER_MOVE);
- folder_options->add_item(TTR("Delete"), FOLDER_REMOVE);
- }
- folder_options->add_separator();
- folder_options->add_item(TTR("New Folder..."), FOLDER_NEW_FOLDER);
- folder_options->add_item(TTR("Open In File Manager"), FOLDER_SHOW_IN_EXPLORER);
+void FileSystemDock::_search_changed(const String &p_text, const Control *p_from) {
+ if (searched_string.length() == 0 && p_text.length() > 0) {
+ // Register the uncollapsed paths before they change
+ uncollapsed_paths_before_search = _compute_uncollapsed_paths();
}
- folder_options->set_position(tree->get_global_position() + p_pos);
- folder_options->popup();
-}
-void FileSystemDock::_search_changed(const String &p_text) {
+ searched_string = p_text.to_lower();
- if (file_list_vb->is_visible())
- _update_files(false);
+ if (p_from == tree_search_box)
+ file_list_search_box->set_text(searched_string);
+ else // file_list_search_box
+ tree_search_box->set_text(searched_string);
+
+ switch (display_mode) {
+ case DISPLAY_MODE_FILE_LIST_ONLY: {
+ _update_files(false);
+ } break;
+ case DISPLAY_MODE_TREE_ONLY: {
+ _update_tree(searched_string.length() == 0 ? uncollapsed_paths_before_search : Vector<String>());
+ } break;
+ case DISPLAY_MODE_SPLIT: {
+ _update_files(false);
+ _update_tree(searched_string.length() == 0 ? uncollapsed_paths_before_search : Vector<String>());
+ } break;
+ }
}
void FileSystemDock::_rescan() {
@@ -1471,20 +1608,25 @@ void FileSystemDock::_rescan() {
EditorFileSystem::get_singleton()->scan();
}
+void FileSystemDock::_toggle_split_mode(bool p_active) {
+ display_mode_setting = p_active ? DISPLAY_MODE_SETTING_SPLIT : DISPLAY_MODE_SETTING_TREE_ONLY;
+ EditorSettings::get_singleton()->set("docks/filesystem/display_mode", int(display_mode_setting));
+ _update_display_mode();
+}
+
void FileSystemDock::fix_dependencies(const String &p_for_file) {
deps_editor->edit(p_for_file);
}
void FileSystemDock::focus_on_filter() {
- if (display_mode == DISPLAY_FILE_LIST_ONLY && tree->is_visible()) {
+ if (display_mode == DISPLAY_MODE_FILE_LIST_ONLY && tree->is_visible()) {
// Tree mode, switch to files list with search box
tree->hide();
file_list_vb->show();
- button_favorite->hide();
}
- search_box->grab_focus();
+ file_list_search_box->grab_focus();
}
void FileSystemDock::set_file_list_display_mode(int p_mode) {
@@ -1497,33 +1639,43 @@ void FileSystemDock::set_file_list_display_mode(int p_mode) {
}
Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- bool is_favorite = false;
+ bool all_favorites = true;
+ bool all_not_favorites = true;
+
Vector<String> paths;
if (p_from == tree) {
- TreeItem *selected = tree->get_selected();
- if (!selected)
- return Variant();
-
- String folder = selected->get_metadata(0);
- if (folder == String())
- return Variant();
-
- paths.push_back(folder.ends_with("/") ? folder : (folder + "/"));
- is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent();
+ // Check if the first selected is in favorite
+ TreeItem *selected = tree->get_next_selected(tree->get_root());
+ while (selected) {
+ bool is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent();
+ all_favorites &= is_favorite;
+ all_not_favorites &= !is_favorite;
+ selected = tree->get_next_selected(selected);
+ }
+ if (all_favorites) {
+ paths = _tree_get_selected(false);
+ } else {
+ paths = _tree_get_selected();
+ }
} else if (p_from == files) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->is_selected(i)) {
paths.push_back(files->get_item_metadata(i));
}
}
+ all_favorites = false;
+ all_not_favorites = true;
}
if (paths.empty())
return Variant();
+ if (!all_favorites && !all_not_favorites)
+ return Variant();
+
Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from);
- if (is_favorite) {
+ if (all_favorites) {
drag_data["type"] = "favorite";
}
return drag_data;
@@ -1535,34 +1687,46 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
- //moving favorite around
+ // Moving favorite around
TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return false;
- int what = tree->get_drop_section_at_position(p_point);
+ int drop_section = tree->get_drop_section_at_position(p_point);
+ TreeItem *favorites_item = tree->get_root()->get_children();
- if (ti == tree->get_root()->get_children()) {
- return (what == 1); //the parent, first fav
+ TreeItem *resources_item = favorites_item->get_next();
+
+ if (ti == favorites_item) {
+ return (drop_section == 1); // The parent, first fav
}
- if (ti->get_parent() && tree->get_root()->get_children() == ti->get_parent()) {
- return true; // a favorite
+ if (ti->get_parent() && favorites_item == ti->get_parent()) {
+ return true; // A favorite
}
-
- if (ti == tree->get_root()->get_children()->get_next()) {
- return (what == -1); //the tree, last fav
+ if (ti == resources_item) {
+ return (drop_section == -1); // The tree, last fav
}
return false;
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- String to_dir = _get_drag_target_folder(p_point, p_from);
+ // Move resources
+ String to_dir;
+ bool favorite;
+ _get_drag_target_folder(to_dir, favorite, p_point, p_from);
return !to_dir.empty();
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
- String to_dir = _get_drag_target_folder(p_point, p_from);
+ // Move files or dir
+ String to_dir;
+ bool favorite;
+ _get_drag_target_folder(to_dir, favorite, p_point, p_from);
+
+ if (favorite)
+ return true;
+
if (to_dir.empty())
return false;
@@ -1587,71 +1751,67 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
return;
Dictionary drag_data = p_data;
- if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
+ Vector<String> dirs = EditorSettings::get_singleton()->get_favorites();
- //moving favorite around
+ if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
+ // Moving favorite around
TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
+ int drop_section = tree->get_drop_section_at_position(p_point);
+ int drop_position;
Vector<String> files = drag_data["files"];
-
- ERR_FAIL_COND(files.size() != 1);
-
- String swap = files[0];
- if (swap != "res://" && swap.ends_with("/")) {
- swap = swap.substr(0, swap.length() - 1);
- }
-
- int what = tree->get_drop_section_at_position(p_point);
-
- TreeItem *swap_item = NULL;
-
- if (ti == tree->get_root()->get_children()) {
- swap_item = tree->get_root()->get_children()->get_children();
-
- } else if (ti->get_parent() && tree->get_root()->get_children() == ti->get_parent()) {
- if (what == -1) {
- swap_item = ti;
- } else {
- swap_item = ti->get_next();
+ TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *resources_item = favorites_item->get_next();
+
+ if (ti == favorites_item) {
+ // Drop on the favorite folder
+ drop_position = 0;
+ } else if (ti == resources_item) {
+ // Drop on the resouce item
+ drop_position = dirs.size();
+ } else {
+ // Drop in the list
+ drop_position = dirs.find(ti->get_metadata(0));
+ if (drop_section == 1) {
+ drop_position++;
}
}
- String swap_with;
-
- if (swap_item) {
- swap_with = swap_item->get_metadata(0);
- if (swap_with != "res://" && swap_with.ends_with("/")) {
- swap_with = swap_with.substr(0, swap_with.length() - 1);
+ // Remove dragged favorites
+ Vector<int> to_remove;
+ int offset = 0;
+ for (int i = 0; i < files.size(); i++) {
+ int to_remove_pos = dirs.find(files[i]);
+ to_remove.push_back(to_remove_pos);
+ if (to_remove_pos < drop_position) {
+ offset++;
}
}
+ drop_position -= offset;
+ to_remove.sort();
+ for (int i = 0; i < to_remove.size(); i++) {
+ dirs.remove(to_remove[i] - i);
+ }
- if (swap == swap_with)
- return;
-
- Vector<String> dirs = EditorSettings::get_singleton()->get_favorite_dirs();
-
- ERR_FAIL_COND(dirs.find(swap) == -1);
- ERR_FAIL_COND(swap_with != String() && dirs.find(swap_with) == -1);
-
- dirs.erase(swap);
-
- if (swap_with == String()) {
- dirs.push_back(swap);
- } else {
- int idx = dirs.find(swap_with);
- dirs.insert(idx, swap);
+ // Re-add them at the right position
+ for (int i = 0; i < files.size(); i++) {
+ dirs.insert(drop_position, files[i]);
+ drop_position++;
}
- EditorSettings::get_singleton()->set_favorite_dirs(dirs);
- _update_tree(true);
+ EditorSettings::get_singleton()->set_favorites(dirs);
+ _update_tree(_compute_uncollapsed_paths());
return;
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
+ // Moving resource
Ref<Resource> res = drag_data["resource"];
- String to_dir = _get_drag_target_folder(p_point, p_from);
+ String to_dir;
+ bool favorite;
+ _get_drag_target_folder(to_dir, favorite, p_point, p_from);
if (res.is_valid() && !to_dir.empty()) {
EditorNode::get_singleton()->push_item(res.ptr());
EditorNode::get_singleton()->save_resource_as(res, to_dir);
@@ -1659,7 +1819,10 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
- String to_dir = _get_drag_target_folder(p_point, p_from);
+ // Move files or add to favorites
+ String to_dir;
+ bool favorite;
+ _get_drag_target_folder(to_dir, favorite, p_point, p_from);
if (!to_dir.empty()) {
Vector<String> fnames = drag_data["files"];
to_move.clear();
@@ -1667,50 +1830,93 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
to_move.push_back(FileOrFolder(fnames[i], !fnames[i].ends_with("/")));
}
_move_operation_confirm(to_dir);
+ } else if (favorite) {
+ // Add the files from favorites
+ Vector<String> fnames = drag_data["files"];
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
+ for (int i = 0; i < fnames.size(); i++) {
+ if (favorites.find(fnames[i]) == -1) {
+ favorites.push_back(fnames[i]);
+ }
+ }
+ EditorSettings::get_singleton()->set_favorites(favorites);
+ _update_tree(_compute_uncollapsed_paths());
}
}
}
-String FileSystemDock::_get_drag_target_folder(const Point2 &p_point, Control *p_from) const {
+void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const {
+ target = String();
+ target_favorites = false;
+
+ // In the file list
if (p_from == files) {
int pos = files->get_item_at_position(p_point, true);
- if (pos == -1)
- return path;
+ if (pos == -1) {
+ return;
+ }
- String target = files->get_item_metadata(pos);
- return target.ends_with("/") ? target : path;
+ String ltarget = files->get_item_metadata(pos);
+ target = ltarget.ends_with("/") ? target : path;
+ return;
}
+ // In the tree
if (p_from == tree) {
TreeItem *ti = tree->get_item_at_position(p_point);
- if (ti && ti != tree->get_root()->get_children())
- return ti->get_metadata(0);
+ int section = tree->get_drop_section_at_position(p_point);
+ if (ti) {
+ // Check the favorites first
+ if (ti == tree->get_root()->get_children() && section >= 0) {
+ target_favorites = true;
+ return;
+ } else if (ti->get_parent() == tree->get_root()->get_children()) {
+ target_favorites = true;
+ return;
+ } else {
+ String fpath = ti->get_metadata(0);
+ if (section == 0) {
+ if (fpath.ends_with("/")) {
+ // We drop on a folder
+ target = fpath;
+ return;
+ }
+ } else {
+ if (ti->get_parent() != tree->get_root()->get_children()) {
+ // Not in the favorite section
+ if (fpath != "res://") {
+ // We drop between two files
+ if (fpath.ends_with("/")) {
+ fpath = fpath.substr(0, fpath.length() - 1);
+ }
+ target = fpath.get_base_dir();
+ return;
+ }
+ }
+ }
+ }
+ }
}
- return String();
+ return;
}
-void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
-
- //Right clicking ".." should clear current selection
- if (files->get_item_text(p_item) == "..") {
- for (int i = 0; i < files->get_item_count(); i++) {
- files->unselect(i);
- }
- }
+void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths) {
+ // Add options for files and folders
+ ERR_FAIL_COND(p_paths.empty())
Vector<String> filenames;
Vector<String> foldernames;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
+
bool all_files = true;
bool all_files_scenes = true;
bool all_folders = true;
- for (int i = 0; i < files->get_item_count(); i++) {
- if (!files->is_selected(i)) {
- continue;
- }
-
- String fpath = files->get_item_metadata(i);
+ bool all_favorites = true;
+ bool all_not_favorites = true;
+ for (int i = 0; i < p_paths.size(); i++) {
+ String fpath = p_paths[i];
if (fpath.ends_with("/")) {
foldernames.push_back(fpath);
all_files = false;
@@ -1719,68 +1925,135 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
all_folders = false;
all_files_scenes &= (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene");
}
+
+ // Check if in favorites
+ bool found = false;
+ for (int j = 0; j < favorites.size(); j++) {
+ if (favorites[j] == fpath) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ all_not_favorites = false;
+ } else {
+ all_favorites = false;
+ }
}
- file_options->clear();
- file_options->set_size(Size2(1, 1));
if (all_files) {
if (all_files_scenes && filenames.size() >= 1) {
- file_options->add_item(TTR("Open Scene(s)"), FILE_OPEN);
- file_options->add_item(TTR("Instance"), FILE_INSTANCE);
- file_options->add_separator();
+ p_popup->add_item(TTR("Open Scene(s)"), FILE_OPEN);
+ p_popup->add_item(TTR("Instance"), FILE_INSTANCE);
+ p_popup->add_separator();
}
if (!all_files_scenes && filenames.size() == 1) {
- file_options->add_item(TTR("Open"), FILE_OPEN);
- file_options->add_separator();
+ p_popup->add_item(TTR("Open"), FILE_OPEN);
+ p_popup->add_separator();
}
+ }
+
+ if (p_paths.size() >= 1) {
+ if (!all_favorites) {
+ p_popup->add_item(TTR("Add to favorites"), FILE_ADD_FAVORITE);
+ }
+ if (!all_not_favorites) {
+ p_popup->add_item(TTR("Remove from favorites"), FILE_REMOVE_FAVORITE);
+ }
+ p_popup->add_separator();
+ }
+ if (all_files) {
if (filenames.size() == 1) {
- file_options->add_item(TTR("Edit Dependencies..."), FILE_DEPENDENCIES);
- file_options->add_item(TTR("View Owners..."), FILE_OWNERS);
- file_options->add_separator();
+ p_popup->add_item(TTR("Edit Dependencies..."), FILE_DEPENDENCIES);
+ p_popup->add_item(TTR("View Owners..."), FILE_OWNERS);
+ p_popup->add_separator();
}
} else if (all_folders && foldernames.size() > 0) {
- file_options->add_item(TTR("Open"), FILE_OPEN);
- file_options->add_separator();
+ p_popup->add_item(TTR("Open"), FILE_OPEN);
+ p_popup->add_separator();
}
- int num_items = filenames.size() + foldernames.size();
- if (num_items >= 1) {
- if (num_items == 1) {
- file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
- file_options->add_item(TTR("Rename..."), FILE_RENAME);
- file_options->add_item(TTR("Duplicate..."), FILE_DUPLICATE);
- }
- file_options->add_item(TTR("Move To..."), FILE_MOVE);
- file_options->add_item(TTR("Delete"), FILE_REMOVE);
- file_options->add_separator();
+ if (p_paths.size() == 1) {
+ p_popup->add_item(TTR("Copy Path"), FILE_COPY_PATH);
+ p_popup->add_item(TTR("Rename..."), FILE_RENAME);
+ p_popup->add_item(TTR("Duplicate..."), FILE_DUPLICATE);
+ }
+
+ p_popup->add_item(TTR("Move To..."), FILE_MOVE);
+ p_popup->add_item(TTR("Delete"), FILE_REMOVE);
+
+ if (p_paths.size() == 1) {
+ p_popup->add_separator();
+ p_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER);
+ p_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
+ p_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
+
+ String fpath = p_paths[0];
+ String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager");
+ p_popup->add_item(item_text, FILE_SHOW_IN_EXPLORER);
}
+}
- file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER);
- file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
- file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
+void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
+ // Right click is pressed in the tree
+ Vector<String> paths = _tree_get_selected();
- String fpath = files->get_item_metadata(p_item);
- String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager");
- file_options->add_item(item_text, FILE_SHOW_IN_EXPLORER);
+ if (paths.size() == 1) {
+ if (paths[0].ends_with("/")) {
+ tree_popup->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL);
+ tree_popup->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL);
+ tree_popup->add_separator();
+ }
+ }
- file_options->set_position(files->get_global_position() + p_pos);
- file_options->popup();
+ // Popup
+ if (!paths.empty()) {
+ tree_popup->clear();
+ tree_popup->set_size(Size2(1, 1));
+ _file_and_folders_fill_popup(tree_popup, paths);
+ tree_popup->set_position(tree->get_global_position() + p_pos);
+ tree_popup->popup();
+ }
}
-void FileSystemDock::_rmb_pressed(const Vector2 &p_pos) {
- file_options->clear();
- file_options->set_size(Size2(1, 1));
+void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
+ // Right click is pressed in the file list
+ Vector<String> paths;
+ for (int i = 0; i < files->get_item_count(); i++) {
+ if (!files->is_selected(i))
+ continue;
+ if (files->get_item_text(p_item) == "..") {
+ files->unselect(i);
+ continue;
+ }
+ paths.push_back(files->get_item_metadata(i));
+ }
+
+ // Popup
+ if (!paths.empty()) {
+ file_list_popup->clear();
+ file_list_popup->set_size(Size2(1, 1));
+ _file_and_folders_fill_popup(file_list_popup, paths);
+ file_list_popup->set_position(files->get_global_position() + p_pos);
+ file_list_popup->popup();
+ }
+}
- file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER);
- file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
- file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
- file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER);
- file_options->set_position(files->get_global_position() + p_pos);
- file_options->popup();
+void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) {
+ // Right click on empty space for file list
+ file_list_popup->clear();
+ file_list_popup->set_size(Size2(1, 1));
+
+ file_list_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER);
+ file_list_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
+ file_list_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
+ file_list_popup->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER);
+ file_list_popup->set_position(files->get_global_position() + p_pos);
+ file_list_popup->popup();
}
void FileSystemDock::select_file(const String &p_file) {
@@ -1790,11 +2063,24 @@ void FileSystemDock::select_file(const String &p_file) {
void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
+ // Set the path to the current focussed item
+ int current = files->get_current();
+ if (current == p_index) {
+ String fpath = files->get_item_metadata(current);
+ if (!fpath.ends_with("/")) {
+ path = fpath;
+ if (display_mode == DISPLAY_MODE_SPLIT) {
+ _update_tree(_compute_uncollapsed_paths());
+ }
+ }
+ }
+
+ // Update the import dock
import_dock_needs_update = true;
call_deferred("_update_import_dock");
}
-void FileSystemDock::_files_gui_input(Ref<InputEvent> p_event) {
+void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
if (get_viewport()->get_modal_stack_top())
return; //ignore because of modal window
@@ -1802,21 +2088,34 @@ void FileSystemDock::_files_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventKey> key = p_event;
if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) {
- _file_option(FILE_DUPLICATE);
+ _tree_rmb_option(FILE_DUPLICATE);
} else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) {
- _file_option(FILE_COPY_PATH);
+ _tree_rmb_option(FILE_COPY_PATH);
} else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) {
- _file_option(FILE_REMOVE);
+ _tree_rmb_option(FILE_REMOVE);
} else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) {
- _file_option(FILE_RENAME);
+ _tree_rmb_option(FILE_RENAME);
}
}
}
-void FileSystemDock::_file_selected() {
+void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) {
- import_dock_needs_update = true;
- _update_import_dock();
+ if (get_viewport()->get_modal_stack_top())
+ return; //ignore because of modal window
+
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
+ if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) {
+ _file_list_rmb_option(FILE_DUPLICATE);
+ } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) {
+ _file_list_rmb_option(FILE_COPY_PATH);
+ } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) {
+ _file_list_rmb_option(FILE_REMOVE);
+ } else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) {
+ _file_list_rmb_option(FILE_RENAME);
+ }
+ }
}
void FileSystemDock::_update_import_dock() {
@@ -1869,16 +2168,25 @@ void FileSystemDock::_update_import_dock() {
void FileSystemDock::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_files_gui_input"), &FileSystemDock::_files_gui_input);
+ ClassDB::bind_method(D_METHOD("_file_list_gui_input"), &FileSystemDock::_file_list_gui_input);
+ ClassDB::bind_method(D_METHOD("_tree_gui_input"), &FileSystemDock::_tree_gui_input);
+
ClassDB::bind_method(D_METHOD("_update_tree"), &FileSystemDock::_update_tree);
ClassDB::bind_method(D_METHOD("_rescan"), &FileSystemDock::_rescan);
- ClassDB::bind_method(D_METHOD("_favorites_pressed"), &FileSystemDock::_favorites_pressed);
- ClassDB::bind_method(D_METHOD("_show_current_scene_file"), &FileSystemDock::_show_current_scene_file);
- //ClassDB::bind_method(D_METHOD("_instance_pressed"),&ScenesDock::_instance_pressed);
- ClassDB::bind_method(D_METHOD("_go_to_file_list"), &FileSystemDock::_go_to_file_list);
- ClassDB::bind_method(D_METHOD("_dir_rmb_pressed"), &FileSystemDock::_dir_rmb_pressed);
- ClassDB::bind_method(D_METHOD("_thumbnail_done"), &FileSystemDock::_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("_toggle_split_mode"), &FileSystemDock::_toggle_split_mode);
+
+ ClassDB::bind_method(D_METHOD("_tree_rmb_option", "option"), &FileSystemDock::_tree_rmb_option);
+ ClassDB::bind_method(D_METHOD("_file_list_rmb_option", "option"), &FileSystemDock::_file_list_rmb_option);
+
+ ClassDB::bind_method(D_METHOD("_tree_rmb_select"), &FileSystemDock::_tree_rmb_select);
+ ClassDB::bind_method(D_METHOD("_file_list_rmb_select"), &FileSystemDock::_file_list_rmb_select);
+ ClassDB::bind_method(D_METHOD("_file_list_rmb_pressed"), &FileSystemDock::_file_list_rmb_pressed);
+
+ ClassDB::bind_method(D_METHOD("_file_list_thumbnail_done"), &FileSystemDock::_file_list_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("_file_list_activate_file"), &FileSystemDock::_file_list_activate_file);
+ ClassDB::bind_method(D_METHOD("_tree_activate_file"), &FileSystemDock::_tree_activate_file);
ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file);
ClassDB::bind_method(D_METHOD("_go_to_tree"), &FileSystemDock::_go_to_tree);
ClassDB::bind_method(D_METHOD("navigate_to_path"), &FileSystemDock::navigate_to_path);
@@ -1886,9 +2194,7 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_fw_history"), &FileSystemDock::_fw_history);
ClassDB::bind_method(D_METHOD("_bw_history"), &FileSystemDock::_bw_history);
ClassDB::bind_method(D_METHOD("_fs_changed"), &FileSystemDock::_fs_changed);
- ClassDB::bind_method(D_METHOD("_dir_selected"), &FileSystemDock::_dir_selected);
- ClassDB::bind_method(D_METHOD("_file_option"), &FileSystemDock::_file_option);
- ClassDB::bind_method(D_METHOD("_folder_option"), &FileSystemDock::_folder_option);
+ ClassDB::bind_method(D_METHOD("_tree_multi_selected"), &FileSystemDock::_tree_multi_selected);
ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm);
ClassDB::bind_method(D_METHOD("_resource_created"), &FileSystemDock::_resource_created);
ClassDB::bind_method(D_METHOD("_move_operation_confirm", "to_path", "overwrite"), &FileSystemDock::_move_operation_confirm, DEFVAL(false));
@@ -1901,13 +2207,10 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw);
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw);
ClassDB::bind_method(D_METHOD("drop_data_fw"), &FileSystemDock::drop_data_fw);
- ClassDB::bind_method(D_METHOD("_files_list_rmb_select"), &FileSystemDock::_files_list_rmb_select);
ClassDB::bind_method(D_METHOD("_preview_invalidated"), &FileSystemDock::_preview_invalidated);
- ClassDB::bind_method(D_METHOD("_file_selected"), &FileSystemDock::_file_selected);
ClassDB::bind_method(D_METHOD("_file_multi_selected"), &FileSystemDock::_file_multi_selected);
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
- ClassDB::bind_method(D_METHOD("_rmb_pressed"), &FileSystemDock::_rmb_pressed);
ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("open"));
@@ -1924,9 +2227,12 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE);
ED_SHORTCUT("filesystem_dock/rename", TTR("Rename"));
+ VBoxContainer *top_vbc = memnew(VBoxContainer);
+ add_child(top_vbc);
+
HBoxContainer *toolbar_hbc = memnew(HBoxContainer);
toolbar_hbc->add_constant_override("separation", 0);
- add_child(toolbar_hbc);
+ top_vbc->add_child(toolbar_hbc);
button_hist_prev = memnew(ToolButton);
button_hist_prev->set_disabled(true);
@@ -1952,22 +2258,25 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_reload->hide();
toolbar_hbc->add_child(button_reload);
- //toolbar_hbc->add_spacer();
+ button_toggle_display_mode = memnew(Button);
+ button_toggle_display_mode->set_flat(true);
+ button_toggle_display_mode->set_toggle_mode(true);
+ button_toggle_display_mode->connect("toggled", this, "_toggle_split_mode");
+ button_toggle_display_mode->set_focus_mode(FOCUS_NONE);
+ button_toggle_display_mode->set_tooltip(TTR("Toggle split mode"));
+ toolbar_hbc->add_child(button_toggle_display_mode);
- button_favorite = memnew(Button);
- button_favorite->set_flat(true);
- button_favorite->set_toggle_mode(true);
- button_favorite->connect("pressed", this, "_favorites_pressed");
- button_favorite->set_tooltip(TTR("Toggle folder status as Favorite."));
- button_favorite->set_focus_mode(FOCUS_NONE);
- toolbar_hbc->add_child(button_favorite);
-
- button_show = memnew(Button);
- button_show->set_flat(true);
- button_show->connect("pressed", this, "_show_current_scene_file");
- toolbar_hbc->add_child(button_show);
- button_show->set_focus_mode(FOCUS_NONE);
- button_show->set_tooltip(TTR("Show current scene file."));
+ HBoxContainer *toolbar2_hbc = memnew(HBoxContainer);
+ toolbar2_hbc->add_constant_override("separation", 0);
+ top_vbc->add_child(toolbar2_hbc);
+
+ tree_search_box = memnew(LineEdit);
+ tree_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ tree_search_box->set_placeholder(TTR("Search files"));
+ tree_search_box->connect("text_changed", this, "_search_changed", varray(tree_search_box));
+ toolbar2_hbc->add_child(tree_search_box);
+
+ //toolbar_hbc->add_spacer();
//Control *spacer = memnew( Control);
@@ -1990,13 +2299,13 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_instance->set_tooltip(TTR("Instance the selected scene(s) as child of the selected node."));
*/
- file_options = memnew(PopupMenu);
- file_options->set_hide_on_window_lose_focus(true);
- add_child(file_options);
+ file_list_popup = memnew(PopupMenu);
+ file_list_popup->set_hide_on_window_lose_focus(true);
+ add_child(file_list_popup);
- folder_options = memnew(PopupMenu);
- folder_options->set_hide_on_window_lose_focus(true);
- add_child(folder_options);
+ tree_popup = memnew(PopupMenu);
+ tree_popup->set_hide_on_window_lose_focus(true);
+ add_child(tree_popup);
split_box = memnew(VSplitContainer);
split_box->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -2007,13 +2316,15 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
tree->set_hide_root(true);
tree->set_drag_forwarding(this);
tree->set_allow_rmb_select(true);
+ tree->set_select_mode(Tree::SELECT_MULTI);
tree->set_custom_minimum_size(Size2(0, 200 * EDSCALE));
split_box->add_child(tree);
tree->connect("item_edited", this, "_favorite_toggled");
- tree->connect("item_activated", this, "_go_to_file_list");
- tree->connect("cell_selected", this, "_dir_selected");
- tree->connect("item_rmb_selected", this, "_dir_rmb_pressed");
+ tree->connect("item_activated", this, "_tree_activate_file");
+ tree->connect("multi_selected", this, "_tree_multi_selected");
+ tree->connect("item_rmb_selected", this, "_tree_rmb_select");
+ tree->connect("gui_input", this, "_tree_gui_input");
file_list_vb = memnew(VBoxContainer);
file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -2027,11 +2338,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_tree->hide();
path_hb->add_child(button_tree);
- search_box = memnew(LineEdit);
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- search_box->set_placeholder(TTR("Search files"));
- search_box->connect("text_changed", this, "_search_changed");
- path_hb->add_child(search_box);
+ file_list_search_box = memnew(LineEdit);
+ file_list_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ file_list_search_box->set_placeholder(TTR("Search files"));
+ file_list_search_box->connect("text_changed", this, "_search_changed", varray(file_list_search_box));
+ path_hb->add_child(file_list_search_box);
button_file_list_display_mode = memnew(ToolButton);
button_file_list_display_mode->set_toggle_mode(true);
@@ -2041,11 +2352,10 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
files->set_v_size_flags(SIZE_EXPAND_FILL);
files->set_select_mode(ItemList::SELECT_MULTI);
files->set_drag_forwarding(this);
- files->connect("item_rmb_selected", this, "_files_list_rmb_select");
- files->connect("gui_input", this, "_files_gui_input");
- files->connect("item_selected", this, "_file_selected");
+ files->connect("item_rmb_selected", this, "_file_list_rmb_select");
+ files->connect("gui_input", this, "_file_list_gui_input");
files->connect("multi_selected", this, "_file_multi_selected");
- files->connect("rmb_clicked", this, "_rmb_pressed");
+ files->connect("rmb_clicked", this, "_file_list_rmb_pressed");
files->set_allow_rmb_select(true);
file_list_vb->add_child(files);
@@ -2123,7 +2433,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
new_resource_dialog->set_base_type("Resource");
new_resource_dialog->connect("create", this, "_resource_created");
+ searched_string = String();
+ uncollapsed_paths_before_search = Vector<String>();
+
updating_tree = false;
+ tree_update_id = 0;
initialized = false;
import_dock_needs_update = false;
@@ -2131,8 +2445,12 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
history_max_size = 20;
history.push_back("res://");
- display_mode = DISPLAY_SPLIT;
+ display_mode = DISPLAY_MODE_SPLIT;
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS;
+
+ display_mode_setting = DISPLAY_MODE_SETTING_TREE_ONLY;
+ old_display_mode_setting = DISPLAY_MODE_SETTING_TREE_ONLY;
+ always_show_folders = false;
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 40be645bf7..51c8791b25 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -66,15 +66,22 @@ public:
};
private:
+ enum DisplayModeSetting {
+ DISPLAY_MODE_SETTING_TREE_ONLY,
+ DISPLAY_MODE_SETTING_SPLIT,
+ };
+
enum DisplayMode {
- DISPLAY_TREE_ONLY,
- DISPLAY_FILE_LIST_ONLY,
- DISPLAY_SPLIT,
+ DISPLAY_MODE_TREE_ONLY,
+ DISPLAY_MODE_FILE_LIST_ONLY,
+ DISPLAY_MODE_SPLIT,
};
enum FileMenu {
FILE_OPEN,
FILE_INSTANCE,
+ FILE_ADD_FAVORITE,
+ FILE_REMOVE_FAVORITE,
FILE_DEPENDENCIES,
FILE_OWNERS,
FILE_MOVE,
@@ -87,18 +94,9 @@ private:
FILE_NEW_SCRIPT,
FILE_SHOW_IN_EXPLORER,
FILE_COPY_PATH,
- FILE_NEW_RESOURCE
- };
-
- enum FolderMenu {
+ FILE_NEW_RESOURCE,
FOLDER_EXPAND_ALL,
FOLDER_COLLAPSE_ALL,
- FOLDER_MOVE,
- FOLDER_RENAME,
- FOLDER_REMOVE,
- FOLDER_NEW_FOLDER,
- FOLDER_SHOW_IN_EXPLORER,
- FOLDER_COPY_PATH
};
VBoxContainer *scanning_vb;
@@ -109,24 +107,30 @@ private:
EditorNode *editor;
Set<String> favorites;
+ Button *button_toggle_display_mode;
Button *button_reload;
- Button *button_favorite;
Button *button_tree;
Button *button_file_list_display_mode;
Button *button_hist_next;
Button *button_hist_prev;
- Button *button_show;
LineEdit *current_path;
- LineEdit *search_box;
+ LineEdit *tree_search_box;
+ LineEdit *file_list_search_box;
+
+ String searched_string;
+ Vector<String> uncollapsed_paths_before_search;
+
TextureRect *search_icon;
HBoxContainer *path_hb;
FileListDisplayMode file_list_display_mode;
DisplayMode display_mode;
+ DisplayModeSetting display_mode_setting;
+ DisplayModeSetting old_display_mode_setting;
bool file_list_view;
- PopupMenu *file_options;
- PopupMenu *folder_options;
+ PopupMenu *file_list_popup;
+ PopupMenu *tree_popup;
DependencyEditor *deps_editor;
DependencyEditorOwners *owners_editor;
@@ -143,6 +147,8 @@ private:
ScriptCreateDialog *make_script_dialog_text;
CreateDialog *new_resource_dialog;
+ bool always_show_folders;
+
class FileOrFolder {
public:
String path;
@@ -169,14 +175,18 @@ private:
bool initialized;
bool updating_tree;
+ int tree_update_id;
Tree *tree; //directories
ItemList *files;
bool import_dock_needs_update;
+ Ref<Texture> _get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx);
bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths);
- void _update_tree(bool keep_collapse_state, bool p_uncollapse_root = false);
+ Vector<String> _compute_uncollapsed_paths();
+ void _update_tree(const Vector<String> p_uncollapsed_paths = Vector<String>(), bool p_uncollapse_root = false);
- void _files_gui_input(Ref<InputEvent> p_event);
+ void _file_list_gui_input(Ref<InputEvent> p_event);
+ void _tree_gui_input(Ref<InputEvent> p_event);
void _update_files(bool p_keep_selection);
void _update_file_list_display_mode_button();
@@ -186,12 +196,13 @@ private:
void _go_to_tree();
void _go_to_file_list();
- void _select_file(int p_idx);
+ void _select_file(const String p_path);
+ void _tree_activate_file();
+ void _file_list_activate_file(int p_idx);
void _file_multi_selected(int p_index, bool p_selected);
- void _update_import_dock();
+ void _tree_multi_selected(Object *p_item, int p_column, bool p_selected);
- void _file_selected();
- void _dir_selected();
+ void _update_import_dock();
void _get_all_items_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files, Vector<String> &folders) const;
void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const;
@@ -199,8 +210,8 @@ private:
void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
void _update_resource_paths_after_move(const Map<String, String> &p_renames) const;
- void _update_favorite_dirs_list_after_move(const Map<String, String> &p_renames) const;
- void _update_project_settings_after_move(const Map<String, String> &p_renames) const;
+ void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const;
+ void _update_project_settings_after_move(const Map<String, String> &p_folders_renames) const;
void _resource_created() const;
void _make_dir_confirm();
@@ -210,8 +221,9 @@ private:
bool _check_existing();
void _move_operation_confirm(const String &p_to_path, bool overwrite = false);
- void _file_option(int p_option);
- void _folder_option(int p_option);
+ void _tree_rmb_option(int p_option);
+ void _file_list_rmb_option(int p_option);
+ void _file_option(int p_option, const Vector<String> p_selected);
void _fw_history();
void _bw_history();
@@ -221,13 +233,14 @@ private:
void _set_scanning_mode();
void _rescan();
- void _favorites_pressed();
- void _show_current_scene_file();
- void _search_changed(const String &p_text);
+ void _toggle_split_mode(bool p_active);
- void _dir_rmb_pressed(const Vector2 &p_pos);
- void _files_list_rmb_select(int p_item, const Vector2 &p_pos);
- void _rmb_pressed(const Vector2 &p_pos);
+ void _search_changed(const String &p_text, const Control *p_from);
+
+ void _file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths);
+ void _tree_rmb_select(const Vector2 &p_pos);
+ void _file_list_rmb_select(int p_item, const Vector2 &p_pos);
+ void _file_list_rmb_pressed(const Vector2 &p_pos);
struct FileInfo {
String name;
@@ -238,7 +251,7 @@ private:
bool import_broken;
bool operator<(const FileInfo &fi) const {
- return name < fi.name;
+ return NaturalNoCaseComparator()(name, fi.name);
}
};
@@ -247,13 +260,16 @@ private:
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
- String _get_drag_target_folder(const Point2 &p_point, Control *p_from) const;
+ void _get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const;
void _preview_invalidated(const String &p_path);
- void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
+ void _file_list_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
+ void _tree_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
void _update_display_mode();
+ Vector<String> _tree_get_selected(bool remove_self_inclusion = true);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 16cba1db77..81a798f0b6 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -104,6 +104,7 @@ void InspectorDock::_menu_option(int p_option) {
res = duplicates[res];
current->set(E->get().name, res);
+ editor->get_inspector()->update_property(E->get().name);
}
}
}
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index b51ff8b320..f7e59e2beb 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -516,12 +516,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
return false;
}
-void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) {
+void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!_get_node())
return;
- Control *vpc = canvas_item_editor->get_viewport_control();
-
Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
const Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
@@ -562,7 +560,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) {
Vector2 point = xform.xform(p);
Vector2 next_point = xform.xform(p2);
- vpc->draw_line(point, next_point, col, 2 * EDSCALE);
+ p_overlay->draw_line(point, next_point, col, 2 * EDSCALE);
}
}
@@ -586,7 +584,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) {
p2 = points[(i + 1) % n_points] + offset;
const Vector2 next_point = xform.xform(p2);
- vpc->draw_line(point, next_point, col, 2 * EDSCALE);
+ p_overlay->draw_line(point, next_point, col, 2 * EDSCALE);
}
}
@@ -598,14 +596,14 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) {
const Vector2 point = xform.xform(p);
const Color modulate = vertex == active_point ? Color(0.5, 1, 2) : Color(1, 1, 1);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5, modulate);
+ p_overlay->draw_texture(handle, point - handle->get_size() * 0.5, modulate);
}
}
if (edge_point.valid()) {
Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons");
- vpc->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5);
+ p_overlay->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5);
}
}
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 9ba03bcdf6..00634ba5b8 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -137,7 +137,7 @@ protected:
public:
bool forward_gui_input(const Ref<InputEvent> &p_event);
- void forward_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node *p_polygon);
AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true);
@@ -153,7 +153,7 @@ class AbstractPolygon2DEditorPlugin : public EditorPlugin {
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); }
- virtual void forward_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_canvas_draw_over_viewport(p_overlay); }
bool has_main_screen() const { return false; }
virtual String get_name() const { return klass; }
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index bf7603bd86..445664f8dd 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -908,7 +908,7 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
}
}
-void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay) {
+void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_overlay) {
if (!onion.can_overlay)
return;
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 5ac7b99903..55f082aadb 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -246,7 +246,7 @@ public:
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
void edit(AnimationPlayer *p_player);
- void forward_force_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_force_draw_over_viewport(Control *p_overlay);
AnimationPlayerEditor(EditorNode *p_editor, AnimationPlayerEditorPlugin *p_plugin);
};
@@ -271,7 +271,7 @@ public:
virtual bool handles(Object *p_object) const;
virtual void make_visible(bool p_visible);
- virtual void forward_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_force_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_canvas_force_draw_over_viewport(p_overlay); }
AnimationPlayerEditorPlugin(EditorNode *p_node);
~AnimationPlayerEditorPlugin();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 302207d123..406c3def0d 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2946,13 +2946,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
float offset = 0;
Ref<Texture> lock = get_icon("LockViewport", "EditorIcons");
- if (p_node->has_meta("_edit_lock_")) {
+ if (p_node->has_meta("_edit_lock_") && show_edit_locks) {
lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
offset += lock->get_size().x;
}
Ref<Texture> group = get_icon("GroupViewport", "EditorIcons");
- if (canvas_item->has_meta("_edit_group_")) {
+ if (canvas_item->has_meta("_edit_group_") && show_edit_locks) {
group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
//offset += group->get_size().x;
}
@@ -3026,6 +3026,7 @@ bool CanvasItemEditor::_build_bones_list(Node *p_node) {
}
void CanvasItemEditor::_draw_viewport() {
+
// Update the transform
transform = Transform2D();
transform.scale_basis(Size2(zoom, zoom));
@@ -3074,11 +3075,11 @@ void CanvasItemEditor::_draw_viewport() {
EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
if (!over_plugin_list->empty()) {
- over_plugin_list->forward_draw_over_viewport(viewport);
+ over_plugin_list->forward_canvas_draw_over_viewport(viewport);
}
EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
if (!force_over_plugin_list->empty()) {
- force_over_plugin_list->forward_force_draw_over_viewport(viewport);
+ force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport);
}
_draw_bones();
@@ -3551,6 +3552,12 @@ void CanvasItemEditor::_popup_callback(int p_op) {
view_menu->get_popup()->set_item_checked(idx, show_viewport);
viewport->update();
} break;
+ case SHOW_EDIT_LOCKS: {
+ show_edit_locks = !show_edit_locks;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
+ view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
+ viewport->update();
+ } break;
case SNAP_USE_NODE_PARENT: {
snap_node_parent = !snap_node_parent;
int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
@@ -4154,6 +4161,7 @@ Dictionary CanvasItemEditor::get_state() const {
state["show_rulers"] = show_rulers;
state["show_guides"] = show_guides;
state["show_helpers"] = show_helpers;
+ state["show_edit_locks"] = show_edit_locks;
state["snap_rotation"] = snap_rotation;
state["snap_relative"] = snap_relative;
state["snap_pixel"] = snap_pixel;
@@ -4273,6 +4281,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
view_menu->get_popup()->set_item_checked(idx, show_helpers);
}
+ if (state.has("show_edit_locks")) {
+ show_edit_locks = state["show_edit_locks"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
+ view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
+ }
+
if (state.has("snap_rotation")) {
snap_rotation = state["snap_rotation"];
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
@@ -4543,6 +4557,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS);
+
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
@@ -4633,6 +4649,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
show_helpers = false;
show_rulers = true;
show_guides = true;
+ show_edit_locks = true;
zoom = 1;
view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH);
previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 18ebba4568..61631dee7d 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -105,6 +105,7 @@ private:
SHOW_GUIDES,
SHOW_ORIGIN,
SHOW_VIEWPORT,
+ SHOW_EDIT_LOCKS,
LOCK_SELECTED,
UNLOCK_SELECTED,
GROUP_SELECTED,
@@ -225,6 +226,7 @@ private:
bool show_origin;
bool show_viewport;
bool show_helpers;
+ bool show_edit_locks;
float zoom;
Point2 view_offset;
Point2 previous_update_view_offset;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 9e052bb027..e3f364790a 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -415,7 +415,7 @@ void CollisionShape2DEditor::_get_current_shape_type() {
canvas_item_editor->get_viewport_control()->update();
}
-void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) {
+void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node) {
return;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index 10784f1129..fb7b2acb0f 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -75,7 +75,7 @@ protected:
public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
- void forward_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node *p_node);
CollisionShape2DEditor(EditorNode *p_editor);
@@ -89,7 +89,7 @@ class CollisionShape2DEditorPlugin : public EditorPlugin {
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); }
- virtual void forward_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
virtual String get_name() const { return "CollisionShape2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 72a746e95b..7f83865777 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -78,7 +78,11 @@ bool EditorTexturePreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Texture");
}
-Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const {
+bool EditorTexturePreviewPlugin::should_generate_small_preview() const {
+ return true;
+}
+
+Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<Image> img;
Ref<AtlasTexture> atex = p_from;
@@ -100,8 +104,6 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const {
img = img->duplicate();
img->clear_mipmaps();
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
if (img->is_compressed()) {
if (img->decompress() != OK)
return Ref<Texture>();
@@ -109,22 +111,15 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const {
img->convert(Image::FORMAT_RGBA8);
}
- int width, height;
- if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) {
-
- width = thumbnail_size;
- height = img->get_height() * thumbnail_size / img->get_width();
- } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) {
-
- height = thumbnail_size;
- width = img->get_width() * thumbnail_size / img->get_height();
- } else {
-
- width = img->get_width();
- height = img->get_height();
+ Vector2 new_size = img->get_size();
+ if (new_size.x > p_size.x) {
+ new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x);
}
+ if (new_size.y > p_size.y) {
+ new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
+ }
+ img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
- img->resize(width, height);
post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
@@ -143,7 +138,7 @@ bool EditorImagePreviewPlugin::handles(const String &p_type) const {
return p_type == "Image";
}
-Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<Image> img = p_from;
@@ -153,8 +148,6 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const {
img = img->duplicate();
img->clear_mipmaps();
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
if (img->is_compressed()) {
if (img->decompress() != OK)
return Ref<Image>();
@@ -162,22 +155,15 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const {
img->convert(Image::FORMAT_RGBA8);
}
- int width, height;
- if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) {
-
- width = thumbnail_size;
- height = img->get_height() * thumbnail_size / img->get_width();
- } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) {
-
- height = thumbnail_size;
- width = img->get_width() * thumbnail_size / img->get_height();
- } else {
-
- width = img->get_width();
- height = img->get_height();
+ Vector2 new_size = img->get_size();
+ if (new_size.x > p_size.x) {
+ new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x);
+ }
+ if (new_size.y > p_size.y) {
+ new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
+ img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
- img->resize(width, height);
post_process_preview(img);
Ref<ImageTexture> ptex;
@@ -190,6 +176,9 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const {
EditorImagePreviewPlugin::EditorImagePreviewPlugin() {
}
+bool EditorImagePreviewPlugin::should_generate_small_preview() const {
+ return true;
+}
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////
bool EditorBitmapPreviewPlugin::handles(const String &p_type) const {
@@ -197,7 +186,7 @@ bool EditorBitmapPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "BitMap");
}
-Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<BitMap> bm = p_from;
@@ -227,8 +216,6 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const {
img.instance();
img->create(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_L8, data);
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
if (img->is_compressed()) {
if (img->decompress() != OK)
return Ref<Texture>();
@@ -236,22 +223,15 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const {
img->convert(Image::FORMAT_RGBA8);
}
- int width, height;
- if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) {
-
- width = thumbnail_size;
- height = img->get_height() * thumbnail_size / img->get_width();
- } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) {
-
- height = thumbnail_size;
- width = img->get_width() * thumbnail_size / img->get_height();
- } else {
-
- width = img->get_width();
- height = img->get_height();
+ Vector2 new_size = img->get_size();
+ if (new_size.x > p_size.x) {
+ new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x);
+ }
+ if (new_size.y > p_size.y) {
+ new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
+ img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
- img->resize(width, height);
post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
@@ -260,6 +240,10 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const {
return ptex;
}
+bool EditorBitmapPreviewPlugin::should_generate_small_preview() const {
+ return true;
+}
+
EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
}
@@ -269,12 +253,12 @@ bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "PackedScene");
}
-Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
- return generate_from_path(p_from->get_path());
+ return generate_from_path(p_from->get_path(), p_size);
}
-Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) const {
+Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const {
String temp_path = EditorSettings::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text();
@@ -323,7 +307,11 @@ bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Material"); //any material
}
-Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const {
+bool EditorMaterialPreviewPlugin::should_generate_small_preview() const {
+ return true;
+}
+
+Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<Material> material = p_from;
ERR_FAIL_COND_V(material.is_null(), Ref<Texture>());
@@ -346,10 +334,9 @@ Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const {
ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>());
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
img->convert(Image::FORMAT_RGBA8);
- img->resize(thumbnail_size, thumbnail_size);
+ int thumbnail_size = MAX(p_size.x, p_size.y);
+ img->resize(thumbnail_size, thumbnail_size, Image::INTERPOLATE_CUBIC);
post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
ptex->create_from_image(img, 0);
@@ -490,7 +477,7 @@ bool EditorScriptPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Script");
}
-Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<Script> scr = p_from;
if (scr.is_null())
@@ -512,10 +499,9 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const {
int line = 0;
int col = 0;
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
Ref<Image> img;
img.instance();
+ int thumbnail_size = MAX(p_size.x, p_size.y);
img->create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8);
Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
@@ -613,16 +599,15 @@ bool EditorAudioStreamPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "AudioStream");
}
-Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<AudioStream> stream = p_from;
ERR_FAIL_COND_V(stream.is_null(), Ref<Texture>());
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
PoolVector<uint8_t> img;
- int w = thumbnail_size;
- int h = thumbnail_size;
+
+ int w = p_size.x;
+ int h = p_size.y;
img.resize(w * h * 3);
PoolVector<uint8_t>::Write imgdata = img.write();
@@ -711,7 +696,7 @@ bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Mesh"); //any Mesh
}
-Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
Ref<Mesh> mesh = p_from;
ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>());
@@ -749,10 +734,17 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const {
VS::get_singleton()->instance_set_base(mesh_instance, RID());
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
img->convert(Image::FORMAT_RGBA8);
- img->resize(thumbnail_size, thumbnail_size);
+
+ Vector2 new_size = img->get_size();
+ if (new_size.x > p_size.x) {
+ new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x);
+ }
+ if (new_size.y > p_size.y) {
+ new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
+ }
+ img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
+
post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
@@ -825,15 +817,12 @@ bool EditorFontPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "DynamicFontData");
}
-Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) const {
+Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const {
Ref<DynamicFontData> SampledFont;
SampledFont.instance();
SampledFont->set_font_path(p_path);
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
-
Ref<DynamicFont> sampled_font;
sampled_font.instance();
sampled_font->set_size(50);
@@ -864,7 +853,15 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c
ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>());
img->convert(Image::FORMAT_RGBA8);
- img->resize(thumbnail_size, thumbnail_size);
+
+ Vector2 new_size = img->get_size();
+ if (new_size.x > p_size.x) {
+ new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x);
+ }
+ if (new_size.y > p_size.y) {
+ new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
+ }
+ img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
post_process_preview(img);
@@ -874,9 +871,9 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c
return ptex;
}
-Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) const {
+Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const {
- return generate_from_path(p_from->get_path());
+ return generate_from_path(p_from->get_path(), p_size);
}
EditorFontPreviewPlugin::EditorFontPreviewPlugin() {
diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
index 8bd7943383..ed5d2a3ecd 100644
--- a/editor/plugins/editor_preview_plugins.h
+++ b/editor/plugins/editor_preview_plugins.h
@@ -39,7 +39,8 @@ class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator)
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual bool should_generate_small_preview() const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorTexturePreviewPlugin();
};
@@ -48,7 +49,8 @@ class EditorImagePreviewPlugin : public EditorResourcePreviewGenerator {
GDCLASS(EditorImagePreviewPlugin, EditorResourcePreviewGenerator)
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual bool should_generate_small_preview() const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorImagePreviewPlugin();
};
@@ -57,7 +59,8 @@ class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator {
GDCLASS(EditorBitmapPreviewPlugin, EditorResourcePreviewGenerator)
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual bool should_generate_small_preview() const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorBitmapPreviewPlugin();
};
@@ -66,8 +69,8 @@ class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
- virtual Ref<Texture> generate_from_path(const String &p_path) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
+ virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const;
EditorPackedScenePreviewPlugin();
};
@@ -95,7 +98,8 @@ protected:
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual bool should_generate_small_preview() const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorMaterialPreviewPlugin();
~EditorMaterialPreviewPlugin();
@@ -104,7 +108,7 @@ public:
class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorScriptPreviewPlugin();
};
@@ -112,7 +116,7 @@ public:
class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator {
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorAudioStreamPreviewPlugin();
};
@@ -139,7 +143,7 @@ protected:
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
EditorMeshPreviewPlugin();
~EditorMeshPreviewPlugin();
@@ -162,8 +166,8 @@ protected:
public:
virtual bool handles(const String &p_type) const;
- virtual Ref<Texture> generate(const RES &p_from) const;
- virtual Ref<Texture> generate_from_path(const String &p_path) const;
+ virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const;
+ virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const;
EditorFontPreviewPlugin();
~EditorFontPreviewPlugin();
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp
index 4f8a307cc1..2f2e1dae81 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -319,13 +319,11 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) {
+void LightOccluder2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node || !node->get_occluder_polygon().is_valid())
return;
- Control *vpc = canvas_item_editor->get_viewport_control();
-
Vector<Vector2> poly;
if (wip_active)
@@ -353,9 +351,9 @@ void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) {
if (i == poly.size() - 1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) {
} else {
- vpc->draw_line(point, next_point, col, 2);
+ p_overlay->draw_line(point, next_point, col, 2);
}
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
+ p_overlay->draw_texture(handle, point - handle->get_size() * 0.5);
}
}
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h
index 39de8b1020..a1962892ee 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.h
+++ b/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -83,7 +83,7 @@ protected:
public:
Vector2 snap_point(const Vector2 &p_point) const;
- void forward_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
bool forward_gui_input(const Ref<InputEvent> &p_event);
void edit(Node *p_collision_polygon);
LightOccluder2DEditor(EditorNode *p_editor);
@@ -98,7 +98,7 @@ class LightOccluder2DEditorPlugin : public EditorPlugin {
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); }
- virtual void forward_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_canvas_draw_over_viewport(p_overlay); }
virtual String get_name() const { return "LightOccluder2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 96c1ad2f2b..88b3194490 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -288,7 +288,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void Path2DEditor::forward_draw_over_viewport(Control *p_overlay) {
+void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node)
return;
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 1e3955f84f..3a78657746 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -107,7 +107,7 @@ protected:
public:
bool forward_gui_input(const Ref<InputEvent> &p_event);
- void forward_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node *p_path2d);
Path2DEditor(EditorNode *p_editor);
};
@@ -121,7 +121,7 @@ class Path2DEditorPlugin : public EditorPlugin {
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); }
- virtual void forward_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
virtual String get_name() const { return "Path2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index bdeeaa106d..d4ddaf274f 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -317,6 +317,7 @@ void ScriptTextEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY:
_load_theme_settings();
+ _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("script_text_editor", "syntax_highlighter", 0));
break;
}
}
@@ -1058,6 +1059,7 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) {
}
// highlighter_menu->set_item_checked(p_idx, true);
set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
+ EditorSettings::get_singleton()->set_project_metadata("script_text_editor", "syntax_highlighter", p_idx);
}
void ScriptTextEditor::_bind_methods() {
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 51e58b712e..361271af89 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -426,7 +426,7 @@ void ShaderEditor::ensure_select_current() {
void ShaderEditor::edit(const Ref<Shader> &p_shader) {
- if (p_shader.is_null())
+ if (p_shader.is_null() || !p_shader->is_text_shader())
return;
shader = p_shader;
@@ -606,7 +606,7 @@ void ShaderEditorPlugin::edit(Object *p_object) {
bool ShaderEditorPlugin::handles(Object *p_object) const {
Shader *shader = Object::cast_to<Shader>(p_object);
- return shader != NULL;
+ return shader != NULL && shader->is_text_shader();
}
void ShaderEditorPlugin::make_visible(bool p_visible) {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 6df026843a..3e6a0ae81a 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2312,12 +2312,12 @@ void SpatialEditorViewport::_draw() {
EditorPluginList *over_plugin_list = EditorNode::get_singleton()->get_editor_plugins_over();
if (!over_plugin_list->empty()) {
- over_plugin_list->forward_draw_over_viewport(surface);
+ over_plugin_list->forward_spatial_draw_over_viewport(surface);
}
EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
if (!force_over_plugin_list->empty()) {
- force_over_plugin_list->forward_force_draw_over_viewport(surface);
+ force_over_plugin_list->forward_spatial_force_draw_over_viewport(surface);
}
if (surface->has_focus()) {
@@ -2346,7 +2346,6 @@ void SpatialEditorViewport::_draw() {
Point2 center = _point_to_screen(_edit.center);
VisualServer::get_singleton()->canvas_item_add_line(ci, _edit.mouse_pos, center, Color(0.4, 0.7, 1.0, 0.8));
}
-
if (previewing) {
Size2 ss = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
@@ -4418,6 +4417,8 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
void SpatialEditor::_init_indicators() {
{
+ origin_enabled = true;
+ grid_enabled = true;
indicator_mat.instance();
indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
@@ -4458,10 +4459,6 @@ void SpatialEditor::_init_indicators() {
VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF);
-
- origin_enabled = true;
- grid_enabled = true;
- last_grid_snap = 1;
}
{
@@ -5586,7 +5583,6 @@ void SpatialEditorPlugin::make_visible(bool p_visible) {
spatial_editor->show();
spatial_editor->set_process(true);
- spatial_editor->grab_focus();
} else {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 0e35ba8517..b7317cd593 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -510,7 +510,6 @@ private:
RID grid[3];
RID grid_instance[3];
bool grid_visible[3]; //currently visible
- float last_grid_snap;
bool grid_enable[3]; //should be always visible if true
bool grid_enabled;
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 3bf4140591..4ff7046a35 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -66,6 +66,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) {
el = el->next();
}
set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
+ EditorSettings::get_singleton()->set_project_metadata("text_editor", "syntax_highlighter", p_idx);
}
void TextEditor::_load_theme_settings() {
@@ -298,7 +299,7 @@ void TextEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY:
_load_theme_settings();
- set_syntax_highlighter(NULL);
+ _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("text_editor", "syntax_highlighter", 0));
break;
}
}
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index a0adbfccff..aa4338d775 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -686,7 +686,7 @@ void TileMapEditor::_erase_selection() {
}
}
-void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) {
+void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) {
Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell);
@@ -783,19 +783,19 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h
modulate.a = 0.5;
if (r.has_no_area())
- canvas_item_editor->draw_texture_rect(t, rect, false, modulate, p_transpose);
+ p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose);
else
- canvas_item_editor->draw_texture_rect_region(t, rect, r, modulate, p_transpose);
+ p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose);
}
-void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) {
+void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) {
PoolVector<Vector2> points = _bucket_fill(p_point, false, true);
PoolVector<Vector2>::Read pr = points.read();
int len = points.size();
for (int i = 0; i < len; ++i) {
- _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform);
+ _draw_cell(p_viewport, p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform);
}
}
@@ -1390,17 +1390,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
+void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node)
return;
Transform2D cell_xf = node->get_cell_transform();
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
+ Transform2D xform = p_overlay->get_canvas_transform() * node->get_global_transform();
Transform2D xform_inv = xform.affine_inverse();
- Size2 screen_size = canvas_item_editor->get_size();
+ Size2 screen_size = p_overlay->get_size();
{
Rect2 aabb;
aabb.position = node->world_to_map(xform_inv.xform(Vector2()));
@@ -1419,7 +1419,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
Vector2 to = xform.xform(node->map_to_world(Vector2(i, si.position.y + si.size.y + 1)));
Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
- canvas_item_editor->draw_line(from, to, col, 1);
+ p_overlay->draw_line(from, to, col, 1);
if (max_lines-- == 0)
break;
}
@@ -1439,7 +1439,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
Vector2 from = xform.xform(node->map_to_world(Vector2(i, j), true) + ofs);
Vector2 to = xform.xform(node->map_to_world(Vector2(i, j + 1), true) + ofs);
Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
- canvas_item_editor->draw_line(from, to, col, 1);
+ p_overlay->draw_line(from, to, col, 1);
if (max_lines-- == 0)
break;
@@ -1457,7 +1457,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
Vector2 to = xform.xform(node->map_to_world(Vector2(si.position.x + si.size.x + 1, i)));
Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
- canvas_item_editor->draw_line(from, to, col, 1);
+ p_overlay->draw_line(from, to, col, 1);
if (max_lines-- == 0)
break;
@@ -1476,7 +1476,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
Vector2 from = xform.xform(node->map_to_world(Vector2(j, i), true) + ofs);
Vector2 to = xform.xform(node->map_to_world(Vector2(j + 1, i), true) + ofs);
Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
- canvas_item_editor->draw_line(from, to, col, 1);
+ p_overlay->draw_line(from, to, col, 1);
if (max_lines-- == 0)
break;
@@ -1493,7 +1493,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, rectangle.size.y + 1)))));
points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(0, rectangle.size.y + 1)))));
- canvas_item_editor->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4));
+ p_overlay->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4));
}
if (mouse_over) {
@@ -1519,7 +1519,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
col = Color(1.0, 0.4, 0.2, 0.8);
for (int i = 0; i < 4; i++)
- canvas_item_editor->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2);
+ p_overlay->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2);
bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview");
if (tool == TOOL_SELECTING || tool == TOOL_PICKING || !bucket_preview) {
@@ -1538,7 +1538,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
- _draw_cell(ids[0], E->key(), flip_h, flip_v, transpose, xform);
+ _draw_cell(p_overlay, ids[0], E->key(), flip_h, flip_v, transpose, xform);
}
} else if (tool == TOOL_RECTANGLE_PAINT) {
@@ -1551,7 +1551,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
- _draw_cell(ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform);
+ _draw_cell(p_overlay, ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform);
}
}
} else if (tool == TOOL_PASTING) {
@@ -1573,7 +1573,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
TileData tcd = E->get();
- _draw_cell(tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform);
+ _draw_cell(p_overlay, tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform);
}
Rect2i duplicate = rectangle;
@@ -1585,12 +1585,12 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, duplicate.size.y + 1)))));
points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(0, duplicate.size.y + 1)))));
- canvas_item_editor->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2));
+ p_overlay->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2));
} else if (tool == TOOL_BUCKET) {
Vector<int> tiles = get_selected_tiles();
- _draw_fill_preview(tiles[0], over_tile, flip_h, flip_v, transpose, xform);
+ _draw_fill_preview(p_overlay, tiles[0], over_tile, flip_h, flip_v, transpose, xform);
} else {
@@ -1599,7 +1599,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) {
if (st.size() == 1 && st[0] == TileMap::INVALID_CELL)
return;
- _draw_cell(st[0], over_tile, flip_h, flip_v, transpose, xform);
+ _draw_cell(p_overlay, st[0], over_tile, flip_h, flip_v, transpose, xform);
}
}
}
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index c824824d56..74aece6f47 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -168,8 +168,8 @@ class TileMapEditor : public VBoxContainer {
void _select(const Point2i &p_from, const Point2i &p_to);
void _erase_selection();
- void _draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform);
- void _draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform);
+ void _draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform);
+ void _draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform);
void _clear_bucket_cache();
void _update_copydata();
@@ -206,7 +206,7 @@ public:
HBoxContainer *get_toolbar() const { return toolbar; }
bool forward_gui_input(const Ref<InputEvent> &p_event);
- void forward_draw_over_viewport(Control *p_overlay);
+ void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node *p_tile_map);
@@ -225,7 +225,7 @@ protected:
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); }
- virtual void forward_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_draw_over_viewport(p_overlay); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_canvas_draw_over_viewport(p_overlay); }
virtual String get_name() const { return "TileMap"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 207078d90f..39e50ec7f8 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -510,6 +510,17 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in
}
undo_redo->create_action("Nodes Connected");
+
+ List<VisualShader::Connection> conns;
+ visual_shader->get_node_connections(type, &conns);
+
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
+ if (E->get().to_node == to && E->get().to_port == p_to_index) {
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ }
+ }
+
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
undo_redo->add_do_method(this, "_update_graph");
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 1f5cd7fe0b..ff6832177e 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -830,6 +830,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
editor_data->get_undo_redo().commit_action();
+ editor->edit_node(new_node);
+
} break;
default: {
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index a28a111025..cc477314e9 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -492,17 +492,19 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
pinfo.usage = PropertyUsageFlags(int(prop[4]));
Variant var = prop[5];
- String hint_string = pinfo.hint_string;
- if (hint_string.begins_with("RES:") && hint_string != "RES:") {
- String path = hint_string.substr(4, hint_string.length());
- var = ResourceLoader::load(path);
- }
-
if (is_new_object) {
//don't update.. it's the same, instead refresh
debugObj->prop_list.push_back(pinfo);
}
+ if (var.get_type() == Variant::STRING) {
+ String str = var;
+ var = str.substr(4, str.length());
+
+ if (str.begins_with("PATH"))
+ var = ResourceLoader::load(var);
+ }
+
debugObj->prop_values[pinfo.name] = var;
}
@@ -573,9 +575,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
PropertyHint h = PROPERTY_HINT_NONE;
String hs = String();
- if (n.begins_with("*")) {
-
- n = n.substr(1, n.length());
+ if (v.get_type() == Variant::OBJECT) {
h = PROPERTY_HINT_OBJECT_ID;
String s = v;
s = s.replace("[", "");
@@ -596,9 +596,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
PropertyHint h = PROPERTY_HINT_NONE;
String hs = String();
- if (n.begins_with("*")) {
-
- n = n.substr(1, n.length());
+ if (v.get_type() == Variant::OBJECT) {
h = PROPERTY_HINT_OBJECT_ID;
String s = v;
s = s.replace("[", "");
@@ -619,9 +617,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
PropertyHint h = PROPERTY_HINT_NONE;
String hs = String();
- if (n.begins_with("*")) {
-
- n = n.substr(1, n.length());
+ if (v.get_type() == Variant::OBJECT) {
h = PROPERTY_HINT_OBJECT_ID;
String s = v;
s = s.replace("[", "");
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index e6eaabd9ce..5fdb6a5196 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -645,7 +645,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
}
set_items.clear();
input_action = INPUT_NONE;
- return true;
+ return set_items.size() > 0;
}
if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) {
diff --git a/modules/opensimplex/doc_classes/SimplexNoise.xml b/modules/opensimplex/doc_classes/SimplexNoise.xml
index 1be7b5896d..de29ff874c 100644
--- a/modules/opensimplex/doc_classes/SimplexNoise.xml
+++ b/modules/opensimplex/doc_classes/SimplexNoise.xml
@@ -20,7 +20,7 @@
print("Values:")
print(noise.get_noise_2d(1.0, 1.0))
print(noise.get_noise_3d(0.5, 3.0, 15.0))
- print(noise.get_noise_3d(0.5, 1.9, 4.7, 0.0))
+ print(noise.get_noise_4d(0.5, 1.9, 4.7, 0.0))
[/codeblock]
</description>
<tutorials>
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 365a6a5cae..24b9083964 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2239,13 +2239,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
_go_left();
}
- } else if (p_event->is_action("ui_up") && p_event->is_pressed()) {
+ } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !k->get_command()) {
if (!cursor_can_exit_tree) accept_event();
_go_up();
- } else if (p_event->is_action("ui_down") && p_event->is_pressed()) {
+ } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !k->get_command()) {
if (!cursor_can_exit_tree) accept_event();
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index d4456738ae..06bc12d774 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2116,6 +2116,12 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
node->set(name, value);
}
+ List<GroupInfo> groups;
+ get_groups(&groups);
+
+ for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next())
+ node->add_to_group(E->get().name, E->get().persistent);
+
node->set_name(get_name());
p_new_parent->add_child(node);
@@ -2210,6 +2216,12 @@ Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
node->set(name, get(name));
}
+ List<GroupInfo> groups;
+ get_groups(&groups);
+
+ for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next())
+ node->add_to_group(E->get().name, E->get().persistent);
+
for (int i = 0; i < get_child_count(); i++) {
get_child(i)->_duplicate_and_reown(node, p_reown_map);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 50bf8f38f7..b78b3a6ffb 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -178,6 +178,7 @@ PoolVector<int> BitmapFont::_get_kernings() const {
void BitmapFont::_set_textures(const Vector<Variant> &p_textures) {
+ textures.clear();
for (int i = 0; i < p_textures.size(); i++) {
Ref<Texture> tex = p_textures[i];
ERR_CONTINUE(!tex.is_valid());
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 1bfc41bd92..66bf3b4991 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -126,6 +126,11 @@ void Shader::get_default_texture_param_list(List<StringName> *r_textures) const
r_textures->push_back(E->key());
}
}
+
+bool Shader::is_text_shader() const {
+ return true;
+}
+
bool Shader::has_param(const StringName &p_param) const {
return params_cache.has(p_param);
@@ -235,8 +240,10 @@ Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resourc
void ResourceFormatSaverShader::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
- if (Object::cast_to<Shader>(*p_resource)) {
- p_extensions->push_back("shader");
+ if (const Shader *shader = Object::cast_to<Shader>(*p_resource)) {
+ if (shader->is_text_shader()) {
+ p_extensions->push_back("shader");
+ }
}
}
bool ResourceFormatSaverShader::recognize(const RES &p_resource) const {
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index 6c91205c0c..c2c205237f 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -79,6 +79,8 @@ public:
Ref<Texture> get_default_texture_param(const StringName &p_param) const;
void get_default_texture_param_list(List<StringName> *r_textures) const;
+ virtual bool is_text_shader() const;
+
_FORCE_INLINE_ StringName remap_param(const StringName &p_param) const {
if (params_cache_dirty)
get_param_list(NULL);
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 6bfb6ec5bf..f12ea8f2bb 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -414,6 +414,10 @@ Shader::Mode VisualShader::get_mode() const {
return shader_mode;
}
+bool VisualShader::is_text_shader() const {
+ return false;
+}
+
String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const {
Ref<VisualShaderNode> node = get_node(p_type, p_node);
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 70d2425304..2867daac3a 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -141,6 +141,8 @@ public:
void set_mode(Mode p_mode);
virtual Mode get_mode() const;
+ virtual bool is_text_shader() const;
+
void set_graph_offset(const Vector2 &p_offset);
Vector2 get_graph_offset() const;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 35236b23f1..4718eb14a5 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -3437,8 +3437,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
}
}
} else {
+ ConstantNode::Value value = values[0];
for (int i = 1; i < cardinality; i++) {
- values.push_back(values[0]);
+ values.push_back(value);
}
}
} else if (values.size() != cardinality) {