diff options
Diffstat (limited to 'editor')
25 files changed, 256 insertions, 1714 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index e9719f8618..2edfcced60 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1727,7 +1727,7 @@ void AnimationTimelineEdit::update_values() { time_icon->set_tooltip(TTR("Animation length (frames)")); } else { length->set_value(animation->get_length()); - length->set_step(0.01); + length->set_step(0.001); length->set_tooltip(TTR("Animation length (seconds)")); time_icon->set_tooltip(TTR("Animation length (seconds)")); } @@ -1890,7 +1890,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() { length = memnew(EditorSpinSlider); length->set_min(0.001); length->set_max(36000); - length->set_step(0.01); + length->set_step(0.001); length->set_allow_greater(true); length->set_custom_minimum_size(Vector2(70 * EDSCALE, 0)); length->set_hide_slider(true); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 04fe6e5ce6..107ecac3b0 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -675,9 +675,12 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess if (f == "") break; + if (da->current_is_hidden()) + continue; + if (da->current_is_dir()) { - if (f.begins_with(".")) //ignore hidden and . / .. + if (f.begins_with(".")) // Ignore special and . / .. continue; if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) // skip if another project inside this @@ -871,9 +874,12 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const if (f == "") break; + if (da->current_is_hidden()) + continue; + if (da->current_is_dir()) { - if (f.begins_with(".")) //ignore hidden and . / .. + if (f.begins_with(".")) // Ignore special and . / .. continue; int idx = p_dir->find_dir_index(f); @@ -1059,8 +1065,12 @@ void EditorFileSystem::get_changed_sources(List<String> *r_changed) { void EditorFileSystem::scan_changes() { - if (scanning || scanning_changes || thread) + if (first_scan || // Prevent a premature changes scan from inhibiting the first full scan + scanning || scanning_changes || thread) { + scan_changes_pending = true; + set_process(true); return; + } _update_extensions(); sources_changed.clear(); @@ -1105,15 +1115,17 @@ void EditorFileSystem::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - if (use_threads && thread) { + Thread *active_thread = thread ? thread : thread_sources; + if (use_threads && active_thread) { //abort thread if in progress abort_scan = true; while (scanning) { OS::get_singleton()->delay_usec(1000); } - Thread::wait_to_finish(thread); - memdelete(thread); + Thread::wait_to_finish(active_thread); + memdelete(active_thread); thread = NULL; + thread_sources = NULL; WARN_PRINT("Scan thread aborted..."); set_process(false); } @@ -1164,6 +1176,11 @@ void EditorFileSystem::_notification(int p_what) { _queue_update_script_classes(); first_scan = false; } + + if (!is_processing() && scan_changes_pending) { + scan_changes_pending = false; + scan_changes(); + } } } break; } @@ -2138,6 +2155,7 @@ EditorFileSystem::EditorFileSystem() { scan_total = 0; update_script_classes_queued = false; first_scan = true; + scan_changes_pending = false; revalidate_import_files = false; } diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index ce9936f983..381acc0fe2 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -145,6 +145,7 @@ class EditorFileSystem : public Node { bool scanning; bool importing; bool first_scan; + bool scan_changes_pending; float scan_total; String filesystem_settings_version_for_import; bool revalidate_import_files; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7d0601e8db..d6dcbf7e84 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -62,6 +62,8 @@ #include "scene/gui/texture_progress.h" #include "scene/gui/tool_button.h" #include "scene/resources/packed_scene.h" +#include "servers/navigation_2d_server.h" +#include "servers/navigation_server.h" #include "servers/physics_2d_server.h" #include "editor/audio_stream_preview.h" @@ -110,7 +112,6 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/animation_state_machine_editor.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/plugins/animation_tree_player_editor_plugin.h" #include "editor/plugins/asset_library_editor_plugin.h" #include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/baked_lightmap_editor_plugin.h" @@ -5584,6 +5585,8 @@ EditorNode::EditorNode() { VisualServer::get_singleton()->textures_keep_original(true); VisualServer::get_singleton()->set_debug_generate_wireframes(true); + NavigationServer::get_singleton()->set_active(false); // no nav by default if editor + PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor ScriptServer::set_scripting_enabled(false); // no scripting by default if editor @@ -6646,7 +6649,6 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(MultiMeshEditorPlugin(this))); add_editor_plugin(memnew(MeshInstanceEditorPlugin(this))); add_editor_plugin(memnew(AnimationTreeEditorPlugin(this))); - add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this))); add_editor_plugin(memnew(MeshLibraryEditorPlugin(this))); add_editor_plugin(memnew(StyleBoxEditorPlugin(this))); add_editor_plugin(memnew(SpriteEditorPlugin(this))); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 5041441ac3..684942dbad 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1782,6 +1782,14 @@ void FileSystemDock::_resource_created() const { Resource *r = Object::cast_to<Resource>(c); ERR_FAIL_COND(!r); + PackedScene *scene = Object::cast_to<PackedScene>(r); + if (scene) { + Node *node = memnew(Node); + node->set_name("Node"); + scene->pack(node); + memdelete(node); + } + REF res(r); editor->push_item(c); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 4ab90ad3e4..b24a5c38f2 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -235,9 +235,11 @@ void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) { if (file == "") break; - // Ignore special dirs and hidden dirs (such as .git and .import) + // Ignore special dirs (such as .git and .import) if (file == "." || file == ".." || file.begins_with(".")) continue; + if (dir->current_is_hidden()) + continue; if (dir->current_is_dir()) out_folders.append(file); diff --git a/editor/icons/icon_animation_tree_player.svg b/editor/icons/icon_animation_tree_player.svg deleted file mode 100644 index 718eaac2d2..0000000000 --- a/editor/icons/icon_animation_tree_player.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h1.166v-2h1.834v2h8v-2h2v2h1v-14h-1v2h-2v-2h-8v2h-1.834v-2zm4 3h2v1 1h1 3v2h-2v1 1h1 1v2h-1-2a1.0001 1.0001 0 0 1 -1-1v-1-2h-1a1.0001 1.0001 0 0 1 -1-1v-1-1zm-2.834 1h1.834v2h-1.834zm9.834 0h2v2h-2zm-9.834 4h1.834v2h-1.834zm9.834 0h2v2h-2z" fill="#cea4f1"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_godot_docs.svg b/editor/icons/icon_godot_docs.svg deleted file mode 100644 index e38885aed9..0000000000 --- a/editor/icons/icon_godot_docs.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".32031" transform="matrix(.017241 0 0 .017241 -.82759 -2.7)"><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 919.24 771.67)"/><path d="m0 0v-59.041c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325h.134c4.795 6.12 9.232 12.569 13.487 19.449-5.651 9.62-12.575 18.217-19.976 26.182-6.864-3.455-13.531-7.369-19.828-11.534-3.151 3.132-6.7 5.694-10.186 8.372-3.425 2.751-7.285 4.768-10.946 7.118 1.09 8.117 1.629 16.108 1.846 24.448-9.446 4.754-19.519 7.906-29.708 10.17-4.068-6.837-7.788-14.241-11.028-21.479-3.842.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.253-6.88 8.693-13.329 13.487-19.449z" fill="#478cbf" transform="matrix(4.1626 0 0 -4.1626 104.7 525.91)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.133c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.1626 0 0 -4.1626 784.07 817.24)"/><path d="m0 0c0-12.052-9.765-21.815-21.813-21.815-12.042 0-21.81 9.763-21.81 21.815 0 12.044 9.768 21.802 21.81 21.802 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 389.21 625.67)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.1626 0 0 -4.1626 367.37 631.06)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 511.99 724.74)"/><path d="m0 0c0-12.052 9.765-21.815 21.815-21.815 12.041 0 21.808 9.763 21.808 21.815 0 12.044-9.767 21.802-21.808 21.802-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 634.79 625.67)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.1626 0 0 -4.1626 656.64 631.06)"/></g><path d="m4 5a3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3h2a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0 -3-3 3 3 0 0 0 -2.8262 2h-2.3496a3 3 0 0 0 -2.8242-2zm0 1a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_particle_attractor_2d.svg b/editor/icons/icon_particle_attractor_2d.svg deleted file mode 100644 index 85f289dc4b..0000000000 --- a/editor/icons/icon_particle_attractor_2d.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a3 7 0 0 0 -2.0801 1.9668 7 3 45 0 0 -2.8691.083984 7 3 45 0 0 -.080078 2.8633 7 3 0 0 0 -1.9707 2.0859 7 3 0 0 0 1.9668 2.0801 3 7 45 0 0 .083984 2.8691 3 7 45 0 0 2.8633.080078 3 7 0 0 0 2.0859 1.9707 3 7 0 0 0 2.0801-1.9668 7 3 45 0 0 2.8691-.083984 7 3 45 0 0 .080078-2.8633 7 3 0 0 0 1.9707-2.0859 7 3 0 0 0 -1.9668-2.0801 3 7 45 0 0 -.083984-2.8691 3 7 45 0 0 -2.8633-.080078 3 7 0 0 0 -2.0859-1.9707zm0 1a2 6 0 0 1 1.2598 1.3438 3 7 45 0 0 -1.2578.75977 7 3 45 0 0 -1.2637-.75781 2 6 0 0 1 1.2617-1.3457zm-3.6348 1.5293a6 2 45 0 1 1.2344.28906 3 7 0 0 0 -.35352 1.4238 7 3 0 0 0 -1.4297.35742 6 2 45 0 1 -.058594-1.8418 6 2 45 0 1 .60742-.22852zm7.0762.0039062a2 6 45 0 1 .80078.22461 2 6 45 0 1 -.060547 1.8418 7 3 0 0 0 -1.4238-.35352 3 7 0 0 0 -.35742-1.4297 2 6 45 0 1 1.041-.2832zm-4.998.70703a6 2 45 0 1 .74023.4707 3 7 45 0 0 -.41211.33984 7 3 0 0 0 -.52344.048828 2 6 0 0 1 .19531-.85938zm3.1152.0019531a2 6 0 0 1 .18945.85547 7 3 0 0 0 -.5293-.050781 7 3 45 0 0 -.4043-.33594 2 6 45 0 1 .74414-.46875zm-1.5586 1.7578a6 2 0 0 1 .82031.021484 6 2 45 0 1 .59375.56445 6 2 45 0 1 .56445.59375 2 6 0 0 1 .021484.82031 2 6 0 0 1 -.021484.82031 2 6 45 0 1 -.56445.59375 2 6 45 0 1 -.59375.56445 6 2 0 0 1 -.82031.021484 6 2 0 0 1 -.82031-.021484 6 2 45 0 1 -.59375-.56445 6 2 45 0 1 -.56445-.59375 2 6 0 0 1 -.021484-.82031 2 6 0 0 1 .021484-.82031 2 6 45 0 1 .56445-.59375 2 6 45 0 1 .59375-.56445 6 2 0 0 1 .82031-.021484zm2.9004.24805a6 2 0 0 1 .85938.19531 2 6 45 0 1 -.4707.74023 7 3 45 0 0 -.33984-.41211 3 7 0 0 0 -.048828-.52344zm-5.8027.0039062a3 7 0 0 0 -.050781.5293 3 7 45 0 0 -.33594.4043 6 2 45 0 1 -.46875-.74414 6 2 0 0 1 .85547-.18945zm7.5566.48633a6 2 0 0 1 1.3457 1.2617 6 2 0 0 1 -1.3438 1.2598 7 3 45 0 0 -.75977-1.2578 3 7 45 0 0 .75781-1.2637zm-9.3105.0019532a7 3 45 0 0 .75977 1.2578 3 7 45 0 0 -.75781 1.2637 6 2 0 0 1 -1.3457-1.2617 6 2 0 0 1 1.3438-1.2598zm4.6562.25977a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm3.2891 1.8145a6 2 45 0 1 .46875.74414 6 2 0 0 1 -.85547.18945 3 7 0 0 0 .050781-.5293 3 7 45 0 0 .33594-.4043zm-6.5781.0019531a7 3 45 0 0 .33984.41211 3 7 0 0 0 .048828.52344 6 2 0 0 1 -.85938-.19531 2 6 45 0 1 .4707-.74023zm-.89258 1.584a7 3 0 0 0 1.4238.35352 3 7 0 0 0 .35742 1.4297 2 6 45 0 1 -1.8418.058594 2 6 45 0 1 .060547-1.8418zm8.3652 0a6 2 45 0 1 .058594 1.8418 6 2 45 0 1 -1.8418-.060547 3 7 0 0 0 .35352-1.4238 7 3 0 0 0 1.4297-.35742zm-2.4316.5a2 6 0 0 1 -.19531.85938 6 2 45 0 1 -.74023-.4707 3 7 45 0 0 .41211-.33984 7 3 0 0 0 .52344-.048828zm-3.5.001953a7 3 0 0 0 .5293.050781 7 3 45 0 0 .4043.33594 2 6 45 0 1 -.74414.46875 2 6 0 0 1 -.18945-.85547zm1.7461.99414a7 3 45 0 0 1.2637.75781 2 6 0 0 1 -1.2617 1.3457 2 6 0 0 1 -1.2598-1.3438 3 7 45 0 0 1.2578-.75977z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
\ No newline at end of file diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index b65482cc6b..ecd1e341d1 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -337,6 +337,7 @@ void InspectorDock::_notification(int p_what) { history_menu->set_icon(get_icon("History", "EditorIcons")); object_menu->set_icon(get_icon("Tools", "EditorIcons")); warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + warning->add_color_override("font_color", get_color("warning_color", "Editor")); } break; } } @@ -584,6 +585,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { add_child(warning); warning->set_text(TTR("Changes may be lost!")); warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + warning->add_color_override("font_color", get_color("warning_color", "Editor")); warning->set_clip_text(true); warning->hide(); warning->connect("pressed", this, "_warning_pressed"); diff --git a/editor/plugins/animation_tree_player_editor_plugin.cpp b/editor/plugins/animation_tree_player_editor_plugin.cpp deleted file mode 100644 index 2b365feec5..0000000000 --- a/editor/plugins/animation_tree_player_editor_plugin.cpp +++ /dev/null @@ -1,1451 +0,0 @@ -/*************************************************************************/ -/* animation_tree_player_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "animation_tree_player_editor_plugin.h" - -#include "core/io/resource_loader.h" -#include "core/os/input.h" -#include "core/os/keyboard.h" -#include "core/project_settings.h" -#include "editor/editor_scale.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/panel.h" -#include "scene/main/viewport.h" - -void AnimationTreePlayerEditor::edit(AnimationTreePlayer *p_anim_tree) { - - anim_tree = p_anim_tree; - - if (!anim_tree) { - hide(); - } else { - order.clear(); - p_anim_tree->get_node_list(&order); - /* - for(List<StringName>::Element* E=order.front();E;E=E->next()) { - - if (E->get() >= (int)last_id) - last_id=E->get()+1; - }*/ - play_button->set_pressed(p_anim_tree->is_active()); - //read the orders - } -} - -Size2 AnimationTreePlayerEditor::_get_maximum_size() { - - Size2 max; - - for (List<StringName>::Element *E = order.front(); E; E = E->next()) { - - Point2 pos = anim_tree->node_get_position(E->get()); - - if (click_type == CLICK_NODE && click_node == E->get()) { - - pos += click_motion - click_pos; - } - pos += get_node_size(E->get()); - if (pos.x > max.x) - max.x = pos.x; - if (pos.y > max.y) - max.y = pos.y; - } - - return max; -} - -const char *AnimationTreePlayerEditor::_node_type_names[] = { "Output", "Animation", "OneShot", "Mix", "Blend2", "Blend3", "Blend4", "TimeScale", "TimeSeek", "Transition" }; - -Size2 AnimationTreePlayerEditor::get_node_size(const StringName &p_node) const { - - AnimationTreePlayer::NodeType type = anim_tree->node_get_type(p_node); - - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - Ref<Font> font = get_font("font", "PopupMenu"); - - Size2 size = style->get_minimum_size(); - - int count = 2; // title and name - int inputs = anim_tree->node_get_input_count(p_node); - count += inputs ? inputs : 1; - String name = p_node; - - float name_w = font->get_string_size(name).width; - float type_w = font->get_string_size(String(_node_type_names[type])).width; - float max_w = MAX(name_w, type_w); - - switch (type) { - case AnimationTreePlayer::NODE_TIMESEEK: - case AnimationTreePlayer::NODE_OUTPUT: { - } break; - case AnimationTreePlayer::NODE_ANIMATION: - case AnimationTreePlayer::NODE_ONESHOT: - case AnimationTreePlayer::NODE_MIX: - case AnimationTreePlayer::NODE_BLEND2: - case AnimationTreePlayer::NODE_BLEND3: - case AnimationTreePlayer::NODE_BLEND4: - case AnimationTreePlayer::NODE_TIMESCALE: - case AnimationTreePlayer::NODE_TRANSITION: { - - size.height += font->get_height(); - } break; - case AnimationTreePlayer::NODE_MAX: { - } - } - - size.x += max_w + 20; - size.y += count * (font->get_height() + get_constant("vseparation", "PopupMenu")); - - return size; -} - -void AnimationTreePlayerEditor::_edit_dialog_changede(String) { - - edit_dialog->hide(); -} - -void AnimationTreePlayerEditor::_edit_dialog_changeds(String s) { - - _edit_dialog_changed(); -} - -void AnimationTreePlayerEditor::_edit_dialog_changedf(float) { - - _edit_dialog_changed(); -} - -void AnimationTreePlayerEditor::_edit_dialog_changed() { - - if (updating_edit) - return; - - if (renaming_edit) { - - if (anim_tree->node_rename(edited_node, edit_line[0]->get_text()) == OK) { - for (List<StringName>::Element *E = order.front(); E; E = E->next()) { - - if (E->get() == edited_node) - E->get() = edit_line[0]->get_text(); - } - edited_node = edit_line[0]->get_text(); - } - update(); - return; - } - - AnimationTreePlayer::NodeType type = anim_tree->node_get_type(edited_node); - - switch (type) { - - case AnimationTreePlayer::NODE_TIMESCALE: - anim_tree->timescale_node_set_scale(edited_node, edit_line[0]->get_text().to_double()); - break; - case AnimationTreePlayer::NODE_ONESHOT: - anim_tree->oneshot_node_set_fadein_time(edited_node, edit_line[0]->get_text().to_double()); - anim_tree->oneshot_node_set_fadeout_time(edited_node, edit_line[1]->get_text().to_double()); - anim_tree->oneshot_node_set_autorestart_delay(edited_node, edit_line[2]->get_text().to_double()); - anim_tree->oneshot_node_set_autorestart_random_delay(edited_node, edit_line[3]->get_text().to_double()); - anim_tree->oneshot_node_set_autorestart(edited_node, edit_check->is_pressed()); - anim_tree->oneshot_node_set_mix_mode(edited_node, edit_option->get_selected()); - - break; - - case AnimationTreePlayer::NODE_MIX: - - anim_tree->mix_node_set_amount(edited_node, edit_scroll[0]->get_value()); - break; - case AnimationTreePlayer::NODE_BLEND2: - anim_tree->blend2_node_set_amount(edited_node, edit_scroll[0]->get_value()); - - break; - - case AnimationTreePlayer::NODE_BLEND3: - anim_tree->blend3_node_set_amount(edited_node, edit_scroll[0]->get_value()); - - break; - case AnimationTreePlayer::NODE_BLEND4: - - anim_tree->blend4_node_set_amount(edited_node, Point2(edit_scroll[0]->get_value(), edit_scroll[1]->get_value())); - - break; - - case AnimationTreePlayer::NODE_TRANSITION: { - anim_tree->transition_node_set_xfade_time(edited_node, edit_line[0]->get_text().to_double()); - if (anim_tree->transition_node_get_current(edited_node) != edit_option->get_selected()) - anim_tree->transition_node_set_current(edited_node, edit_option->get_selected()); - } break; - default: { - } - } -} - -void AnimationTreePlayerEditor::_edit_dialog_animation_changed() { - - Ref<Animation> anim = property_editor->get_variant().operator RefPtr(); - anim_tree->animation_node_set_animation(edited_node, anim); - update(); -} - -void AnimationTreePlayerEditor::_edit_dialog_edit_animation() { - - if (Engine::get_singleton()->is_editor_hint()) { - get_tree()->get_root()->get_child(0)->call("_resource_selected", property_editor->get_variant().operator RefPtr()); - }; -}; - -void AnimationTreePlayerEditor::_edit_oneshot_start() { - - anim_tree->oneshot_node_start(edited_node); -} - -void AnimationTreePlayerEditor::_play_toggled() { - - anim_tree->set_active(play_button->is_pressed()); -} - -void AnimationTreePlayerEditor::_master_anim_menu_item(int p_item) { - - if (p_item == 0) - _edit_filters(); - else { - - String str = master_anim_popup->get_item_text(p_item); - anim_tree->animation_node_set_master_animation(edited_node, str); - } - update(); -} - -void AnimationTreePlayerEditor::_popup_edit_dialog() { - - updating_edit = true; - - for (int i = 0; i < 2; i++) - edit_scroll[i]->hide(); - - for (int i = 0; i < 4; i++) { - - edit_line[i]->hide(); - edit_label[i]->hide(); - } - - edit_option->hide(); - edit_button->hide(); - filter_button->hide(); - edit_check->hide(); - - Point2 pos = anim_tree->node_get_position(edited_node) - Point2(h_scroll->get_value(), v_scroll->get_value()); - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - Size2 size = get_node_size(edited_node); - Point2 popup_pos(pos.x + style->get_margin(MARGIN_LEFT), pos.y + size.y - style->get_margin(MARGIN_BOTTOM)); - popup_pos += get_global_position(); - - if (renaming_edit) { - - edit_label[0]->set_text(TTR("New name:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_line[0]->set_begin(Point2(15, 25)); - edit_line[0]->set_text(edited_node); - edit_line[0]->show(); - edit_dialog->set_size(Size2(150, 50)); - - } else { - - AnimationTreePlayer::NodeType type = anim_tree->node_get_type(edited_node); - - switch (type) { - - case AnimationTreePlayer::NODE_ANIMATION: - - if (anim_tree->get_master_player() != NodePath() && anim_tree->has_node(anim_tree->get_master_player()) && Object::cast_to<AnimationPlayer>(anim_tree->get_node(anim_tree->get_master_player()))) { - - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(anim_tree->get_node(anim_tree->get_master_player())); - master_anim_popup->clear(); - master_anim_popup->add_item(TTR("Edit Filters")); - master_anim_popup->add_separator(); - List<StringName> sn; - ap->get_animation_list(&sn); - sn.sort_custom<StringName::AlphCompare>(); - for (List<StringName>::Element *E = sn.front(); E; E = E->next()) { - master_anim_popup->add_item(E->get()); - } - - master_anim_popup->set_position(popup_pos); - master_anim_popup->popup(); - } else { - property_editor->edit(this, "", Variant::OBJECT, anim_tree->animation_node_get_animation(edited_node), PROPERTY_HINT_RESOURCE_TYPE, "Animation"); - property_editor->set_position(popup_pos); - property_editor->popup(); - updating_edit = false; - } - return; - case AnimationTreePlayer::NODE_TIMESCALE: - edit_label[0]->set_text(TTR("Scale:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_line[0]->set_begin(Point2(15, 25)); - edit_line[0]->set_text(rtos(anim_tree->timescale_node_get_scale(edited_node))); - edit_line[0]->show(); - edit_dialog->set_size(Size2(150, 50)); - break; - case AnimationTreePlayer::NODE_ONESHOT: - edit_label[0]->set_text(TTR("Fade In (s):")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_line[0]->set_begin(Point2(15, 25)); - edit_line[0]->set_text(rtos(anim_tree->oneshot_node_get_fadein_time(edited_node))); - edit_line[0]->show(); - edit_label[1]->set_text(TTR("Fade Out (s):")); - edit_label[1]->set_position(Point2(5, 55)); - edit_label[1]->show(); - edit_line[1]->set_begin(Point2(15, 75)); - edit_line[1]->set_text(rtos(anim_tree->oneshot_node_get_fadeout_time(edited_node))); - edit_line[1]->show(); - - edit_option->clear(); - edit_option->add_item(TTR("Blend"), 0); - edit_option->add_item(TTR("Mix"), 1); - edit_option->set_begin(Point2(15, 105)); - - edit_option->select(anim_tree->oneshot_node_get_mix_mode(edited_node)); - edit_option->show(); - - edit_check->set_text(TTR("Auto Restart:")); - edit_check->set_begin(Point2(15, 125)); - edit_check->set_pressed(anim_tree->oneshot_node_has_autorestart(edited_node)); - edit_check->show(); - - edit_label[2]->set_text(TTR("Restart (s):")); - edit_label[2]->set_position(Point2(5, 145)); - edit_label[2]->show(); - edit_line[2]->set_begin(Point2(15, 165)); - edit_line[2]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_delay(edited_node))); - edit_line[2]->show(); - edit_label[3]->set_text(TTR("Random Restart (s):")); - edit_label[3]->set_position(Point2(5, 195)); - edit_label[3]->show(); - edit_line[3]->set_begin(Point2(15, 215)); - edit_line[3]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_random_delay(edited_node))); - edit_line[3]->show(); - - filter_button->set_begin(Point2(10, 245)); - filter_button->show(); - - edit_button->set_begin(Point2(10, 268)); - edit_button->set_text(TTR("Start!")); - - edit_button->show(); - - edit_dialog->set_size(Size2(180, 293)); - - break; - - case AnimationTreePlayer::NODE_MIX: - - edit_label[0]->set_text(TTR("Amount:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_scroll[0]->set_min(0); - edit_scroll[0]->set_max(1); - edit_scroll[0]->set_step(0.01); - edit_scroll[0]->set_value(anim_tree->mix_node_get_amount(edited_node)); - edit_scroll[0]->set_begin(Point2(15, 25)); - edit_scroll[0]->show(); - edit_dialog->set_size(Size2(150, 50)); - - break; - case AnimationTreePlayer::NODE_BLEND2: - edit_label[0]->set_text(TTR("Blend:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_scroll[0]->set_min(0); - edit_scroll[0]->set_max(1); - edit_scroll[0]->set_step(0.01); - edit_scroll[0]->set_value(anim_tree->blend2_node_get_amount(edited_node)); - edit_scroll[0]->set_begin(Point2(15, 25)); - edit_scroll[0]->show(); - filter_button->set_begin(Point2(10, 47)); - filter_button->show(); - edit_dialog->set_size(Size2(150, 74)); - - break; - - case AnimationTreePlayer::NODE_BLEND3: - edit_label[0]->set_text(TTR("Blend:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_scroll[0]->set_min(-1); - edit_scroll[0]->set_max(1); - edit_scroll[0]->set_step(0.01); - edit_scroll[0]->set_value(anim_tree->blend3_node_get_amount(edited_node)); - edit_scroll[0]->set_begin(Point2(15, 25)); - edit_scroll[0]->show(); - edit_dialog->set_size(Size2(150, 50)); - - break; - case AnimationTreePlayer::NODE_BLEND4: - - edit_label[0]->set_text(TTR("Blend 0:")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_scroll[0]->set_min(0); - edit_scroll[0]->set_max(1); - edit_scroll[0]->set_step(0.01); - edit_scroll[0]->set_value(anim_tree->blend4_node_get_amount(edited_node).x); - edit_scroll[0]->set_begin(Point2(15, 25)); - edit_scroll[0]->show(); - edit_label[1]->set_text(TTR("Blend 1:")); - edit_label[1]->set_position(Point2(5, 55)); - edit_label[1]->show(); - edit_scroll[1]->set_min(0); - edit_scroll[1]->set_max(1); - edit_scroll[1]->set_step(0.01); - edit_scroll[1]->set_value(anim_tree->blend4_node_get_amount(edited_node).y); - edit_scroll[1]->set_begin(Point2(15, 75)); - edit_scroll[1]->show(); - edit_dialog->set_size(Size2(150, 100)); - - break; - - case AnimationTreePlayer::NODE_TRANSITION: { - - edit_label[0]->set_text(TTR("X-Fade Time (s):")); - edit_label[0]->set_position(Point2(5, 5)); - edit_label[0]->show(); - edit_line[0]->set_begin(Point2(15, 25)); - edit_line[0]->set_text(rtos(anim_tree->transition_node_get_xfade_time(edited_node))); - edit_line[0]->show(); - - edit_label[1]->set_text(TTR("Current:")); - edit_label[1]->set_position(Point2(5, 55)); - edit_label[1]->show(); - edit_option->set_begin(Point2(15, 75)); - - edit_option->clear(); - - for (int i = 0; i < anim_tree->transition_node_get_input_count(edited_node); i++) { - edit_option->add_item(itos(i), i); - } - - edit_option->select(anim_tree->transition_node_get_current(edited_node)); - edit_option->show(); - edit_dialog->set_size(Size2(150, 100)); - - } break; - default: { - } - } - } - - edit_dialog->set_position(popup_pos); - edit_dialog->popup(); - - updating_edit = false; -} - -void AnimationTreePlayerEditor::_draw_node(const StringName &p_node) { - - RID ci = get_canvas_item(); - AnimationTreePlayer::NodeType type = anim_tree->node_get_type(p_node); - - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - Ref<Font> font = get_font("font", "PopupMenu"); - Color font_color = get_color("font_color", "PopupMenu"); - Color font_color_title = get_color("font_color_hover", "PopupMenu"); - font_color_title.a *= 0.8; - Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons"); - - Size2 size = get_node_size(p_node); - Point2 pos = anim_tree->node_get_position(p_node); - if (click_type == CLICK_NODE && click_node == p_node) { - - pos += click_motion - click_pos; - if (pos.x < 5) - pos.x = 5; - if (pos.y < 5) - pos.y = 5; - } - - pos -= Point2(h_scroll->get_value(), v_scroll->get_value()); - - style->draw(ci, Rect2(pos, size)); - - float w = size.width - style->get_minimum_size().width; - float h = font->get_height() + get_constant("vseparation", "PopupMenu"); - - Point2 ofs = style->get_offset() + pos; - Point2 ascofs(0, font->get_ascent()); - - Color bx = font_color_title; - bx.a *= 0.1; - draw_rect(Rect2(ofs, Size2(size.width - style->get_minimum_size().width, font->get_height())), bx); - font->draw_halign(ci, ofs + ascofs, HALIGN_CENTER, w, String(_node_type_names[type]), font_color_title); - - ofs.y += h; - font->draw_halign(ci, ofs + ascofs, HALIGN_CENTER, w, p_node, font_color); - ofs.y += h; - - int inputs = anim_tree->node_get_input_count(p_node); - - float icon_h_ofs = Math::floor((font->get_height() - slot_icon->get_height()) / 2.0) + 1; - - if (type != AnimationTreePlayer::NODE_OUTPUT) - slot_icon->draw(ci, ofs + Point2(w, icon_h_ofs)); //output - - if (inputs) { - for (int i = 0; i < inputs; i++) { - - slot_icon->draw(ci, ofs + Point2(-slot_icon->get_width(), icon_h_ofs)); - String text; - switch (type) { - - case AnimationTreePlayer::NODE_TIMESCALE: - case AnimationTreePlayer::NODE_TIMESEEK: text = "in"; break; - case AnimationTreePlayer::NODE_OUTPUT: text = "out"; break; - case AnimationTreePlayer::NODE_ANIMATION: break; - case AnimationTreePlayer::NODE_ONESHOT: text = (i == 0 ? "in" : "add"); break; - case AnimationTreePlayer::NODE_BLEND2: - case AnimationTreePlayer::NODE_MIX: text = (i == 0 ? "a" : "b"); break; - case AnimationTreePlayer::NODE_BLEND3: - switch (i) { - case 0: text = "b-"; break; - case 1: text = "a"; break; - case 2: text = "b+"; break; - } - break; - - case AnimationTreePlayer::NODE_BLEND4: - switch (i) { - case 0: text = "a0"; break; - case 1: text = "b0"; break; - case 2: text = "a1"; break; - case 3: text = "b1"; break; - } - break; - - case AnimationTreePlayer::NODE_TRANSITION: - text = itos(i); - if (anim_tree->transition_node_has_input_auto_advance(p_node, i)) - text += "->"; - - break; - default: { - } - } - font->draw(ci, ofs + ascofs + Point2(3, 0), text, font_color); - - ofs.y += h; - } - } else { - ofs.y += h; - } - - Ref<StyleBox> pg_bg = get_stylebox("bg", "ProgressBar"); - Ref<StyleBox> pg_fill = get_stylebox("fill", "ProgressBar"); - Rect2 pg_rect(ofs, Size2(w, h)); - - bool editable = true; - switch (type) { - case AnimationTreePlayer::NODE_ANIMATION: { - - Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node); - String text; - if (anim_tree->animation_node_get_master_animation(p_node) != "") - text = anim_tree->animation_node_get_master_animation(p_node); - else if (anim.is_null()) - text = "load..."; - else - text = anim->get_name(); - - font->draw_halign(ci, ofs + ascofs, HALIGN_CENTER, w, text, font_color_title); - - } break; - case AnimationTreePlayer::NODE_ONESHOT: - case AnimationTreePlayer::NODE_MIX: - case AnimationTreePlayer::NODE_BLEND2: - case AnimationTreePlayer::NODE_BLEND3: - case AnimationTreePlayer::NODE_BLEND4: - case AnimationTreePlayer::NODE_TIMESCALE: - case AnimationTreePlayer::NODE_TRANSITION: { - - font->draw_halign(ci, ofs + ascofs, HALIGN_CENTER, w, "edit...", font_color_title); - } break; - default: editable = false; - } - - if (editable) { - - Ref<Texture> arrow = get_icon("GuiDropdown", "EditorIcons"); - Point2 arrow_ofs(w - arrow->get_width(), Math::floor((h - arrow->get_height()) / 2)); - arrow->draw(ci, ofs + arrow_ofs); - } -} - -AnimationTreePlayerEditor::ClickType AnimationTreePlayerEditor::_locate_click(const Point2 &p_click, StringName *p_node_id, int *p_slot_index) const { - - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - Ref<Font> font = get_font("font", "PopupMenu"); - - float h = (font->get_height() + get_constant("vseparation", "PopupMenu")); - - for (const List<StringName>::Element *E = order.back(); E; E = E->prev()) { - - const StringName &node = E->get(); - - AnimationTreePlayer::NodeType type = anim_tree->node_get_type(node); - - Point2 pos = anim_tree->node_get_position(node); - Size2 size = get_node_size(node); - - pos -= Point2(h_scroll->get_value(), v_scroll->get_value()); - - if (!Rect2(pos, size).has_point(p_click)) - continue; - - if (p_node_id) - *p_node_id = node; - - pos = p_click - pos; - - float y = pos.y - style->get_offset().height; - - if (y < 2 * h) - return CLICK_NODE; - y -= 2 * h; - - int inputs = anim_tree->node_get_input_count(node); - int count = MAX(inputs, 1); - - if (inputs == 0 || (pos.x > size.width / 2 && type != AnimationTreePlayer::NODE_OUTPUT)) { - - if (y < count * h) { - - if (p_slot_index) - *p_slot_index = 0; - return CLICK_OUTPUT_SLOT; - } - } - - for (int i = 0; i < count; i++) { - - if (y < h) { - if (p_slot_index) - *p_slot_index = i; - return CLICK_INPUT_SLOT; - } - y -= h; - } - - bool has_parameters = type != AnimationTreePlayer::NODE_OUTPUT && type != AnimationTreePlayer::NODE_TIMESEEK; - return has_parameters ? CLICK_PARAMETER : CLICK_NODE; - } - - return CLICK_NONE; -} - -Point2 AnimationTreePlayerEditor::_get_slot_pos(const StringName &p_node_id, bool p_input, int p_slot) { - - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - Ref<Font> font = get_font("font", "PopupMenu"); - Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons"); - - Size2 size = get_node_size(p_node_id); - Point2 pos = anim_tree->node_get_position(p_node_id); - - if (click_type == CLICK_NODE && click_node == p_node_id) { - - pos += click_motion - click_pos; - if (pos.x < 5) - pos.x = 5; - if (pos.y < 5) - pos.y = 5; - } - - pos -= Point2(h_scroll->get_value(), v_scroll->get_value()); - - float w = size.width - style->get_minimum_size().width; - float h = font->get_height() + get_constant("vseparation", "PopupMenu"); - - pos += style->get_offset(); - - pos.y += h * 2; - - pos.y += h * p_slot; - - pos += Point2(-slot_icon->get_width() / 2.0, h / 2.0).floor(); - - if (!p_input) { - pos.x += w + slot_icon->get_width(); - } - - return pos; -} - -void AnimationTreePlayerEditor::_gui_input(Ref<InputEvent> p_event) { - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - - if (mb->is_pressed()) { - - if (mb->get_button_index() == 1) { - click_pos = Point2(mb->get_position().x, mb->get_position().y); - click_motion = click_pos; - click_type = _locate_click(click_pos, &click_node, &click_slot); - if (click_type != CLICK_NONE) { - - order.erase(click_node); - order.push_back(click_node); - update(); - } - - switch (click_type) { - case CLICK_INPUT_SLOT: { - click_pos = _get_slot_pos(click_node, true, click_slot); - } break; - case CLICK_OUTPUT_SLOT: { - click_pos = _get_slot_pos(click_node, false, click_slot); - } break; - case CLICK_PARAMETER: { - - edited_node = click_node; - renaming_edit = false; - _popup_edit_dialog(); - //open editor - //_node_edit_property(click_node); - } break; - default: { - } - } - } - if (mb->get_button_index() == 2) { - - if (click_type != CLICK_NONE) { - click_type = CLICK_NONE; - update(); - } else { - // try to disconnect/remove - - Point2 rclick_pos = Point2(mb->get_position().x, mb->get_position().y); - rclick_type = _locate_click(rclick_pos, &rclick_node, &rclick_slot); - if (rclick_type == CLICK_INPUT_SLOT || rclick_type == CLICK_OUTPUT_SLOT) { - - node_popup->clear(); - node_popup->set_size(Size2(1, 1)); - node_popup->add_item(TTR("Disconnect"), NODE_DISCONNECT); - if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION) { - node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT); - if (rclick_type == CLICK_INPUT_SLOT) { - if (anim_tree->transition_node_has_input_auto_advance(rclick_node, rclick_slot)) - node_popup->add_item(TTR("Clear Auto-Advance"), NODE_CLEAR_AUTOADVANCE); - else - node_popup->add_item(TTR("Set Auto-Advance"), NODE_SET_AUTOADVANCE); - node_popup->add_item(TTR("Delete Input"), NODE_DELETE_INPUT); - } - } - - node_popup->set_position(rclick_pos + get_global_position()); - node_popup->popup(); - } - - if (rclick_type == CLICK_NODE) { - node_popup->clear(); - node_popup->set_size(Size2(1, 1)); - node_popup->add_item(TTR("Rename"), NODE_RENAME); - node_popup->add_item(TTR("Remove"), NODE_ERASE); - if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION) - node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT); - node_popup->set_position(rclick_pos + get_global_position()); - node_popup->popup(); - } - } - } - } else { - - if (mb->get_button_index() == 1 && click_type != CLICK_NONE) { - - switch (click_type) { - case CLICK_INPUT_SLOT: - case CLICK_OUTPUT_SLOT: { - - Point2 dst_click_pos = Point2(mb->get_position().x, mb->get_position().y); - StringName id; - int slot; - ClickType dst_click_type = _locate_click(dst_click_pos, &id, &slot); - - if (dst_click_type == CLICK_INPUT_SLOT && click_type == CLICK_OUTPUT_SLOT) { - - anim_tree->connect_nodes(click_node, id, slot); - } - if (click_type == CLICK_INPUT_SLOT && dst_click_type == CLICK_OUTPUT_SLOT) { - - anim_tree->connect_nodes(id, click_node, click_slot); - } - - } break; - case CLICK_NODE: { - Point2 new_pos = anim_tree->node_get_position(click_node) + (click_motion - click_pos); - if (new_pos.x < 5) - new_pos.x = 5; - if (new_pos.y < 5) - new_pos.y = 5; - anim_tree->node_set_position(click_node, new_pos); - - } break; - default: { - } - } - - click_type = CLICK_NONE; - update(); - } - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (mm->get_button_mask() & 1 && click_type != CLICK_NONE) { - - click_motion = Point2(mm->get_position().x, mm->get_position().y); - update(); - } - if (mm->get_button_mask() & 4 || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { - - h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); - v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); - update(); - } - } -} - -void AnimationTreePlayerEditor::_draw_cos_line(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color) { - - static const int steps = 20; - - Rect2 r; - r.position = p_from; - r.expand_to(p_to); - Vector2 sign = Vector2((p_from.x < p_to.x) ? 1 : -1, (p_from.y < p_to.y) ? 1 : -1); - bool flip = sign.x * sign.y < 0; - - Vector2 prev; - for (int i = 0; i <= steps; i++) { - - float d = i / float(steps); - float c = -Math::cos(d * Math_PI) * 0.5 + 0.5; - if (flip) - c = 1.0 - c; - Vector2 p = r.position + Vector2(d * r.size.width, c * r.size.height); - - if (i > 0) { - - draw_line(prev, p, p_color, 2); - } - - prev = p; - } -} - -void AnimationTreePlayerEditor::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - play_button->set_icon(get_icon("Play", "EditorIcons")); - add_menu->set_icon(get_icon("Add", "EditorIcons")); - } break; - case NOTIFICATION_DRAW: { - - _update_scrollbars(); - //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1)); - get_stylebox("bg", "Tree")->draw(get_canvas_item(), Rect2(Point2(), get_size())); - - for (List<StringName>::Element *E = order.front(); E; E = E->next()) { - - _draw_node(E->get()); - } - - if (click_type == CLICK_INPUT_SLOT || click_type == CLICK_OUTPUT_SLOT) { - - _draw_cos_line(click_pos, click_motion, Color(0.5, 1, 0.5, 0.8)); - } - - List<AnimationTreePlayer::Connection> connections; - anim_tree->get_connection_list(&connections); - - for (List<AnimationTreePlayer::Connection>::Element *E = connections.front(); E; E = E->next()) { - - const AnimationTreePlayer::Connection &c = E->get(); - Point2 source = _get_slot_pos(c.src_node, false, 0); - Point2 dest = _get_slot_pos(c.dst_node, true, c.dst_input); - Color col = Color(1, 1, 0.5, 0.8); - /* - if (click_type==CLICK_NODE && click_node==c.src_node) { - - source+=click_motion-click_pos; - } - - if (click_type==CLICK_NODE && click_node==c.dst_node) { - - dest+=click_motion-click_pos; - }*/ - - _draw_cos_line(source, dest, col); - } - - const Ref<Font> f = get_font("font", "Label"); - const Point2 status_offset = Point2(5, 25) * EDSCALE + Point2(0, f->get_ascent()); - - switch (anim_tree->get_last_error()) { - - case AnimationTreePlayer::CONNECT_OK: { - - f->draw(get_canvas_item(), status_offset, TTR("Animation tree is valid."), Color(0, 1, 0.6, 0.8)); - } break; - default: { - - f->draw(get_canvas_item(), status_offset, TTR("Animation tree is invalid."), Color(1, 0.6, 0.0, 0.8)); - } break; - } - - } break; - } -} - -void AnimationTreePlayerEditor::_update_scrollbars() { - - Size2 size = get_size(); - Size2 hmin = h_scroll->get_combined_minimum_size(); - Size2 vmin = v_scroll->get_combined_minimum_size(); - - v_scroll->set_begin(Point2(size.width - vmin.width, 0)); - v_scroll->set_end(Point2(size.width, size.height)); - - h_scroll->set_begin(Point2(0, size.height - hmin.height)); - h_scroll->set_end(Point2(size.width - vmin.width, size.height)); - - Size2 min = _get_maximum_size(); - - if (min.height < size.height - hmin.height) { - - v_scroll->hide(); - offset.y = 0; - } else { - - v_scroll->show(); - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - hmin.height); - offset.y = v_scroll->get_value(); - } - - if (min.width < size.width - vmin.width) { - - h_scroll->hide(); - offset.x = 0; - } else { - - h_scroll->show(); - h_scroll->set_max(min.width); - h_scroll->set_page(size.width - vmin.width); - offset.x = h_scroll->get_value(); - } -} - -void AnimationTreePlayerEditor::_scroll_moved(float) { - - offset.x = h_scroll->get_value(); - offset.y = v_scroll->get_value(); - update(); -} - -void AnimationTreePlayerEditor::_node_menu_item(int p_item) { - - switch (p_item) { - - case NODE_DISCONNECT: { - - if (rclick_type == CLICK_INPUT_SLOT) { - - anim_tree->disconnect_nodes(rclick_node, rclick_slot); - update(); - } - - if (rclick_type == CLICK_OUTPUT_SLOT) { - - List<AnimationTreePlayer::Connection> connections; - anim_tree->get_connection_list(&connections); - - for (List<AnimationTreePlayer::Connection>::Element *E = connections.front(); E; E = E->next()) { - - const AnimationTreePlayer::Connection &c = E->get(); - if (c.dst_node == rclick_node) { - - anim_tree->disconnect_nodes(c.dst_node, c.dst_input); - } - } - update(); - } - - } break; - case NODE_RENAME: { - - renaming_edit = true; - edited_node = rclick_node; - _popup_edit_dialog(); - - } break; - case NODE_ADD_INPUT: { - - anim_tree->transition_node_set_input_count(rclick_node, anim_tree->transition_node_get_input_count(rclick_node) + 1); - update(); - } break; - case NODE_DELETE_INPUT: { - - anim_tree->transition_node_delete_input(rclick_node, rclick_slot); - update(); - } break; - case NODE_SET_AUTOADVANCE: { - - anim_tree->transition_node_set_input_auto_advance(rclick_node, rclick_slot, true); - update(); - - } break; - case NODE_CLEAR_AUTOADVANCE: { - - anim_tree->transition_node_set_input_auto_advance(rclick_node, rclick_slot, false); - update(); - - } break; - - case NODE_ERASE: { - - if (rclick_node == "out") - break; - order.erase(rclick_node); - anim_tree->remove_node(rclick_node); - update(); - } break; - } -} - -StringName AnimationTreePlayerEditor::_add_node(int p_item) { - - static const char *bname[] = { - "out", - "anim", - "oneshot", - "mix", - "blend2", - "blend3", - "blend4", - "scale", - "seek", - "transition" - }; - - String name; - int idx = 1; - - while (true) { - - name = bname[p_item]; - if (idx > 1) - name += " " + itos(idx); - if (anim_tree->node_exists(name)) - idx++; - else - break; - } - - anim_tree->add_node((AnimationTreePlayer::NodeType)p_item, name); - anim_tree->node_set_position(name, Point2(last_x, last_y)); - order.push_back(name); - last_x += 10; - last_y += 10; - last_x = last_x % (int)get_size().width; - last_y = last_y % (int)get_size().height; - update(); - - return name; -}; - -void AnimationTreePlayerEditor::_file_dialog_selected(String p_path) { - - switch (file_op) { - - case MENU_IMPORT_ANIMATIONS: { - Vector<String> files = file_dialog->get_selected_files(); - - for (int i = 0; i < files.size(); i++) { - - StringName node = _add_node(AnimationTreePlayer::NODE_ANIMATION); - - RES anim = ResourceLoader::load(files[i]); - anim_tree->animation_node_set_animation(node, anim); - //anim_tree->node_set_name(node, files[i].get_file()); - }; - } break; - - default: - break; - }; -}; - -void AnimationTreePlayerEditor::_add_menu_item(int p_item) { - - if (p_item == MENU_GRAPH_CLEAR) { - - //clear - } else if (p_item == MENU_IMPORT_ANIMATIONS) { - - file_op = MENU_IMPORT_ANIMATIONS; - file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); - file_dialog->popup_centered_ratio(); - - } else { - - _add_node(p_item); - } -} - -Size2 AnimationTreePlayerEditor::get_minimum_size() const { - - return Size2(10, 200); -} - -void AnimationTreePlayerEditor::_find_paths_for_filter(const StringName &p_node, Set<String> &paths) { - - ERR_FAIL_COND(!anim_tree->node_exists(p_node)); - - for (int i = 0; i < anim_tree->node_get_input_count(p_node); i++) { - - StringName port = anim_tree->node_get_input_source(p_node, i); - if (port == StringName()) - continue; - _find_paths_for_filter(port, paths); - } - - if (anim_tree->node_get_type(p_node) == AnimationTreePlayer::NODE_ANIMATION) { - - Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node); - if (anim.is_valid()) { - - for (int i = 0; i < anim->get_track_count(); i++) { - paths.insert(anim->track_get_path(i)); - } - } - } -} - -void AnimationTreePlayerEditor::_filter_edited() { - - TreeItem *ed = filter->get_edited(); - if (!ed) - return; - - if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_ONESHOT) { - anim_tree->oneshot_node_set_filter_path(edited_node, ed->get_metadata(0), ed->is_checked(0)); - } else if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_BLEND2) { - anim_tree->blend2_node_set_filter_path(edited_node, ed->get_metadata(0), ed->is_checked(0)); - } else if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_ANIMATION) { - anim_tree->animation_node_set_filter_path(edited_node, ed->get_metadata(0), ed->is_checked(0)); - } -} - -void AnimationTreePlayerEditor::_edit_filters() { - - filter_dialog->popup_centered_ratio(); - filter->clear(); - - Set<String> npb; - _find_paths_for_filter(edited_node, npb); - - TreeItem *root = filter->create_item(); - filter->set_hide_root(true); - Map<String, TreeItem *> pm; - - Node *base = anim_tree->get_node(anim_tree->get_base_path()); - - for (Set<String>::Element *E = npb.front(); E; E = E->next()) { - - TreeItem *parent = root; - String descr = E->get(); - if (base) { - NodePath np = E->get(); - - if (np.get_subname_count() == 1) { - Node *n = base->get_node(np); - Skeleton *s = Object::cast_to<Skeleton>(n); - if (s) { - - String skelbase = E->get().substr(0, E->get().find(":")); - - int bidx = s->find_bone(np.get_subname(0)); - - if (bidx != -1) { - int bparent = s->get_bone_parent(bidx); - // - if (bparent != -1) { - - String bpn = skelbase + ":" + s->get_bone_name(bparent); - if (pm.has(bpn)) { - parent = pm[bpn]; - descr = np.get_subname(0); - } - } else { - - if (pm.has(skelbase)) { - parent = pm[skelbase]; - } - } - } - } - } - } - - TreeItem *it = filter->create_item(parent); - it->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - it->set_text(0, descr); - it->set_metadata(0, NodePath(E->get())); - it->set_editable(0, true); - if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_ONESHOT) { - it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node, E->get())); - } else if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_BLEND2) { - it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node, E->get())); - } else if (anim_tree->node_get_type(edited_node) == AnimationTreePlayer::NODE_ANIMATION) { - it->set_checked(0, anim_tree->animation_node_is_path_filtered(edited_node, E->get())); - } - pm[E->get()] = it; - } -} - -void AnimationTreePlayerEditor::_bind_methods() { - - ClassDB::bind_method("_add_menu_item", &AnimationTreePlayerEditor::_add_menu_item); - ClassDB::bind_method("_node_menu_item", &AnimationTreePlayerEditor::_node_menu_item); - ClassDB::bind_method("_gui_input", &AnimationTreePlayerEditor::_gui_input); - //ClassDB::bind_method( "_node_param_changed", &AnimationTreeEditor::_node_param_changed ); - ClassDB::bind_method("_scroll_moved", &AnimationTreePlayerEditor::_scroll_moved); - ClassDB::bind_method("_edit_dialog_changeds", &AnimationTreePlayerEditor::_edit_dialog_changeds); - ClassDB::bind_method("_edit_dialog_changede", &AnimationTreePlayerEditor::_edit_dialog_changede); - ClassDB::bind_method("_edit_dialog_changedf", &AnimationTreePlayerEditor::_edit_dialog_changedf); - ClassDB::bind_method("_edit_dialog_changed", &AnimationTreePlayerEditor::_edit_dialog_changed); - ClassDB::bind_method("_edit_dialog_animation_changed", &AnimationTreePlayerEditor::_edit_dialog_animation_changed); - ClassDB::bind_method("_edit_dialog_edit_animation", &AnimationTreePlayerEditor::_edit_dialog_edit_animation); - ClassDB::bind_method("_play_toggled", &AnimationTreePlayerEditor::_play_toggled); - ClassDB::bind_method("_edit_oneshot_start", &AnimationTreePlayerEditor::_edit_oneshot_start); - ClassDB::bind_method("_file_dialog_selected", &AnimationTreePlayerEditor::_file_dialog_selected); - ClassDB::bind_method("_master_anim_menu_item", &AnimationTreePlayerEditor::_master_anim_menu_item); - ClassDB::bind_method("_edit_filters", &AnimationTreePlayerEditor::_edit_filters); - ClassDB::bind_method("_filter_edited", &AnimationTreePlayerEditor::_filter_edited); -} - -AnimationTreePlayerEditor::AnimationTreePlayerEditor() { - - set_focus_mode(FOCUS_ALL); - - PopupMenu *p; - List<PropertyInfo> defaults; - - add_menu = memnew(MenuButton); - //add_menu->set_ - add_menu->set_position(Point2(0, 0)); - add_menu->set_size(Point2(25, 15)); - add_child(add_menu); - - p = add_menu->get_popup(); - p->add_item(TTR("Animation Node"), AnimationTreePlayer::NODE_ANIMATION); - p->add_item(TTR("OneShot Node"), AnimationTreePlayer::NODE_ONESHOT); - p->add_item(TTR("Mix Node"), AnimationTreePlayer::NODE_MIX); - p->add_item(TTR("Blend2 Node"), AnimationTreePlayer::NODE_BLEND2); - p->add_item(TTR("Blend3 Node"), AnimationTreePlayer::NODE_BLEND3); - p->add_item(TTR("Blend4 Node"), AnimationTreePlayer::NODE_BLEND4); - p->add_item(TTR("TimeScale Node"), AnimationTreePlayer::NODE_TIMESCALE); - p->add_item(TTR("TimeSeek Node"), AnimationTreePlayer::NODE_TIMESEEK); - p->add_item(TTR("Transition Node"), AnimationTreePlayer::NODE_TRANSITION); - p->add_separator(); - p->add_item(TTR("Import Animations..."), MENU_IMPORT_ANIMATIONS); // wtf - p->add_separator(); - p->add_item(TTR("Clear"), MENU_GRAPH_CLEAR); - - p->connect("id_pressed", this, "_add_menu_item"); - - play_button = memnew(Button); - play_button->set_position(Point2(25, 0) * EDSCALE); - play_button->set_size(Point2(25, 15)); - add_child(play_button); - play_button->set_toggle_mode(true); - play_button->connect("pressed", this, "_play_toggled"); - - last_x = 50; - last_y = 50; - - property_editor = memnew(CustomPropertyEditor); - add_child(property_editor); - property_editor->connect("variant_changed", this, "_edit_dialog_animation_changed"); - property_editor->connect("resource_edit_request", this, "_edit_dialog_edit_animation"); - - h_scroll = memnew(HScrollBar); - v_scroll = memnew(VScrollBar); - - add_child(h_scroll); - add_child(v_scroll); - - h_scroll->connect("value_changed", this, "_scroll_moved"); - v_scroll->connect("value_changed", this, "_scroll_moved"); - - node_popup = memnew(PopupMenu); - add_child(node_popup); - node_popup->set_as_toplevel(true); - - master_anim_popup = memnew(PopupMenu); - add_child(master_anim_popup); - master_anim_popup->connect("id_pressed", this, "_master_anim_menu_item"); - - node_popup->connect("id_pressed", this, "_node_menu_item"); - - updating_edit = false; - - edit_dialog = memnew(PopupPanel); - //edit_dialog->get_ok()->hide(); - //edit_dialog->get_cancel()->hide(); - add_child(edit_dialog); - - edit_option = memnew(OptionButton); - edit_option->set_anchor(MARGIN_RIGHT, ANCHOR_END); - edit_option->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(edit_option); - edit_option->connect("item_selected", this, "_edit_dialog_changedf"); - edit_option->hide(); - - for (int i = 0; i < 2; i++) { - edit_scroll[i] = memnew(HSlider); - edit_scroll[i]->set_anchor(MARGIN_RIGHT, ANCHOR_END); - edit_scroll[i]->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(edit_scroll[i]); - edit_scroll[i]->hide(); - edit_scroll[i]->connect("value_changed", this, "_edit_dialog_changedf"); - } - for (int i = 0; i < 4; i++) { - edit_line[i] = memnew(LineEdit); - edit_line[i]->set_anchor(MARGIN_RIGHT, ANCHOR_END); - edit_line[i]->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(edit_line[i]); - edit_line[i]->hide(); - edit_line[i]->connect("text_changed", this, "_edit_dialog_changeds"); - edit_line[i]->connect("text_entered", this, "_edit_dialog_changede"); - edit_label[i] = memnew(Label); - edit_dialog->add_child(edit_label[i]); - edit_label[i]->hide(); - } - - edit_button = memnew(Button); - edit_button->set_anchor(MARGIN_RIGHT, ANCHOR_END); - edit_button->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(edit_button); - edit_button->hide(); - edit_button->connect("pressed", this, "_edit_oneshot_start"); - - edit_check = memnew(CheckButton); - edit_check->set_anchor(MARGIN_RIGHT, ANCHOR_END); - edit_check->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(edit_check); - edit_check->hide(); - edit_check->connect("pressed", this, "_edit_dialog_changed"); - - file_dialog = memnew(EditorFileDialog); - file_dialog->set_enable_multiple_selection(true); - file_dialog->set_current_dir(ProjectSettings::get_singleton()->get_resource_path()); - add_child(file_dialog); - file_dialog->connect("file_selected", this, "_file_dialog_selected"); - - filter_dialog = memnew(AcceptDialog); - filter_dialog->set_title(TTR("Edit Node Filters")); - add_child(filter_dialog); - - filter = memnew(Tree); - filter_dialog->add_child(filter); - //filter_dialog->set_child_rect(filter); - filter->connect("item_edited", this, "_filter_edited"); - - filter_button = memnew(Button); - filter_button->set_anchor(MARGIN_RIGHT, ANCHOR_END); - filter_button->set_margin(MARGIN_RIGHT, -10); - edit_dialog->add_child(filter_button); - filter_button->hide(); - filter_button->set_text(TTR("Filters...")); - filter_button->connect("pressed", this, "_edit_filters"); - - set_clip_contents(true); -} - -void AnimationTreePlayerEditorPlugin::edit(Object *p_object) { - - anim_tree_editor->edit(Object::cast_to<AnimationTreePlayer>(p_object)); -} - -bool AnimationTreePlayerEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("AnimationTreePlayer"); -} - -void AnimationTreePlayerEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - //editor->hide_animation_player_editors(); - //editor->animation_panel_make_visible(true); - button->show(); - editor->make_bottom_panel_item_visible(anim_tree_editor); - anim_tree_editor->set_physics_process(true); - } else { - - if (anim_tree_editor->is_visible_in_tree()) - editor->hide_bottom_panel(); - button->hide(); - anim_tree_editor->set_physics_process(false); - } -} - -AnimationTreePlayerEditorPlugin::AnimationTreePlayerEditorPlugin(EditorNode *p_node) { - - editor = p_node; - anim_tree_editor = memnew(AnimationTreePlayerEditor); - anim_tree_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE); - - button = editor->add_bottom_panel_item(TTR("AnimationTree"), anim_tree_editor); - button->hide(); -} - -AnimationTreePlayerEditorPlugin::~AnimationTreePlayerEditorPlugin() { -} diff --git a/editor/plugins/animation_tree_player_editor_plugin.h b/editor/plugins/animation_tree_player_editor_plugin.h deleted file mode 100644 index d3fd6ae362..0000000000 --- a/editor/plugins/animation_tree_player_editor_plugin.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* animation_tree_player_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef ANIMATION_TREE_PLAYER_EDITOR_PLUGIN_H -#define ANIMATION_TREE_PLAYER_EDITOR_PLUGIN_H - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "editor/property_editor.h" -#include "scene/animation/animation_tree_player.h" -#include "scene/gui/button.h" -#include "scene/gui/popup.h" -#include "scene/gui/tree.h" - -class AnimationTreePlayerEditor : public Control { - - GDCLASS(AnimationTreePlayerEditor, Control); - - static const char *_node_type_names[]; - - enum ClickType { - CLICK_NONE, - CLICK_NAME, - CLICK_NODE, - CLICK_INPUT_SLOT, - CLICK_OUTPUT_SLOT, - CLICK_PARAMETER - }; - - enum { - - MENU_GRAPH_CLEAR = 100, - MENU_IMPORT_ANIMATIONS = 101, - NODE_DISCONNECT, - NODE_RENAME, - NODE_ERASE, - NODE_ADD_INPUT, - NODE_DELETE_INPUT, - NODE_SET_AUTOADVANCE, - NODE_CLEAR_AUTOADVANCE - }; - - bool renaming_edit; - StringName edited_node; - bool updating_edit; - Popup *edit_dialog; - HSlider *edit_scroll[2]; - LineEdit *edit_line[4]; - OptionButton *edit_option; - Label *edit_label[4]; - Button *edit_button; - Button *filter_button; - CheckButton *edit_check; - EditorFileDialog *file_dialog; - int file_op; - - void _popup_edit_dialog(); - - void _setup_edit_dialog(const StringName &p_node); - PopupMenu *master_anim_popup; - PopupMenu *node_popup; - PopupMenu *add_popup; - HScrollBar *h_scroll; - VScrollBar *v_scroll; - MenuButton *add_menu; - - CustomPropertyEditor *property_editor; - - AnimationTreePlayer *anim_tree; - List<StringName> order; - Set<StringName> active_nodes; - - int last_x, last_y; - - Point2 offset; - ClickType click_type; - Point2 click_pos; - StringName click_node; - int click_slot; - Point2 click_motion; - ClickType rclick_type; - StringName rclick_node; - int rclick_slot; - - Button *play_button; - - Size2 _get_maximum_size(); - Size2 get_node_size(const StringName &p_node) const; - void _draw_node(const StringName &p_node); - - AcceptDialog *filter_dialog; - Tree *filter; - - void _draw_cos_line(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color); - void _update_scrollbars(); - void _scroll_moved(float); - void _play_toggled(); - /* - void _node_param_changed(); - void _node_add_callback(); - void _node_add(VisualServer::AnimationTreeNodeType p_type); - void _node_edit_property(const StringName& p_node); -*/ - - void _master_anim_menu_item(int p_item); - void _node_menu_item(int p_item); - void _add_menu_item(int p_item); - - void _filter_edited(); - void _find_paths_for_filter(const StringName &p_node, Set<String> &paths); - void _edit_filters(); - - void _edit_oneshot_start(); - void _edit_dialog_animation_changed(); - void _edit_dialog_edit_animation(); - void _edit_dialog_changeds(String); - void _edit_dialog_changede(String); - void _edit_dialog_changedf(float); - void _edit_dialog_changed(); - void _dialog_changed() const; - ClickType _locate_click(const Point2 &p_click, StringName *p_node_id, int *p_slot_index) const; - Point2 _get_slot_pos(const StringName &p_node_id, bool p_input, int p_slot); - - StringName _add_node(int p_item); - void _file_dialog_selected(String p_path); - -protected: - void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); - static void _bind_methods(); - -public: - virtual Size2 get_minimum_size() const; - void edit(AnimationTreePlayer *p_anim_tree); - AnimationTreePlayerEditor(); -}; - -class AnimationTreePlayerEditorPlugin : public EditorPlugin { - - GDCLASS(AnimationTreePlayerEditorPlugin, EditorPlugin); - - AnimationTreePlayerEditor *anim_tree_editor; - EditorNode *editor; - Button *button; - -public: - virtual String get_name() const { return "AnimTree"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - - AnimationTreePlayerEditorPlugin(EditorNode *p_node); - ~AnimationTreePlayerEditorPlugin(); -}; - -#endif // ANIMATION_TREE_EDITOR_PLUGIN_H diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 2428bf82d4..d88a716122 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -31,6 +31,8 @@ #include "asset_library_editor_plugin.h" #include "core/io/json.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" @@ -620,6 +622,21 @@ void EditorAssetLibrary::_notification(int p_what) { } } +void EditorAssetLibrary::_unhandled_input(const Ref<InputEvent> &p_event) { + + const Ref<InputEventKey> key = p_event; + + if (key.is_valid() && key->is_pressed()) { + + if (key->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F) && is_visible_in_tree()) { + + filter->grab_focus(); + filter->select_all(); + accept_event(); + } + } +} + void EditorAssetLibrary::_install_asset() { ERR_FAIL_COND(!description); @@ -1320,6 +1337,7 @@ void EditorAssetLibrary::disable_community_support() { void EditorAssetLibrary::_bind_methods() { + ClassDB::bind_method("_unhandled_input", &EditorAssetLibrary::_unhandled_input); ClassDB::bind_method("_http_request_completed", &EditorAssetLibrary::_http_request_completed); ClassDB::bind_method("_select_asset", &EditorAssetLibrary::_select_asset); ClassDB::bind_method("_select_author", &EditorAssetLibrary::_select_author); @@ -1502,6 +1520,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { description = NULL; set_process(true); + set_process_unhandled_input(true); downloads_scroll = memnew(ScrollContainer); downloads_scroll->set_enable_h_scroll(true); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index aa3c735810..8852125b8b 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -300,6 +300,7 @@ class EditorAssetLibrary : public PanelContainer { protected: static void _bind_methods(); void _notification(int p_what); + void _unhandled_input(const Ref<InputEvent> &p_event); public: void disable_community_support(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index bf21abb455..ab816dc7f3 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -606,7 +606,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no } } -void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) { +void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, bool p_allow_locked) { Node *scene = editor->get_edited_scene(); @@ -621,14 +621,16 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel node = node->get_parent(); }; - // Replace the node by the group if grouped CanvasItem *canvas_item = Object::cast_to<CanvasItem>(node); - while (node && node != scene->get_parent()) { - CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node); - if (canvas_item_tmp && node->has_meta("_edit_group_")) { - canvas_item = canvas_item_tmp; + if (!p_allow_locked) { + // Replace the node by the group if grouped + while (node && node != scene->get_parent()) { + CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node); + if (canvas_item_tmp && node->has_meta("_edit_group_")) { + canvas_item = canvas_item_tmp; + } + node = node->get_parent(); } - node = node->get_parent(); } // Check if the canvas item is already in the list (for groups or scenes) @@ -641,7 +643,7 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel } //Remove the item if invalid - if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || _is_node_locked(canvas_item)) { + if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || (!p_allow_locked && _is_node_locked(canvas_item))) { r_items.remove(i); i--; } else { @@ -1987,7 +1989,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (selection.size() > 0) { drag_type = DRAG_MOVE; - CanvasItem *canvas_item = drag_selection[0]; + CanvasItem *canvas_item = selection[0]; Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse(); Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized(); Transform2D simple_xform = viewport->get_transform() * unscaled_transform; @@ -2106,7 +2108,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } // Move the canvas items with the arrow keys - if (k.is_valid() && k->is_pressed() && tool == TOOL_SELECT && + if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) { if (!k->is_echo()) { // Start moving the canvas items with the keyboard @@ -2223,7 +2225,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { // Popup the selection menu list Point2 click = transform.affine_inverse().xform(b->get_position()); - _get_canvas_items_at_pos(click, selection_results); + _get_canvas_items_at_pos(click, selection_results, b->get_alt() && tool != TOOL_LIST_SELECT); if (selection_results.size() == 1) { CanvasItem *item = selection_results[0].item; @@ -2245,7 +2247,29 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(item, "Node"); String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path()); - selection_menu->add_item(item->get_name()); + int locked = 0; + if (_is_node_locked(item)) { + locked = 1; + } else { + Node *scene = editor->get_edited_scene(); + Node *node = item; + + while (node && node != scene->get_parent()) { + CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node); + if (canvas_item_tmp && node->has_meta("_edit_group_")) { + locked = 2; + } + node = node->get_parent(); + } + } + + String suffix = String(); + if (locked == 1) { + suffix = " (" + TTR("Locked") + ")"; + } else if (locked == 2) { + suffix = " (" + TTR("Grouped") + ")"; + } + selection_menu->add_item((String)item->get_name() + suffix); selection_menu->set_item_icon(i, icon); selection_menu->set_item_metadata(i, node_path); selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 37bc47ecd4..eb6e621c93 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -418,7 +418,7 @@ private: bool _is_node_locked(const Node *p_node); bool _is_node_movable(const Node *p_node, bool p_popup_warning = false); void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items); + void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, bool p_allow_locked = false); void _get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items); void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 25329906a9..aaba6406c7 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -32,7 +32,7 @@ #include "editor/editor_scale.h" #include "scene/3d/collision_shape.h" -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_mesh_instance.h" #include "scene/3d/physics_body.h" #include "scene/gui/box_container.h" #include "spatial_editor_plugin.h" @@ -60,10 +60,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { } switch (p_option) { - case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: - case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: { - - bool trimesh_shape = (p_option == MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); + case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: { EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -71,9 +68,12 @@ void MeshInstanceEditor::_menu_option(int p_option) { List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.empty()) { - Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape(); - if (shape.is_null()) + Ref<Shape> shape = mesh->create_trimesh_shape(); + if (shape.is_null()) { + err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape.")); + err_dialog->popup_centered_minsize(); return; + } CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); @@ -82,11 +82,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); - if (trimesh_shape) - ur->create_action(TTR("Create Static Trimesh Body")); - else - ur->create_action(TTR("Create Static Convex Body")); - + ur->create_action(TTR("Create Static Trimesh Body")); ur->add_do_method(node, "add_child", body); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); @@ -108,7 +104,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (m.is_null()) continue; - Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape(); + Ref<Shape> shape = m->create_trimesh_shape(); if (shape.is_null()) continue; @@ -158,10 +154,44 @@ void MeshInstanceEditor::_menu_option(int p_option) { ur->add_undo_method(node->get_parent(), "remove_child", cshape); ur->commit_action(); } break; - case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: { + case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: { if (node == get_tree()->get_edited_scene_root()) { - err_dialog->set_text(TTR("This doesn't work on scene root!")); + err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root.")); + err_dialog->popup_centered_minsize(); + return; + } + + Ref<Shape> shape = mesh->create_convex_shape(); + + if (shape.is_null()) { + err_dialog->set_text(TTR("Couldn't create a single convex collision shape.")); + err_dialog->popup_centered_minsize(); + return; + } + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action(TTR("Create Single Convex Shape")); + + CollisionShape *cshape = memnew(CollisionShape); + cshape->set_shape(shape); + cshape->set_transform(node->get_transform()); + + Node *owner = node->get_owner(); + + ur->add_do_method(node->get_parent(), "add_child", cshape); + ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); + ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_reference(cshape); + ur->add_undo_method(node->get_parent(), "remove_child", cshape); + + ur->commit_action(); + + } break; + case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: { + + if (node == get_tree()->get_edited_scene_root()) { + err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root.")); err_dialog->popup_centered_minsize(); return; } @@ -169,13 +199,13 @@ void MeshInstanceEditor::_menu_option(int p_option) { Vector<Ref<Shape> > shapes = mesh->convex_decompose(); if (!shapes.size()) { - err_dialog->set_text(TTR("Failed creating shapes!")); + err_dialog->set_text(TTR("Couldn't create any collision shapes.")); err_dialog->popup_centered_minsize(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Create Convex Shape(s)")); + ur->create_action(TTR("Create Multiple Convex Shapes")); for (int i = 0; i < shapes.size(); i++) { @@ -421,13 +451,19 @@ MeshInstanceEditor::MeshInstanceEditor() { options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance", "EditorIcons")); options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); - options->get_popup()->add_item(TTR("Create Convex Collision Sibling(s)"), MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); + options->get_popup()->add_item(TTR("Create Single Convex Collision Siblings"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); + options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a static outline mesh. The outline mesh will have its normals flipped automatically.\nThis can be used instead of the SpatialMaterial Grow property when using that property isn't possible.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1); options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2); diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h index 5c95676fc4..5ca9aa3fec 100644 --- a/editor/plugins/mesh_instance_editor_plugin.h +++ b/editor/plugins/mesh_instance_editor_plugin.h @@ -43,9 +43,9 @@ class MeshInstanceEditor : public Control { enum Menu { MENU_OPTION_CREATE_STATIC_TRIMESH_BODY, - MENU_OPTION_CREATE_STATIC_CONVEX_BODY, MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE, - MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE, + MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE, + MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES, MENU_OPTION_CREATE_NAVMESH, MENU_OPTION_CREATE_OUTLINE_MESH, MENU_OPTION_CREATE_UV2, diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 92898ff9c3..42859e9190 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "editor/editor_settings.h" #include "main/main.h" #include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_mesh_instance.h" #include "scene/3d/physics_body.h" #include "scene/main/viewport.h" #include "scene/resources/packed_scene.h" diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 31e6b65640..8f7ff04b2c 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -250,7 +250,7 @@ void SpatialEditorViewport::_clear_selected() { editor_selection->clear(); } -void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single) { +void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) { if (!clicked) return; @@ -260,17 +260,20 @@ void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single) { if (!selected) return; - // Replace the node by the group if grouped - while (node && node != editor->get_edited_scene()->get_parent()) { - Spatial *selected_tmp = Object::cast_to<Spatial>(node); - if (selected_tmp && node->has_meta("_edit_group_")) { - selected = selected_tmp; + if (!p_allow_locked) { + // Replace the node by the group if grouped + while (node && node != editor->get_edited_scene()->get_parent()) { + Spatial *selected_tmp = Object::cast_to<Spatial>(node); + if (selected_tmp && node->has_meta("_edit_group_")) { + selected = selected_tmp; + } + node = node->get_parent(); } - node = node->get_parent(); } - if (!_is_node_locked(selected)) + if (p_allow_locked || !_is_node_locked(selected)) { _select(selected, clicked_wants_append, true); + } } void SpatialEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { @@ -848,7 +851,7 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { selection_results.clear(); if (clicked) { - _select_clicked(clicked_wants_append, true); + _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); clicked = 0; } @@ -865,7 +868,29 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { String node_path = "/" + root_name + "/" + root_path.rel_path_to(spat->get_path()); - selection_menu->add_item(spat->get_name()); + int locked = 0; + if (_is_node_locked(spat)) { + locked = 1; + } else { + Node *ed_scene = editor->get_edited_scene(); + Node *node = spat; + + while (node && node != ed_scene->get_parent()) { + Spatial *selected_tmp = Object::cast_to<Spatial>(node); + if (selected_tmp && node->has_meta("_edit_group_")) { + locked = 2; + } + node = node->get_parent(); + } + } + + String suffix = String(); + if (locked == 1) { + suffix = " (" + TTR("Locked") + ")"; + } else if (locked == 2) { + suffix = " (" + TTR("Grouped") + ")"; + } + selection_menu->add_item((String)spat->get_name() + suffix); selection_menu->set_item_icon(i, icon); selection_menu->set_item_metadata(i, node_path); selection_menu->set_item_tooltip(i, String(spat->get_name()) + "\nType: " + spat->get_class() + "\nPath: " + node_path); @@ -2892,7 +2917,7 @@ void SpatialEditorViewport::_selection_result_pressed(int p_result) { clicked = selection_results[p_result].item->get_instance_id(); if (clicked) { - _select_clicked(clicked_wants_append, true); + _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); clicked = 0; } } diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 5cc2b24cbb..269e1715ef 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -234,7 +234,7 @@ private: void _update_name(); void _compute_edit(const Point2 &p_point); void _clear_selected(); - void _select_clicked(bool p_append, bool p_single); + void _select_clicked(bool p_append, bool p_single, bool p_allow_locked = false); void _select(Node *p_node, bool p_append, bool p_single); ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = NULL, bool p_alt_select = false); void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index f889228f87..0c3e29028c 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -2026,13 +2026,13 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { toolbar->add_child(bucket_fill_button); picker_button = memnew(ToolButton); - picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_CONTROL)); + picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I)); picker_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PICKING)); picker_button->set_toggle_mode(true); toolbar->add_child(picker_button); select_button = memnew(ToolButton); - select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD + KEY_B)); + select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M)); select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECTING)); select_button->set_toggle_mode(true); toolbar->add_child(select_button); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ee434aaac2..9cc2a79399 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -885,7 +885,8 @@ public: rs_button->set_pressed(true); rvb->add_child(rs_button); l = memnew(Label); - l->set_text(TTR("Higher visual quality\nAll features available\nIncompatible with older hardware\nNot recommended for web games")); + l->set_text(TTR("- Higher visual quality\n- All features available\n- Incompatible with older hardware\n- Not recommended for web games")); + l->set_modulate(Color(1, 1, 1, 0.7)); rvb->add_child(l); rshb->add_child(memnew(VSeparator)); @@ -899,12 +900,17 @@ public: rs_button->set_meta("driver_name", "GLES2"); rvb->add_child(rs_button); l = memnew(Label); - l->set_text(TTR("Lower visual quality\nSome features not available\nWorks on most hardware\nRecommended for web games")); + l->set_text(TTR("- Lower visual quality\n- Some features not available\n- Works on most hardware\n- Recommended for web games")); + l->set_modulate(Color(1, 1, 1, 0.7)); rvb->add_child(l); l = memnew(Label); - l->set_text(TTR("Renderer can be changed later, but scenes may need to be adjusted.")); + l->set_text(TTR("The renderer can be changed later, but scenes may need to be adjusted.")); + // Add some extra spacing to separate it from the list above and the buttons below. + l->set_custom_minimum_size(Size2(0, 40) * EDSCALE); l->set_align(Label::ALIGN_CENTER); + l->set_valign(Label::VALIGN_CENTER); + l->set_modulate(Color(1, 1, 1, 0.7)); rasterizer_container->add_child(l); fdialog = memnew(FileDialog); @@ -1037,6 +1043,7 @@ public: void sort_projects(); int get_project_count() const; void select_project(int p_index); + void select_first_visible_project(); void erase_selected_projects(); Vector<Item> get_selected_projects() const; const Set<String> &get_selected_project_keys() const; @@ -1629,6 +1636,23 @@ void ProjectList::select_project(int p_index) { toggle_select(p_index); } +void ProjectList::select_first_visible_project() { + bool found = false; + + for (int i = 0; i < _projects.size(); i++) { + if (_projects[i].control->is_visible()) { + select_project(i); + found = true; + break; + } + } + + if (!found) { + // Deselect all projects if there are no visible projects in the list. + _selected_project_keys.clear(); + } +} + inline void sort(int &a, int &b) { if (a > b) { int temp = a; @@ -2347,6 +2371,12 @@ void ProjectManager::_on_order_option_changed() { void ProjectManager::_on_filter_option_changed() { _project_list->set_search_term(project_filter->get_search_term()); _project_list->sort_projects(); + + // Select the first visible project in the list. + // This makes it possible to open a project without ever touching the mouse, + // as the search field is automatically focused on startup. + _project_list->select_first_visible_project(); + _update_project_buttons(); } void ProjectManager::_bind_methods() { diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index b656fd647f..6635f5cb47 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -719,9 +719,18 @@ void ProjectSettingsEditor::_update_actions() { item->set_range(1, action["deadzone"]); item->set_custom_bg_color(1, get_color("prop_subsection", "Editor")); + const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(pi.name) != NULL; + const String tooltip = is_builtin_input ? TTR("Built-in actions can't be removed as they're used for UI navigation.") : TTR("Remove"); item->add_button(2, get_icon("Add", "EditorIcons"), 1, false, TTR("Add Event")); - if (!ProjectSettings::get_singleton()->get_input_presets().find(pi.name)) { - item->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); + item->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, tooltip); + + if (is_builtin_input) { + // Built-in action (like `ui_up`). Make the action not removable, + // but still display the button so the "Add" button is at the same + // horizontal position as for custom actions. + item->set_button_disabled(2, 1, true); + } else { + // Not a built-in action. Make the action name editable. item->set_editable(0, true); } @@ -747,10 +756,9 @@ void ProjectSettingsEditor::_update_actions() { if (jb.is_valid()) { String str = _get_device_string(jb->get_device()) + ", " + TTR("Button") + " " + itos(jb->get_button_index()); - if (jb->get_button_index() >= 0 && jb->get_button_index() < JOY_BUTTON_MAX) - str += String() + " (" + _button_names[jb->get_button_index()] + ")."; - else - str += "."; + if (jb->get_button_index() >= 0 && jb->get_button_index() < JOY_BUTTON_MAX) { + str += String() + " (" + _button_names[jb->get_button_index()] + ")"; + } action2->set_text(0, str); action2->set_icon(0, get_icon("JoyButton", "EditorIcons")); @@ -761,12 +769,12 @@ void ProjectSettingsEditor::_update_actions() { if (mb.is_valid()) { String str = _get_device_string(mb->get_device()) + ", "; switch (mb->get_button_index()) { - case BUTTON_LEFT: str += TTR("Left Button."); break; - case BUTTON_RIGHT: str += TTR("Right Button."); break; - case BUTTON_MIDDLE: str += TTR("Middle Button."); break; - case BUTTON_WHEEL_UP: str += TTR("Wheel Up."); break; - case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down."); break; - default: str += TTR("Button") + " " + itos(mb->get_button_index()) + "."; + case BUTTON_LEFT: str += TTR("Left Button"); break; + case BUTTON_RIGHT: str += TTR("Right Button"); break; + case BUTTON_MIDDLE: str += TTR("Middle Button"); break; + case BUTTON_WHEEL_UP: str += TTR("Wheel Up"); break; + case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down"); break; + default: str += vformat(TTR("%d Button"), mb->get_button_index()); } action2->set_text(0, str); @@ -780,7 +788,7 @@ void ProjectSettingsEditor::_update_actions() { int ax = jm->get_axis(); int n = 2 * ax + (jm->get_axis_value() < 0 ? 0 : 1); String desc = _axis_names[n]; - String str = _get_device_string(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc + "."; + String str = _get_device_string(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc; action2->set_text(0, str); action2->set_icon(0, get_icon("JoyAxis", "EditorIcons")); } @@ -789,6 +797,10 @@ void ProjectSettingsEditor::_update_actions() { action2->add_button(2, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); action2->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); + // Fade out the individual event buttons slightly to make the + // Add/Remove buttons stand out more. + action2->set_button_color(2, 0, Color(1, 1, 1, 0.75)); + action2->set_button_color(2, 1, Color(1, 1, 1, 0.75)); } } diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index c94b0eeab0..d012b2f821 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -41,7 +41,7 @@ #include "scene/3d/light.h" #include "scene/3d/listener.h" #include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_mesh_instance.h" #include "scene/3d/particles.h" #include "scene/3d/physics_joint.h" #include "scene/3d/position_3d.h" |