diff options
Diffstat (limited to 'editor')
57 files changed, 993 insertions, 734 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 28642f1bb4..02b4a12b92 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -398,17 +398,17 @@ void AnimationBezierTrackEdit::_notification(int p_what) { float scale = timeline->get_zoom_scale(); Ref<Texture2D> point = get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")); - for (Map<int, Color>::Element *E = subtrack_colors.front(); E; E = E->next()) { - _draw_track(E->key(), E->get()); + for (const KeyValue<int, Color> &E : subtrack_colors) { + _draw_track(E.key, E.value); - for (int i = 0; i < animation->track_get_key_count(E->key()); i++) { - float offset = animation->track_get_key_time(E->key(), i); - float value = animation->bezier_track_get_key_value(E->key(), i); + for (int i = 0; i < animation->track_get_key_count(E.key); i++) { + float offset = animation->track_get_key_time(E.key, i); + float value = animation->bezier_track_get_key_value(E.key, i); Vector2 pos((offset - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value)); if (pos.x >= limit && pos.x <= right_limit) { - draw_texture(point, pos - point->get_size() / 2, E->get()); + draw_texture(point, pos - point->get_size() / 2, E.value); } } } @@ -680,9 +680,9 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { emit_signal(SNAME("close_request")); return; } - for (Map<int, Rect2>::Element *E = subtracks.front(); E; E = E->next()) { - if (E->get().has_point(mb->get_position())) { - set_animation_and_track(animation, E->key()); + for (const KeyValue<int, Rect2> &E : subtracks) { + if (E.value.has_point(mb->get_position())) { + set_animation_and_track(animation, E.key); _clear_selection(); return; } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 324237ff82..d5afd5020c 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -700,16 +700,15 @@ public: return; } - for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) { + for (const KeyValue<int, List<float>> &E : key_ofs_map) { int key = 0; - for (float &F : E->value()) { - float key_ofs = F; + for (const float &key_ofs : E.value) { if (from != key_ofs) { key++; continue; } - int track = E->key(); + int track = E.key; key_ofs_map[track][key] = to; if (setting) { @@ -726,10 +725,9 @@ public: bool _set(const StringName &p_name, const Variant &p_value) { bool update_obj = false; bool change_notify_deserved = false; - for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) { - int track = E->key(); - for (float &F : E->value()) { - float key_ofs = F; + for (const KeyValue<int, List<float>> &E : key_ofs_map) { + int track = E.key; + for (const float &key_ofs : E.value) { int key = animation->track_find_key(track, key_ofs, true); ERR_FAIL_COND_V(key == -1, false); @@ -984,10 +982,9 @@ public: } bool _get(const StringName &p_name, Variant &r_ret) const { - for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) { - int track = E->key(); - for (float &F : E->value()) { - float key_ofs = F; + for (const KeyValue<int, List<float>> &E : key_ofs_map) { + int track = E.key; + for (const float &key_ofs : E.value) { int key = animation->track_find_key(track, key_ofs, true); ERR_CONTINUE(key == -1); @@ -1119,15 +1116,15 @@ public: bool show_time = true; bool same_track_type = true; bool same_key_type = true; - for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) { - int track = E->key(); + for (const KeyValue<int, List<float>> &E : key_ofs_map) { + int track = E.key; ERR_FAIL_INDEX(track, animation->get_track_count()); if (first_track < 0) { first_track = track; } - if (show_time && E->value().size() > 1) { + if (show_time && E.value.size() > 1) { show_time = false; } @@ -1137,7 +1134,7 @@ public: same_key_type = false; } - for (float &F : E->value()) { + for (const float &F : E.value) { int key = animation->track_find_key(track, F, true); ERR_FAIL_COND(key == -1); if (first_key < 0) { @@ -4831,8 +4828,8 @@ void AnimationTrackEditor::_update_key_edit() { Map<int, List<float>> key_ofs_map; Map<int, NodePath> base_map; int first_track = -1; - for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) { - int track = E->key().track; + for (const KeyValue<SelectedKey, KeyInfo> &E : selection) { + int track = E.key.track; if (first_track < 0) { first_track = track; } @@ -4842,7 +4839,7 @@ void AnimationTrackEditor::_update_key_edit() { base_map[track] = NodePath(); } - key_ofs_map[track].push_back(animation->track_get_key_time(track, E->key().key)); + key_ofs_map[track].push_back(animation->track_get_key_time(track, E.key.key)); } multi_key_edit->key_ofs_map = key_ofs_map; multi_key_edit->base_map = base_map; @@ -5386,8 +5383,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { float len = -1e20; float pivot = 0; - for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) { - float t = animation->track_get_key_time(E->key().track, E->key().key); + for (const KeyValue<SelectedKey, KeyInfo> &E : selection) { + float t = animation->track_get_key_time(E.key.track, E.key.key); if (t < from_t) { from_t = t; } diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index f7f4988873..2efcdcda31 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -216,15 +216,15 @@ AudioStreamPreviewGenerator *AudioStreamPreviewGenerator::singleton = nullptr; void AudioStreamPreviewGenerator::_notification(int p_what) { if (p_what == NOTIFICATION_PROCESS) { List<ObjectID> to_erase; - for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) { - if (!E->get().generating.is_set()) { - if (E->get().thread) { - E->get().thread->wait_to_finish(); - memdelete(E->get().thread); - E->get().thread = nullptr; + for (KeyValue<ObjectID, Preview> &E : previews) { + if (!E.value.generating.is_set()) { + if (E.value.thread) { + E.value.thread->wait_to_finish(); + memdelete(E.value.thread); + E.value.thread = nullptr; } - if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview - to_erase.push_back(E->key()); + if (!ObjectDB::get_instance(E.key)) { //no longer in use, get rid of preview + to_erase.push_back(E.key); } } } diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index fbd3aaa409..485d58f4a3 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -306,8 +306,8 @@ Dictionary DebugAdapterParser::req_stackTrace(const Dictionary &p_params) const Array arr; DebugAdapterProtocol *dap = DebugAdapterProtocol::get_singleton(); - for (Map<DAP::StackFrame, List<int>>::Element *E = dap->stackframe_list.front(); E; E = E->next()) { - DAP::StackFrame sf = E->key(); + for (const KeyValue<DAP::StackFrame, List<int>> &E : dap->stackframe_list) { + DAP::StackFrame sf = E.key; if (!lines_at_one) { sf.line--; } diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp index a1eb71235c..e53f66e72e 100644 --- a/editor/debugger/editor_debugger_inspector.cpp +++ b/editor/debugger/editor_debugger_inspector.cpp @@ -200,12 +200,12 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { } void EditorDebuggerInspector::clear_cache() { - for (Map<ObjectID, EditorDebuggerRemoteObject *>::Element *E = remote_objects.front(); E; E = E->next()) { + for (const KeyValue<ObjectID, EditorDebuggerRemoteObject *> &E : remote_objects) { EditorNode *editor = EditorNode::get_singleton(); - if (editor->get_editor_history()->get_current() == E->value()->get_instance_id()) { + if (editor->get_editor_history()->get_current() == E.value->get_instance_id()) { editor->push_item(nullptr); } - memdelete(E->value()); + memdelete(E.value); } remote_objects.clear(); remote_dependencies.clear(); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index be84e8dec5..188f5708aa 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -328,9 +328,9 @@ void EditorDebuggerNode::_notification(int p_what) { debugger->set_editor_remote_tree(remote_scene_tree); debugger->start(server->take_connection()); // Send breakpoints. - for (Map<Breakpoint, bool>::Element *E = breakpoints.front(); E; E = E->next()) { - const Breakpoint &bp = E->key(); - debugger->set_breakpoint(bp.source, bp.line, E->get()); + for (const KeyValue<Breakpoint, bool> &E : breakpoints) { + const Breakpoint &bp = E.key; + debugger->set_breakpoint(bp.source, bp.line, E.value); } // Will arrive too late, how does the regular run work? debugger->update_live_edit_root(); @@ -497,8 +497,8 @@ void EditorDebuggerNode::set_breakpoints(const String &p_path, Array p_lines) { set_breakpoint(p_path, p_lines[i], true); } - for (Map<Breakpoint, bool>::Element *E = breakpoints.front(); E; E = E->next()) { - Breakpoint b = E->key(); + for (const KeyValue<Breakpoint, bool> &E : breakpoints) { + Breakpoint b = E.key; if (b.source == p_path && !p_lines.has(b.line)) { set_breakpoint(p_path, b.line, false); } diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp index 9479fbd5d4..d4385630be 100644 --- a/editor/debugger/editor_network_profiler.cpp +++ b/editor/debugger/editor_network_profiler.cpp @@ -56,18 +56,18 @@ void EditorNetworkProfiler::_update_frame() { TreeItem *root = counters_display->create_item(); - for (Map<ObjectID, DebuggerMarshalls::MultiplayerNodeInfo>::Element *E = nodes_data.front(); E; E = E->next()) { + for (const KeyValue<ObjectID, DebuggerMarshalls::MultiplayerNodeInfo> &E : nodes_data) { TreeItem *node = counters_display->create_item(root); for (int j = 0; j < counters_display->get_columns(); ++j) { node->set_text_align(j, j > 0 ? TreeItem::ALIGN_RIGHT : TreeItem::ALIGN_LEFT); } - node->set_text(0, E->get().node_path); - node->set_text(1, E->get().incoming_rpc == 0 ? "-" : itos(E->get().incoming_rpc)); - node->set_text(2, E->get().incoming_rset == 0 ? "-" : itos(E->get().incoming_rset)); - node->set_text(3, E->get().outgoing_rpc == 0 ? "-" : itos(E->get().outgoing_rpc)); - node->set_text(4, E->get().outgoing_rset == 0 ? "-" : itos(E->get().outgoing_rset)); + node->set_text(0, E.value.node_path); + node->set_text(1, E.value.incoming_rpc == 0 ? "-" : itos(E.value.incoming_rpc)); + node->set_text(2, E.value.incoming_rset == 0 ? "-" : itos(E.value.incoming_rset)); + node->set_text(3, E.value.outgoing_rpc == 0 ? "-" : itos(E.value.outgoing_rpc)); + node->set_text(4, E.value.outgoing_rset == 0 ? "-" : itos(E.value.outgoing_rset)); } } diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index fa9c9f61f5..2fe7cd7886 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -515,11 +515,11 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const { if (!m.valid) { continue; } - for (Map<StringName, Metric::Category *>::Element *E = m.category_ptrs.front(); E; E = E->next()) { - possible_signatures.insert(E->key()); + for (const KeyValue<StringName, Metric::Category *> &E : m.category_ptrs) { + possible_signatures.insert(E.key); } - for (Map<StringName, Metric::Category::Item *>::Element *E = m.item_ptrs.front(); E; E = E->next()) { - possible_signatures.insert(E->key()); + for (const KeyValue<StringName, Metric::Category::Item *> &E : m.item_ptrs) { + possible_signatures.insert(E.key); } } @@ -557,11 +557,11 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const { values.clear(); values.resize(possible_signatures.size()); - for (Map<StringName, Metric::Category *>::Element *E = m.category_ptrs.front(); E; E = E->next()) { - values.write[sig_map[E->key()]] = String::num_real(E->value()->total_time); + for (const KeyValue<StringName, Metric::Category *> &E : m.category_ptrs) { + values.write[sig_map[E.key]] = String::num_real(E.value->total_time); } - for (Map<StringName, Metric::Category::Item *>::Element *E = m.item_ptrs.front(); E; E = E->next()) { - values.write[sig_map[E->key()]] = String::num_real(E->value()->total); + for (const KeyValue<StringName, Metric::Category::Item *> &E : m.item_ptrs) { + values.write[sig_map[E.key]] = String::num_real(E.value->total); } res.push_back(values); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index a9d8cb219c..d07d77c112 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -74,16 +74,16 @@ void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String String path = efsd->get_file_path(i); - for (Map<String, String>::Element *E = candidates[file].front(); E; E = E->next()) { - if (E->get() == String()) { - E->get() = path; + for (KeyValue<String, String> &E : candidates[file]) { + if (E.value == String()) { + E.value = path; continue; } //must match the best, using subdirs - String existing = E->get().replace_first("res://", ""); + String existing = E.value.replace_first("res://", ""); String current = path.replace_first("res://", ""); - String lost = E->key().replace_first("res://", ""); + String lost = E.key.replace_first("res://", ""); Vector<String> existingv = existing.split("/"); existingv.reverse(); @@ -107,7 +107,7 @@ void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String if (current_score > existing_score) { //if it was the same, could track distance to new path but.. - E->get() = path; //replace by more accurate + E.value = path; //replace by more accurate } } } @@ -133,10 +133,10 @@ void DependencyEditor::_fix_all() { Map<String, String> remaps; - for (Map<String, Map<String, String>>::Element *E = candidates.front(); E; E = E->next()) { - for (Map<String, String>::Element *F = E->get().front(); F; F = F->next()) { - if (F->get() != String()) { - remaps[F->key()] = F->get(); + for (KeyValue<String, Map<String, String>> &E : candidates) { + for (const KeyValue<String, String> &F : E.value) { + if (F.value != String()) { + remaps[F.key] = F.value; } } } diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index ec162231e9..beead74c53 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -44,8 +44,8 @@ #include "modules/modules_enabled.gen.h" void DocTools::merge_from(const DocTools &p_data) { - for (Map<String, DocData::ClassDoc>::Element *E = class_list.front(); E; E = E->next()) { - DocData::ClassDoc &c = E->get(); + for (KeyValue<String, DocData::ClassDoc> &E : class_list) { + DocData::ClassDoc &c = E.value; if (!p_data.class_list.has(c.name)) { continue; @@ -185,9 +185,9 @@ void DocTools::merge_from(const DocTools &p_data) { } void DocTools::remove_from(const DocTools &p_data) { - for (Map<String, DocData::ClassDoc>::Element *E = p_data.class_list.front(); E; E = E->next()) { - if (class_list.has(E->key())) { - class_list.erase(E->key()); + for (const KeyValue<String, DocData::ClassDoc> &E : p_data.class_list) { + if (class_list.has(E.key)) { + class_list.erase(E.key); } } } @@ -1227,8 +1227,8 @@ static void _write_method_doc(FileAccess *f, const String &p_name, Vector<DocDat } Error DocTools::save_classes(const String &p_default_path, const Map<String, String> &p_class_path) { - for (Map<String, DocData::ClassDoc>::Element *E = class_list.front(); E; E = E->next()) { - DocData::ClassDoc &c = E->get(); + for (KeyValue<String, DocData::ClassDoc> &E : class_list) { + DocData::ClassDoc &c = E.value; String save_path; if (p_class_path.has(c.name)) { diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index fcf79a80a7..0840c3b6a8 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -473,8 +473,8 @@ void EditorAutoloadSettings::update_autoload() { } // Remove deleted/changed autoloads - for (Map<String, AutoLoadInfo>::Element *E = to_remove.front(); E; E = E->next()) { - AutoLoadInfo &info = E->get(); + for (KeyValue<String, AutoLoadInfo> &E : to_remove) { + AutoLoadInfo &info = E.value; if (info.is_singleton) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptServer::get_language(i)->remove_named_global_constant(info.name); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 225526da5b..aee9c21007 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -1105,8 +1105,8 @@ Array EditorSelection::_get_transformable_selected_nodes() { TypedArray<Node> EditorSelection::get_selected_nodes() { TypedArray<Node> ret; - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - ret.push_back(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + ret.push_back(E.key); } return ret; @@ -1133,8 +1133,8 @@ void EditorSelection::_update_nl() { selected_node_list.clear(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - Node *parent = E->key(); + for (const KeyValue<Node *, Object *> &E : selection) { + Node *parent = E.key; parent = parent->get_parent(); bool skip = false; while (parent) { @@ -1148,7 +1148,7 @@ void EditorSelection::_update_nl() { if (skip) { continue; } - selected_node_list.push_back(E->key()); + selected_node_list.push_back(E.key); } nl_changed = true; @@ -1183,8 +1183,8 @@ List<Node *> &EditorSelection::get_selected_node_list() { List<Node *> EditorSelection::get_full_selected_node_list() { List<Node *> node_list; - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - node_list.push_back(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + node_list.push_back(E.key); } return node_list; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 10ed76673e..a88adf3634 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -451,6 +451,9 @@ void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_d } for (int i = 0; i < p_dir->get_file_count(); i++) { + if (p_dir->get_file_type(i) == "TextFile") { + continue; + } p_paths.insert(p_dir->get_file_path(i)); } } @@ -1814,9 +1817,9 @@ bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, List<String> EditorExportPlatformPC::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const { List<String> list; - for (Map<String, String>::Element *E = extensions.front(); E; E = E->next()) { - if (p_preset->get(E->key())) { - list.push_back(extensions[E->key()]); + for (const KeyValue<String, String> &E : extensions) { + if (p_preset->get(E.key)) { + list.push_back(extensions[E.key]); return list; } } diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 84a9237a96..2222a5e5d3 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -179,9 +179,9 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) { Array dis_props; - for (Map<StringName, Set<StringName>>::Element *E = disabled_properties.front(); E; E = E->next()) { - for (Set<StringName>::Element *F = E->get().front(); F; F = F->next()) { - dis_props.push_back(String(E->key()) + ":" + String(F->get())); + for (KeyValue<StringName, Set<StringName>> &E : disabled_properties) { + for (Set<StringName>::Element *F = E.value.front(); F; F = F->next()) { + dis_props.push_back(String(E.key) + ":" + String(F->get())); } } diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 8523833d52..0882b525d7 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -862,6 +862,9 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); + if (fi->type == "" && textfile_extensions.has(ext)) { + fi->type = "TextFile"; + } fi->uid = ResourceLoader::get_resource_uid(path); fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->deps = _get_dependencies(path); @@ -984,6 +987,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; fi->type = ResourceLoader::get_resource_type(path); + if (fi->type == "" && textfile_extensions.has(ext)) { + fi->type = "TextFile"; + } fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->import_valid = ResourceLoader::is_import_valid(path); fi->import_group_file = ResourceLoader::get_import_group_file(path); @@ -1539,6 +1545,9 @@ void EditorFileSystem::update_file(const String &p_file) { } String type = ResourceLoader::get_resource_type(p_file); + if (type == "" && textfile_extensions.has(p_file.get_extension())) { + type = "TextFile"; + } ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_file); if (cpos == -1) { @@ -1556,7 +1565,7 @@ void EditorFileSystem::update_file(const String &p_file) { EditorFileSystemDirectory::FileInfo *fi = memnew(EditorFileSystemDirectory::FileInfo); fi->file = file_name; fi->import_modified_time = 0; - fi->import_valid = ResourceLoader::is_import_valid(p_file); + fi->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file); if (idx == fs->files.size()) { fs->files.push_back(fi); @@ -1577,7 +1586,7 @@ void EditorFileSystem::update_file(const String &p_file) { fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file); fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->deps = _get_dependencies(p_file); - fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); + fs->files[cpos]->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file); if (uid != ResourceUID::INVALID_ID) { if (ResourceUID::get_singleton()->has_id(uid)) { @@ -1654,8 +1663,8 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector Error err = importer->import_group_file(p_group_file, source_file_options, base_paths); //all went well, overwrite config files with proper remaps and md5s - for (Map<String, Map<StringName, Variant>>::Element *E = source_file_options.front(); E; E = E->next()) { - const String &file = E->key(); + for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) { + const String &file = E.key; String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file); FileAccessRef f = FileAccess::open(file + ".import", FileAccess::WRITE); ERR_FAIL_COND_V_MSG(!f, ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'."); @@ -1740,6 +1749,9 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(file + ".import"); fs->files[cpos]->deps = _get_dependencies(file); fs->files[cpos]->type = importer->get_resource_type(); + if (fs->files[cpos]->type == "" && textfile_extensions.has(file.get_extension())) { + fs->files[cpos]->type = "TextFile"; + } fs->files[cpos]->import_valid = err == OK; //if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it @@ -2121,10 +2133,10 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { if (groups_to_reimport.size()) { Map<String, Vector<String>> group_files; _find_group_files(filesystem, group_files, groups_to_reimport); - for (Map<String, Vector<String>>::Element *E = group_files.front(); E; E = E->next()) { - Error err = _reimport_group(E->key(), E->get()); + for (const KeyValue<String, Vector<String>> &E : group_files) { + Error err = _reimport_group(E.key, E.value); if (err == OK) { - _reimport_file(E->key()); + _reimport_file(E.key); } } } @@ -2329,6 +2341,7 @@ void EditorFileSystem::_bind_methods() { void EditorFileSystem::_update_extensions() { valid_extensions.clear(); import_extensions.clear(); + textfile_extensions.clear(); List<String> extensionsl; ResourceLoader::get_recognized_extensions_for_type("", &extensionsl); @@ -2336,6 +2349,15 @@ void EditorFileSystem::_update_extensions() { valid_extensions.insert(E); } + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (const String &E : textfile_ext) { + if (valid_extensions.has(E)) { + continue; + } + valid_extensions.insert(E); + textfile_extensions.insert(E); + } + extensionsl.clear(); ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl); for (const String &E : extensionsl) { diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index b47cf5523a..feadd0f2b2 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -190,6 +190,7 @@ class EditorFileSystem : public Node { void _delete_internal_files(String p_file); + Set<String> textfile_extensions; Set<String> valid_extensions; Set<String> import_extensions; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index fff9e5e908..b17f105507 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -394,8 +394,8 @@ void EditorHelp::_update_doc() { bool prev = false; class_desc->push_font(doc_font); - for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { - if (E->get().inherits == cd.name) { + for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) { + if (E.value.inherits == cd.name) { if (!found) { class_desc->push_color(title_color); class_desc->add_text(TTR("Inherited by:") + " "); @@ -406,7 +406,7 @@ void EditorHelp::_update_doc() { class_desc->add_text(" , "); } - _add_type(E->get().name); + _add_type(E.value.name); prev = true; } } @@ -876,14 +876,14 @@ void EditorHelp::_update_doc() { class_desc->add_newline(); - for (Map<String, Vector<DocData::ConstantDoc>>::Element *E = enums.front(); E; E = E->next()) { - enum_line[E->key()] = class_desc->get_line_count() - 2; + for (KeyValue<String, Vector<DocData::ConstantDoc>> &E : enums) { + enum_line[E.key] = class_desc->get_line_count() - 2; class_desc->push_font(doc_code_font); class_desc->push_color(title_color); class_desc->add_text("enum "); class_desc->pop(); - String e = E->key(); + String e = E.key; if ((e.get_slice_count(".") > 1) && (e.get_slice(".", 0) == edited_class)) { e = e.get_slice(".", 1); } @@ -913,10 +913,10 @@ void EditorHelp::_update_doc() { } class_desc->push_indent(1); - Vector<DocData::ConstantDoc> enum_list = E->get(); + Vector<DocData::ConstantDoc> enum_list = E.value; Map<String, int> enumValuesContainer; - int enumStartingLine = enum_line[E->key()]; + int enumStartingLine = enum_line[E.key]; for (int i = 0; i < enum_list.size(); i++) { if (cd.name == "@GlobalScope") { @@ -955,7 +955,7 @@ void EditorHelp::_update_doc() { } if (cd.name == "@GlobalScope") { - enum_values_line[E->key()] = enumValuesContainer; + enum_values_line[E.key] = enumValuesContainer; } class_desc->pop(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 4832cd6994..4d0f27c5d4 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -842,10 +842,10 @@ void EditorProperty::set_bottom_editor(Control *p_control) { bool EditorProperty::is_cache_valid() const { if (object) { - for (Map<StringName, Variant>::Element *E = cache.front(); E; E = E->next()) { + for (const KeyValue<StringName, Variant> &E : cache) { bool valid; - Variant value = object->get(E->key(), &valid); - if (!valid || value != E->get()) { + Variant value = object->get(E.key, &valid); + if (!valid || value != E.value) { return false; } } @@ -3029,8 +3029,8 @@ void EditorInspector::collapse_all_folding() { E->fold(); } - for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) { - for (EditorProperty *E : F->get()) { + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + for (EditorProperty *E : F.value) { E->collapse_all_folding(); } } @@ -3040,8 +3040,8 @@ void EditorInspector::expand_all_folding() { for (EditorInspectorSection *E : sections) { E->unfold(); } - for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) { - for (EditorProperty *E : F->get()) { + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + for (EditorProperty *E : F.value) { E->expand_all_folding(); } } @@ -3306,11 +3306,11 @@ void EditorInspector::_property_selected(const String &p_path, int p_focusable) property_selected = p_path; property_focusable = p_focusable; //deselect the others - for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) { - if (F->key() == property_selected) { + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + if (F.key == property_selected) { continue; } - for (EditorProperty *E : F->get()) { + for (EditorProperty *E : F.value) { if (E->is_selected()) { E->deselect(); } @@ -3368,8 +3368,8 @@ void EditorInspector::_notification(int p_what) { if (refresh_countdown > 0) { refresh_countdown -= get_process_delta_time(); if (refresh_countdown <= 0) { - for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) { - for (EditorProperty *E : F->get()) { + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + for (EditorProperty *E : F.value) { if (!E->is_cache_valid()) { E->update_property(); E->update_reload_status(); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index f91cb7f607..346b93a87c 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -116,8 +116,8 @@ void EditorLog::_save_state() { config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); const String section = "editor_log"; - for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { - config->set_value(section, "log_filter_" + itos(E->key()), E->get()->is_active()); + for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) { + config->set_value(section, "log_filter_" + itos(E.key), E.value->is_active()); } config->set_value(section, "collapse", collapse); @@ -135,8 +135,8 @@ void EditorLog::_load_state() { // Run the below code even if config->load returns an error, since we want the defaults to be set even if the file does not exist yet. const String section = "editor_log"; - for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { - E->get()->set_active(config->get_value(section, "log_filter_" + itos(E->key()), true)); + for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) { + E.value->set_active(config->get_value(section, "log_filter_" + itos(E.key), true)); } collapse = config->get_value(section, "collapse", false); @@ -306,8 +306,8 @@ void EditorLog::_search_changed(const String &p_text) { } void EditorLog::_reset_message_counts() { - for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { - E->value()->set_message_count(0); + for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) { + E.value->set_message_count(0); } } @@ -441,7 +441,7 @@ void EditorLog::deinit() { } EditorLog::~EditorLog() { - for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { - memdelete(E->get()); + for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) { + memdelete(E.value); } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 1aaa5432f4..8bc87b7f81 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -741,6 +741,21 @@ void EditorNode::_notification(int p_what) { main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts"))); } + Set<String> updated_textfile_extensions; + bool extensions_match = true; + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (const String &E : textfile_ext) { + updated_textfile_extensions.insert(E); + if (extensions_match && !textfile_extensions.has(E)) { + extensions_match = false; + } + } + + if (!extensions_match || updated_textfile_extensions.size() < textfile_extensions.size()) { + textfile_extensions = updated_textfile_extensions; + EditorFileSystem::get_singleton()->scan(); + } + _update_update_spinner(); } break; @@ -1114,7 +1129,13 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d dependency_errors.clear(); Error err; - RES res = ResourceLoader::load(p_resource, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + + RES res; + if (ResourceLoader::exists(p_resource, "")) { + res = ResourceLoader::load(p_resource, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + } else if (textfile_extensions.has(p_resource.get_extension())) { + res = ScriptEditor::get_singleton()->open_file(p_resource); + } ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN); if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) { @@ -3181,8 +3202,8 @@ void EditorNode::_update_addon_config() { Vector<String> enabled_addons; - for (Map<String, EditorPlugin *>::Element *E = plugin_addons.front(); E; E = E->next()) { - enabled_addons.push_back(E->key()); + for (const KeyValue<String, EditorPlugin *> &E : plugin_addons) { + enabled_addons.push_back(E.key); } if (enabled_addons.size() == 0) { @@ -3564,9 +3585,9 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b dependency_errors.erase(lpath); //at least not self path - for (Map<String, Set<String>>::Element *E = dependency_errors.front(); E; E = E->next()) { - String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E->key()) + "\n"; - for (Set<String>::Element *F = E->get().front(); F; F = F->next()) { + for (KeyValue<String, Set<String>> &E : dependency_errors) { + String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E.key) + "\n"; + for (Set<String>::Element *F = E.value.front(); F; F = F->next()) { txt += "\t" + F->get() + "\n"; } add_io_error(txt); @@ -4029,8 +4050,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); - for (const Map<String, Vector<EditorData::CustomType>>::Element *E = p_map.front(); E; E = E->next()) { - const Vector<EditorData::CustomType> &ct = E->value(); + for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) { + const Vector<EditorData::CustomType> &ct = E.value; for (int i = 0; i < ct.size(); ++i) { if (ct[i].name == p_class) { if (ct[i].icon.is_valid()) { @@ -5995,6 +6016,11 @@ EditorNode::EditorNode() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (const String &E : textfile_ext) { + textfile_extensions.insert(E); + } + theme_base = memnew(Control); add_child(theme_base); theme_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE); @@ -6195,12 +6221,12 @@ EditorNode::EditorNode() { scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE); scene_tabs->set_drag_to_rearrange_enabled(true); scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); - scene_tabs->connect("right_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited)); + scene_tabs->connect("tab_rmb_clicked", callable_mp(this, &EditorNode::_scene_tab_script_edited)); scene_tabs->connect("tab_closed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE)); scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered)); scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit)); scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input)); - scene_tabs->connect("reposition_active_tab_request", callable_mp(this, &EditorNode::_reposition_active_tab)); + scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorNode::_reposition_active_tab)); scene_tabs->connect("resized", callable_mp(this, &EditorNode::_update_scene_tabs)); tabbar_container = memnew(HBoxContainer); diff --git a/editor/editor_node.h b/editor/editor_node.h index d1f4cf8452..07c834eeca 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -542,6 +542,7 @@ private: String import_reload_fn; + Set<String> textfile_extensions; Set<FileDialog *> file_dialogs; Set<EditorFileDialog *> editor_file_dialogs; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index c0dadc4484..2d4a3ac788 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3574,7 +3574,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ case Variant::PACKED_COLOR_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_COLOR_ARRAY); - + return editor; } break; default: { } diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 5828549bdc..74ebffc404 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -66,9 +66,9 @@ void EditorRunNative::_notification(int p_what) { bool changed = EditorExport::get_singleton()->poll_export_platforms() || first; if (changed) { - for (Map<int, MenuButton *>::Element *E = menus.front(); E; E = E->next()) { - Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(E->key()); - MenuButton *mb = E->get(); + for (KeyValue<int, MenuButton *> &E : menus) { + Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(E.key); + MenuButton *mb = E.value; int dc = eep->get_options_count(); if (dc == 0) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 70f43e01cf..f0e97a7787 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -73,14 +73,15 @@ bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value) if (p_name == "shortcuts") { Array arr = p_value; - ERR_FAIL_COND_V(arr.size() && arr.size() & 1, true); - for (int i = 0; i < arr.size(); i += 2) { - String name = arr[i]; - Ref<InputEvent> shortcut = arr[i + 1]; + for (int i = 0; i < arr.size(); i++) { + Dictionary dict = arr[i]; + String name = dict["name"]; + + Array shortcut_events = dict["shortcuts"]; Ref<Shortcut> sc; sc.instantiate(); - sc->set_event(shortcut); + sc->set_events(shortcut_events); add_shortcut(name, sc); } @@ -138,11 +139,11 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const { _THREAD_SAFE_METHOD_ if (p_name == "shortcuts") { - Array arr; - for (const Map<String, Ref<Shortcut>>::Element *E = shortcuts.front(); E; E = E->next()) { - Ref<Shortcut> sc = E->get(); + Array save_array; + for (const KeyValue<String, Ref<Shortcut>> &shortcut_definition : shortcuts) { + Ref<Shortcut> sc = shortcut_definition.value; - if (builtin_action_overrides.has(E->key())) { + if (builtin_action_overrides.has(shortcut_definition.key)) { // This shortcut was auto-generated from built in actions: don't save. continue; } @@ -151,34 +152,57 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const { if (!sc->has_meta("original")) { continue; //this came from settings but is not any longer used } + } - Ref<InputEvent> original = sc->get_meta("original"); - if (sc->matches_event(original) || (original.is_null() && sc->get_event().is_null())) { - continue; //not changed from default, don't save - } + Array original_events = sc->get_meta("original"); + Array shortcut_events = sc->get_events(); + + bool is_same = Shortcut::is_event_array_equal(original_events, shortcut_events); + if (is_same) { + continue; // Not changed from default; don't save. } - arr.push_back(E->key()); - arr.push_back(sc->get_event()); + Dictionary dict; + dict["name"] = shortcut_definition.key; + dict["shortcuts"] = shortcut_events; + + save_array.push_back(dict); } - r_ret = arr; + r_ret = save_array; return true; } else if (p_name == "builtin_action_overrides") { Array actions_arr; - for (Map<String, List<Ref<InputEvent>>>::Element *E = builtin_action_overrides.front(); E; E = E->next()) { - List<Ref<InputEvent>> events = E->get(); + for (const KeyValue<String, List<Ref<InputEvent>>> &action_override : builtin_action_overrides) { + List<Ref<InputEvent>> events = action_override.value; - // TODO: skip actions which are the same as the builtin. Dictionary action_dict; - action_dict["name"] = E->key(); + action_dict["name"] = action_override.key; + // Convert the list to an array, and only keep key events as this is for the editor. Array events_arr; - for (List<Ref<InputEvent>>::Element *I = events.front(); I; I = I->next()) { - events_arr.push_back(I->get()); + for (const Ref<InputEvent> &ie : events) { + Ref<InputEventKey> iek = ie; + if (iek.is_valid()) { + events_arr.append(iek); + } } - action_dict["events"] = events_arr; + Array defaults_arr; + List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins()[action_override.key]; + for (const Ref<InputEvent> &default_input_event : defaults) { + if (default_input_event.is_valid()) { + defaults_arr.append(default_input_event); + } + } + + bool same = Shortcut::is_event_array_equal(events_arr, defaults_arr); + // Don't save if same as default. + if (same) { + continue; + } + + action_dict["events"] = events_arr; actions_arr.push_back(action_dict); } @@ -460,6 +484,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // FileSystem EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "docks/filesystem/thumbnail_size", 64, "32,128,16") _initial_set("docks/filesystem/always_show_folders", true); + _initial_set("docks/filesystem/textfile_extensions", "txt,md,cfg,ini,log,json,yml,yaml,toml"); // Property editor _initial_set("docks/property_editor/auto_refresh_interval", 0.2); //update 5 times per second by default @@ -1404,7 +1429,7 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const { const Map<String, List<Ref<InputEvent>>>::Element *builtin_override = builtin_action_overrides.find(p_name); if (builtin_override) { sc.instantiate(); - sc->set_event(builtin_override->get().front()->get()); + sc->set_events_list(&builtin_override->get()); sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name)); } @@ -1413,7 +1438,7 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const { const OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name); if (builtin_default) { sc.instantiate(); - sc->set_event(builtin_default.get().front()->get()); + sc->set_events_list(&builtin_default.get()); sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name)); } } @@ -1428,8 +1453,8 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const { } void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) { - for (const Map<String, Ref<Shortcut>>::Element *E = shortcuts.front(); E; E = E->next()) { - r_shortcuts->push_back(E->key()); + for (const KeyValue<String, Ref<Shortcut>> &E : shortcuts) { + r_shortcuts->push_back(E.key); } } @@ -1449,52 +1474,91 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + "."); + PackedInt32Array arr; + arr.push_back(p_keycode); + + ED_SHORTCUT_OVERRIDE_ARRAY(p_path, p_feature, arr); +} + +void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes) { + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); + ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + "."); + // Only add the override if the OS supports the provided feature. - if (OS::get_singleton()->has_feature(p_feature)) { - Ref<InputEventKey> ie; - if (p_keycode) { - ie = InputEventKey::create_reference(p_keycode); + if (!OS::get_singleton()->has_feature(p_feature)) { + return; + } + + Array events; + + for (int i = 0; i < p_keycodes.size(); i++) { + Key keycode = (Key)p_keycodes[i]; + +#ifdef OSX_ENABLED + // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS + if (keycode == KEY_DELETE) { + keycode = KEY_MASK_CMD | KEY_BACKSPACE; } +#endif - // Directly override the existing shortcut. - sc->set_event(ie); - sc->set_meta("original", ie); + Ref<InputEventKey> ie; + if (keycode) { + ie = InputEventKey::create_reference(keycode); + events.push_back(ie); + } } + + // Directly override the existing shortcut. + sc->set_events(events); + sc->set_meta("original", events); } Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode) { + PackedInt32Array arr; + arr.push_back(p_keycode); + return ED_SHORTCUT_ARRAY(p_path, p_name, arr); +} + +Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes) { + Array events; + + for (int i = 0; i < p_keycodes.size(); i++) { + Key keycode = (Key)p_keycodes[i]; + #ifdef OSX_ENABLED - // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS - if (p_keycode == KEY_DELETE) { - p_keycode = KEY_MASK_CMD | KEY_BACKSPACE; - } + // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS + if (keycode == KEY_DELETE) { + keycode = KEY_MASK_CMD | KEY_BACKSPACE; + } #endif - Ref<InputEventKey> ie; - if (p_keycode) { - ie = InputEventKey::create_reference(p_keycode); + Ref<InputEventKey> ie; + if (keycode) { + ie = InputEventKey::create_reference(keycode); + events.push_back(ie); + } } if (!EditorSettings::get_singleton()) { Ref<Shortcut> sc; sc.instantiate(); sc->set_name(p_name); - sc->set_event(ie); - sc->set_meta("original", ie); + sc->set_events(events); + sc->set_meta("original", events); return sc; } Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); if (sc.is_valid()) { sc->set_name(p_name); //keep name (the ones that come from disk have no name) - sc->set_meta("original", ie); //to compare against changes + sc->set_meta("original", events); //to compare against changes return sc; } sc.instantiate(); sc->set_name(p_name); - sc->set_event(ie); - sc->set_meta("original", ie); //to compare against changes + sc->set_events(events); + sc->set_meta("original", events); //to compare against changes EditorSettings::get_singleton()->add_shortcut(p_path, sc); return sc; @@ -1549,7 +1613,7 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr // Update the shortcut (if it is used somewhere in the editor) to be the first event of the new list. if (shortcuts.has(p_name)) { - shortcuts[p_name]->set_event(event_list.front()->get()); + shortcuts[p_name]->set_events_list(&event_list); } } diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 9067539e29..04e227bc5c 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -201,7 +201,9 @@ Variant _EDITOR_GET(const String &p_setting); #define ED_IS_SHORTCUT(p_name, p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name, p_ev)) Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode = KEY_NONE); +Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes); void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode = KEY_NONE); +void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes); Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path); #endif // EDITOR_SETTINGS_H diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index de1d7b5706..0579fb4cbd 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -962,8 +962,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected); theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected); theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons")); - theme->set_stylebox("button_pressed", "Tabs", style_menu); - theme->set_stylebox("button", "Tabs", style_menu); + theme->set_stylebox("close_bg_pressed", "Tabs", style_menu); + theme->set_stylebox("close_bg_highlight", "Tabs", style_menu); theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons")); theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons")); theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons")); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 28bbfc2eff..1d1976d7e5 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -106,7 +106,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory List<FileInfo> file_list; for (int i = 0; i < p_dir->get_file_count(); i++) { String file_type = p_dir->get_file_type(i); - if (_is_file_type_disabled_by_feature_profile(file_type)) { + if (file_type != "TextFile" && _is_file_type_disabled_by_feature_profile(file_type)) { // If type is disabled, file won't be displayed. continue; } @@ -1301,11 +1301,11 @@ void FileSystemDock::_update_dependencies_after_move(const Map<String, String> & void FileSystemDock::_update_project_settings_after_move(const Map<String, String> &p_renames) const { // Find all project settings of type FILE and replace them if needed. const Map<StringName, PropertyInfo> prop_info = ProjectSettings::get_singleton()->get_custom_property_info(); - for (const Map<StringName, PropertyInfo>::Element *E = prop_info.front(); E; E = E->next()) { - if (E->get().hint == PROPERTY_HINT_FILE) { - String old_path = GLOBAL_GET(E->key()); + for (const KeyValue<StringName, PropertyInfo> &E : prop_info) { + if (E.value.hint == PROPERTY_HINT_FILE) { + String old_path = GLOBAL_GET(E.key); if (p_renames.has(old_path)) { - ProjectSettings::get_singleton()->set_setting(E->key(), p_renames[old_path]); + ProjectSettings::get_singleton()->set_setting(E.key, p_renames[old_path]); } }; } @@ -1954,6 +1954,13 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_NEW_RESOURCE: { new_resource_dialog->popup_create(true); } break; + case FILE_NEW_TEXTFILE: { + String fpath = path; + if (!fpath.ends_with("/")) { + fpath = fpath.get_base_dir(); + } + ScriptEditor::get_singleton()->open_text_file_create_dialog(fpath); + } break; } } @@ -2473,6 +2480,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str p_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE); p_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT); p_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE); + p_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); p_popup->add_separator(); } @@ -2513,6 +2521,7 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) { tree_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE); tree_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT); tree_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE); + tree_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); tree_popup->set_position(tree->get_global_position() + p_pos); tree_popup->popup(); } @@ -2558,6 +2567,7 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { file_list_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE); file_list_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT); file_list_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE); + file_list_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); file_list_popup->add_separator(); file_list_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); file_list_popup->set_position(files->get_global_position() + p_pos); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 21a7abe622..73bdd685b7 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -101,6 +101,7 @@ private: FILE_SHOW_IN_EXPLORER, FILE_COPY_PATH, FILE_NEW_RESOURCE, + FILE_NEW_TEXTFILE, FOLDER_EXPAND_ALL, FOLDER_COLLAPSE_ALL, }; diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 9444706fd2..380b269675 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -840,8 +840,8 @@ void FindInFilesPanel::_on_replace_all_clicked() { PackedStringArray modified_files; - for (Map<String, TreeItem *>::Element *E = _file_items.front(); E; E = E->next()) { - TreeItem *file_item = E->value(); + for (KeyValue<String, TreeItem *> &E : _file_items) { + TreeItem *file_item = E.value; String fpath = file_item->get_metadata(0); Vector<Result> locations; diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index b6d0927ce6..4cd9066350 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -2095,19 +2095,19 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) { } void Collada::_merge_skeletons2(VisualScene *p_vscene) { - for (Map<String, SkinControllerData>::Element *E = state.skin_controller_data_map.front(); E; E = E->next()) { - SkinControllerData &cd = E->get(); + for (KeyValue<String, SkinControllerData> &E : state.skin_controller_data_map) { + SkinControllerData &cd = E.value; NodeSkeleton *skeleton = nullptr; - for (Map<String, Transform3D>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) { + for (const KeyValue<String, Transform3D> &F : cd.bone_rest_map) { String name; - if (!state.sid_to_node_map.has(F->key())) { + if (!state.sid_to_node_map.has(F.key)) { continue; } - name = state.sid_to_node_map[F->key()]; + name = state.sid_to_node_map[F.key]; ERR_CONTINUE(!state.scene_map.has(name)); @@ -2248,9 +2248,9 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it //make rests relative to the skeleton (they seem to be always relative to world) - for (Map<String, Transform3D>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) { - E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton - state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative + for (KeyValue<String, Transform3D> &E : skin.bone_rest_map) { + E.value = skel_inv * E.value; //make the bone rest local to the skeleton + state.bone_rest_map[E.key] = E.value; // make it remember where the bone is globally, now that it's relative } //but most exporters seem to work only if i do this.. @@ -2302,8 +2302,8 @@ void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) { } void Collada::_optimize() { - for (Map<String, VisualScene>::Element *E = state.visual_scene_map.front(); E; E = E->next()) { - VisualScene &vs = E->get(); + for (KeyValue<String, VisualScene> &E : state.visual_scene_map) { + VisualScene &vs = E.value; for (int i = 0; i < vs.root_nodes.size(); i++) { _create_skeletons(&vs.root_nodes.write[i]); } diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 7ab80ac3b4..3de7426302 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -1314,8 +1314,8 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t } void ColladaImport::_fix_param_animation_tracks() { - for (Map<String, Collada::Node *>::Element *E = collada.state.scene_map.front(); E; E = E->next()) { - Collada::Node *n = E->get(); + for (KeyValue<String, Collada::Node *> &E : collada.state.scene_map) { + Collada::Node *n = E.value; switch (n->type) { case Collada::Node::TYPE_NODE: { // ? do nothing @@ -1363,7 +1363,7 @@ void ColladaImport::_fix_param_animation_tracks() { for (int rti = 0; rti < rt.size(); rti++) { Collada::AnimationTrack *at = &collada.state.animation_tracks.write[rt[rti]]; - at->target = E->key(); + at->target = E.key; at->param = "morph/" + collada.state.mesh_name_map[mesh_name]; at->property = true; //at->param @@ -1431,11 +1431,11 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones animation->set_name(collada.state.animation_clips[p_clip].name); } - for (Map<String, NodeMap>::Element *E = node_map.front(); E; E = E->next()) { - if (E->get().bone < 0) { + for (const KeyValue<String, NodeMap> &E : node_map) { + if (E.value.bone < 0) { continue; } - bones_with_animation[E->key()] = false; + bones_with_animation[E.key] = false; } //store and validate tracks @@ -1626,19 +1626,19 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (p_make_tracks_in_all_bones) { //some bones may lack animation, but since we don't store pose as a property, we must add keyframes! - for (Map<String, bool>::Element *E = bones_with_animation.front(); E; E = E->next()) { - if (E->get()) { + for (const KeyValue<String, bool> &E : bones_with_animation) { + if (E.value) { continue; } - NodeMap &nm = node_map[E->key()]; + NodeMap &nm = node_map[E.key]; String path = scene->get_path_to(nm.node); ERR_CONTINUE(nm.bone < 0); Skeleton3D *sk = static_cast<Skeleton3D *>(nm.node); String name = sk->get_bone_name(nm.bone); path = path + ":" + name; - Collada::Node *cn = collada.state.scene_map[E->key()]; + Collada::Node *cn = collada.state.scene_map[E.key]; if (cn->ignore_anim) { WARN_PRINT("Collada: Ignoring animation on node: " + path); continue; diff --git a/editor/import/editor_importer_bake_reset.cpp b/editor/import/editor_importer_bake_reset.cpp index 00dce6850e..fb5de941ae 100644 --- a/editor/import/editor_importer_bake_reset.cpp +++ b/editor/import/editor_importer_bake_reset.cpp @@ -122,14 +122,14 @@ void BakeReset::_align_animations(AnimationPlayer *p_ap, const Map<StringName, B for (List<StringName>::Element *anim_i = anim_names.front(); anim_i; anim_i = anim_i->next()) { Ref<Animation> a = p_ap->get_animation(anim_i->get()); ERR_CONTINUE(a.is_null()); - for (Map<StringName, BakeResetRestBone>::Element *rest_bone_i = r_rest_bones.front(); rest_bone_i; rest_bone_i = rest_bone_i->next()) { - int track = a->find_track(NodePath(rest_bone_i->key())); + for (const KeyValue<StringName, BakeResetRestBone> &rest_bone_i : r_rest_bones) { + int track = a->find_track(NodePath(rest_bone_i.key)); if (track == -1) { continue; } int new_track = a->add_track(Animation::TYPE_TRANSFORM3D); - NodePath new_path = NodePath(rest_bone_i->key()); - BakeResetRestBone rest_bone = rest_bone_i->get(); + NodePath new_path = NodePath(rest_bone_i.key); + const BakeResetRestBone rest_bone = rest_bone_i.value; a->track_set_path(new_track, new_path); for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) { Vector3 loc; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 61745cb6ee..96a53b3257 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -86,28 +86,28 @@ void ResourceImporterTexture::update_imports() { return; } - for (Map<StringName, MakeInfo>::Element *E = make_flags.front(); E; E = E->next()) { + for (const KeyValue<StringName, MakeInfo> &E : make_flags) { Ref<ConfigFile> cf; cf.instantiate(); - String src_path = String(E->key()) + ".import"; + String src_path = String(E.key) + ".import"; Error err = cf->load(src_path); ERR_CONTINUE(err != OK); bool changed = false; - if (E->get().flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { + if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { cf->set_value("params", "compress/normal_map", 1); changed = true; } - if (E->get().flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { - cf->set_value("params", "roughness/mode", E->get().channel_for_roughness + 2); - cf->set_value("params", "roughness/src_normal", E->get().normal_path_for_roughness); + if (E.value.flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { + cf->set_value("params", "roughness/mode", E.value.channel_for_roughness + 2); + cf->set_value("params", "roughness/src_normal", E.value.normal_path_for_roughness); changed = true; } - if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { + if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { int compress_to = cf->get_value("params", "detect_3d/compress_to"); cf->set_value("params", "detect_3d/compress_to", 0); if (compress_to == 1) { @@ -121,7 +121,7 @@ void ResourceImporterTexture::update_imports() { if (changed) { cf->save(src_path); - to_reimport.push_back(E->key()); + to_reimport.push_back(E.key); } } diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index f99ab9888a..7ab5308a47 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -771,52 +771,52 @@ void SceneImportSettings::_re_import() { Dictionary subresources; - for (Map<String, NodeData>::Element *E = node_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, NodeData> &E : node_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - nodes[E->key()] = d; + nodes[E.key] = d; } } if (nodes.size()) { subresources["nodes"] = nodes; } - for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, MaterialData> &E : material_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - materials[E->key()] = d; + materials[E.key] = d; } } if (materials.size()) { subresources["materials"] = materials; } - for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, MeshData> &E : mesh_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - meshes[E->key()] = d; + meshes[E.key] = d; } } if (meshes.size()) { subresources["meshes"] = meshes; } - for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, AnimationData> &E : animation_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - animations[E->key()] = d; + animations[E.key] = d; } } if (animations.size()) { @@ -889,8 +889,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { switch (current_action) { case ACTION_EXTRACT_MATERIALS: { - for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { - MaterialData &md = material_map[E->key()]; + for (const KeyValue<String, MaterialData> &E : material_map) { + MaterialData &md = material_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -905,7 +905,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already External"); item->set_tooltip(2, TTR("This material already references an external file, no action will be taken.\nDisable the external property for it to be extracted again.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); @@ -942,8 +942,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { external_paths->get_ok_button()->set_text(TTR("Extract")); } break; case ACTION_CHOOSE_MESH_SAVE_PATHS: { - for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { - MeshData &md = mesh_map[E->key()]; + for (const KeyValue<String, MeshData> &E : mesh_map) { + MeshData &md = mesh_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -958,7 +958,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already Saving"); item->set_tooltip(2, TTR("This mesh already saves to an external resource, no action will be taken.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); @@ -995,8 +995,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { external_paths->get_ok_button()->set_text(TTR("Set Paths")); } break; case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: { - for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { - AnimationData &ad = animation_map[E->key()]; + for (const KeyValue<String, AnimationData> &E : animation_map) { + AnimationData &ad = animation_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -1010,7 +1010,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already Saving"); item->set_tooltip(2, TTR("This animation already saves to an external resource, no action will be taken.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index f83a7d046a..370394b475 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -966,8 +966,8 @@ Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { Vector<Vector3> vertices; vertices.resize(unique_vertices.size()); - for (Map<Vector3, int>::Element *E = unique_vertices.front(); E; E = E->next()) { - vertices.write[E->get()] = E->key(); + for (const KeyValue<Vector3, int> &E : unique_vertices) { + vertices.write[E.value] = E.key; } Ref<NavigationMesh> nm; diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp index 25bca1d4f4..8300dcf555 100644 --- a/editor/import_defaults_editor.cpp +++ b/editor/import_defaults_editor.cpp @@ -86,9 +86,9 @@ void ImportDefaultsEditor::_save() { if (settings->importer.is_valid()) { Dictionary modified; - for (Map<StringName, Variant>::Element *E = settings->values.front(); E; E = E->next()) { - if (E->get() != settings->default_values[E->key()]) { - modified[E->key()] = E->get(); + for (const KeyValue<StringName, Variant> &E : settings->values) { + if (E.value != settings->default_values[E.key]) { + modified[E.key] = E.value; } } diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 04ddf3552b..a559f05785 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -204,11 +204,24 @@ void InspectorDock::_load_resource(const String &p_type) { load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (int i = 0; i < textfile_ext.size(); i++) { + load_resource_dialog->add_filter("*." + textfile_ext[i] + " ; " + textfile_ext[i].to_upper()); + } + load_resource_dialog->popup_file_dialog(); } void InspectorDock::_resource_file_selected(String p_file) { - RES res = ResourceLoader::load(p_file); + RES res; + if (ResourceLoader::exists(p_file, "")) { + res = ResourceLoader::load(p_file); + } else { + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + if (textfile_ext.has(p_file.get_extension())) { + res = ScriptEditor::get_singleton()->open_file(p_file); + } + } if (res.is_null()) { warning_dialog->set_text(TTR("Failed to load resource.")); @@ -469,18 +482,19 @@ void InspectorDock::update(Object *p_object) { const bool is_object = p_object != nullptr; const bool is_resource = is_object && p_object->is_class("Resource"); + const bool is_text_file = is_object && p_object->is_class("TextFile"); const bool is_node = is_object && p_object->is_class("Node"); - object_menu->set_disabled(!is_object); - search->set_editable(is_object); - resource_save_button->set_disabled(!is_resource); - open_docs_button->set_disabled(!is_resource && !is_node); + object_menu->set_disabled(!is_object || is_text_file); + search->set_editable(is_object && !is_text_file); + resource_save_button->set_disabled(!is_resource || is_text_file); + open_docs_button->set_disabled(is_text_file || (!is_resource && !is_node)); PopupMenu *resource_extra_popup = resource_extra_button->get_popup(); - resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_COPY), !is_resource); - resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_MAKE_BUILT_IN), !is_resource); + resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_COPY), !is_resource || is_text_file); + resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_MAKE_BUILT_IN), !is_resource || is_text_file); - if (!is_object) { + if (!is_object || is_text_file) { warning->hide(); editor_path->clear_path(); return; diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 24cb660f7a..55ffbf9477 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -776,16 +776,16 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) { } if (player) { - for (Map<StringName, ProgressBar *>::Element *E = animations.front(); E; E = E->next()) { - Ref<AnimationNodeAnimation> an = blend_tree->get_node(E->key()); + for (const KeyValue<StringName, ProgressBar *> &E : animations) { + Ref<AnimationNodeAnimation> an = blend_tree->get_node(E.key); if (an.is_valid()) { if (player->has_animation(an->get_animation())) { Ref<Animation> anim = player->get_animation(an->get_animation()); if (anim.is_valid()) { - E->get()->set_max(anim->get_length()); + E.value->set_max(anim->get_length()); //StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node; - StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E->key()) + "/time"; - E->get()->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path)); + StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E.key) + "/time"; + E.value->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path)); } } } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 664b2f521e..aacfc3e305 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -830,9 +830,9 @@ void EditorAssetLibrary::_update_image_queue() { int current_images = 0; List<int> to_delete; - for (Map<int, ImageQueue>::Element *E = image_queue.front(); E; E = E->next()) { - if (!E->get().active && current_images < max_images) { - String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + E->get().image_url.md5_text()); + for (KeyValue<int, ImageQueue> &E : image_queue) { + if (!E.value.active && current_images < max_images) { + String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + E.value.image_url.md5_text()); Vector<String> headers; if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) { @@ -844,14 +844,14 @@ void EditorAssetLibrary::_update_image_queue() { } } - Error err = E->get().request->request(E->get().image_url, headers); + Error err = E.value.request->request(E.value.image_url, headers); if (err != OK) { - to_delete.push_back(E->key()); + to_delete.push_back(E.key); } else { - E->get().active = true; + E.value.active = true; } current_images++; - } else if (E->get().active) { + } else if (E.value.active) { current_images++; } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a42bdfea34..a49dd916f3 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -748,8 +748,8 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_locked, bool remove_canvas_item_if_parent_in_selection) { List<CanvasItem *> selection; - for (Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (retreive_locked || !_is_node_locked(canvas_item))) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (se) { @@ -3782,8 +3782,8 @@ void CanvasItemEditor::_notification(int p_what) { } // Update the viewport if bones changes - for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) { - Object *b = ObjectDB::get_instance(E->key().from); + for (KeyValue<BoneKey, BoneList> &E : bone_list) { + Object *b = ObjectDB::get_instance(E.key.from); if (!b) { viewport->update(); break; @@ -3796,14 +3796,14 @@ void CanvasItemEditor::_notification(int p_what) { Transform2D global_xform = b2->get_global_transform(); - if (global_xform != E->get().xform) { - E->get().xform = global_xform; + if (global_xform != E.value.xform) { + E.value.xform = global_xform; viewport->update(); } Bone2D *bone = Object::cast_to<Bone2D>(b); - if (bone && bone->get_length() != E->get().length) { - E->get().length = bone->get_length(); + if (bone && bone->get_length() != E.value.length) { + E.value.length = bone->get_length(); viewport->update(); } } @@ -4263,8 +4263,8 @@ void CanvasItemEditor::_button_tool_select(int p_index) { void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) { Map<Node *, Object *> &selection = editor_selection->get_selection(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item || !canvas_item->is_visible_in_tree()) { continue; } @@ -4695,8 +4695,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { Map<Node *, Object *> &selection = editor_selection->get_selection(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item || !canvas_item->is_visible_in_tree()) { continue; } @@ -4741,8 +4741,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { case ANIM_CLEAR_POSE: { Map<Node *, Object *> &selection = editor_selection->get_selection(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item || !canvas_item->is_visible_in_tree()) { continue; } @@ -4816,8 +4816,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { Node *editor_root = EditorNode::get_singleton()->get_edited_scene()->get_tree()->get_edited_scene_root(); undo_redo->create_action(TTR("Create Custom Bone2D(s) from Node(s)")); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - Node2D *n2d = Object::cast_to<Node2D>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + Node2D *n2d = Object::cast_to<Node2D>(E.key); Bone2D *new_bone = memnew(Bone2D); String new_bone_name = n2d->get_name(); @@ -4861,8 +4861,8 @@ void CanvasItemEditor::_focus_selection(int p_op) { int count = 0; Map<Node *, Object *> &selection = editor_selection->get_selection(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item) { continue; } diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index eb771f2bc4..ac7bfd267b 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -4773,10 +4773,10 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } Vector<Vector3> lines; - for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) { - if (E->get()) { - lines.push_back(E->key().from); - lines.push_back(E->key().to); + for (const KeyValue<_EdgeKey, bool> &E : edge_map) { + if (E.value) { + lines.push_back(E.key.from); + lines.push_back(E.key.to); } } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 857190bc92..f179c01f89 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -357,8 +357,8 @@ int Node3DEditorViewport::get_selected_count() const { int count = 0; - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - Node3D *sp = Object::cast_to<Node3D>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + Node3D *sp = Object::cast_to<Node3D>(E.key); if (!sp) { continue; } @@ -864,8 +864,8 @@ void Node3DEditorViewport::_compute_edit(const Point2 &p_point) { Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr; if (se && se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) { - int subgizmo_id = E->key(); + for (const KeyValue<int, Transform3D> &E : se->subgizmos) { + int subgizmo_id = E.key; se->subgizmos[subgizmo_id] = se->gizmo->get_subgizmo_transform(subgizmo_id); } se->original_local = selected->get_transform(); @@ -1374,9 +1374,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector<int> ids; Vector<Transform3D> restore; - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - ids.push_back(GE->key()); - restore.push_back(GE->value()); + for (const KeyValue<int, Transform3D> &GE : se->subgizmos) { + ids.push_back(GE.key); + restore.push_back(GE.value); } se->gizmo->commit_subgizmos(ids, restore, true); @@ -1612,9 +1612,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector<int> ids; Vector<Transform3D> restore; - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - ids.push_back(GE->key()); - restore.push_back(GE->value()); + for (const KeyValue<int, Transform3D> &GE : se->subgizmos) { + ids.push_back(GE.key); + restore.push_back(GE.value); } se->gizmo->commit_subgizmos(ids, restore, false); @@ -1845,13 +1845,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - Transform3D xform = GE->get(); + for (KeyValue<int, Transform3D> &GE : se->subgizmos) { + Transform3D xform = GE.value; Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords); if (!local_coords) { new_xform = se->original.affine_inverse() * new_xform; } - se->gizmo->set_subgizmo_transform(GE->key(), new_xform); + se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords); @@ -1944,11 +1944,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - Transform3D xform = GE->get(); + for (KeyValue<int, Transform3D> &GE : se->subgizmos) { + Transform3D xform = GE.value; Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords); new_xform = se->original.affine_inverse() * new_xform; - se->gizmo->set_subgizmo_transform(GE->key(), new_xform); + se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords); @@ -2030,14 +2030,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector3 compute_axis = local_coords ? axis : plane.normal; if (se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - Transform3D xform = GE->get(); + for (KeyValue<int, Transform3D> &GE : se->subgizmos) { + Transform3D xform = GE.value; Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords); if (!local_coords) { new_xform = se->original.affine_inverse() * new_xform; } - se->gizmo->set_subgizmo_transform(GE->key(), new_xform); + se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords); @@ -2483,8 +2483,14 @@ static bool is_shortcut_pressed(const String &p_path) { if (shortcut.is_null()) { return false; } - InputEventKey *k = Object::cast_to<InputEventKey>(shortcut->get_event().ptr()); - if (k == nullptr) { + + const Array shortcuts = shortcut->get_events(); + Ref<InputEventKey> k; + if (shortcuts.size() > 0) { + k = shortcuts.front(); + } + + if (k.is_null()) { return false; } const Input &input = *Input::get_singleton(); @@ -2666,8 +2672,8 @@ void Node3DEditorViewport::_notification(int p_what) { bool changed = false; bool exist = false; - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - Node3D *sp = Object::cast_to<Node3D>(E->key()); + for (const KeyValue<Node *, Object *> &E : selection) { + Node3D *sp = Object::cast_to<Node3D>(E.key); if (!sp) { continue; } @@ -3809,8 +3815,8 @@ void Node3DEditorViewport::focus_selection() { } if (se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { - center += se->gizmo->get_subgizmo_transform(GE->key()).origin; + for (const KeyValue<int, Transform3D> &GE : se->subgizmos) { + center += se->gizmo->get_subgizmo_transform(GE.key).origin; count++; } } @@ -4750,8 +4756,8 @@ void Node3DEditor::update_transform_gizmo() { Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr; if (se && se->gizmo.is_valid()) { - for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) { - Transform3D xf = se->sp->get_global_transform() * se->gizmo->get_subgizmo_transform(E->key()); + for (const KeyValue<int, Transform3D> &E : se->subgizmos) { + Transform3D xf = se->sp->get_global_transform() * se->gizmo->get_subgizmo_transform(E.key); gizmo_center += xf.origin; if (count == 0 && local_gizmo_coords) { gizmo_basis = xf.basis; @@ -6677,8 +6683,8 @@ Vector<int> Node3DEditor::get_subgizmo_selection() { Vector<int> ret; if (se) { - for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) { - ret.push_back(E->key()); + for (const KeyValue<int, Transform3D> &E : se->subgizmos) { + ret.push_back(E.key); } } return ret; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 6922a48a50..ccb63871b7 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1030,35 +1030,22 @@ void ScriptEditor::_file_dialog_action(String p_file) { } file->close(); memdelete(file); - [[fallthrough]]; - } - case FILE_OPEN: { - List<String> extensions; - ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); - if (extensions.find(p_file.get_extension())) { - Ref<Script> scr = ResourceLoader::load(p_file); - if (!scr.is_valid()) { - editor->show_warning(TTR("Could not load file at:") + "\n\n" + p_file, TTR("Error!")); - file_dialog_option = -1; - return; - } - edit(scr); - file_dialog_option = -1; - return; - } - - Error error; - Ref<TextFile> text_file = _load_text_file(p_file, &error); - if (error != OK) { - editor->show_warning(TTR("Could not load file at:") + "\n\n" + p_file, TTR("Error!")); + if (EditorFileSystem::get_singleton()) { + const Vector<String> textfile_extensions = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + if (textfile_extensions.has(p_file.get_extension())) { + EditorFileSystem::get_singleton()->update_file(p_file); + } } - if (text_file.is_valid()) { - edit(text_file); - file_dialog_option = -1; + if (!open_textfile_after_create) { return; } + [[fallthrough]]; + } + case FILE_OPEN: { + open_file(p_file); + file_dialog_option = -1; } break; case FILE_SAVE_AS: { ScriptEditorBase *current = _get_current_editor(); @@ -1133,8 +1120,13 @@ void ScriptEditor::_menu_option(int p_option) { file_dialog_option = FILE_NEW_TEXTFILE; file_dialog->clear_filters(); + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (int i = 0; i < textfile_ext.size(); i++) { + file_dialog->add_filter("*." + textfile_ext[i] + " ; " + textfile_ext[i].to_upper()); + } file_dialog->popup_file_dialog(); file_dialog->set_title(TTR("New Text File...")); + open_textfile_after_create = true; } break; case FILE_OPEN: { file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); @@ -1148,6 +1140,11 @@ void ScriptEditor::_menu_option(int p_option) { file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (int i = 0; i < textfile_ext.size(); i++) { + file_dialog->add_filter("*." + textfile_ext[i] + " ; " + textfile_ext[i].to_upper()); + } + file_dialog->popup_file_dialog(); file_dialog->set_title(TTR("Open File")); return; @@ -2436,6 +2433,41 @@ void ScriptEditor::open_script_create_dialog(const String &p_base_name, const St script_create_dialog->config(p_base_name, p_base_path); } +void ScriptEditor::open_text_file_create_dialog(const String &p_base_path, const String &p_base_name) { + file_dialog->set_current_file(p_base_name); + file_dialog->set_current_dir(p_base_path); + _menu_option(FILE_NEW_TEXTFILE); + open_textfile_after_create = false; +} + +RES ScriptEditor::open_file(const String &p_file) { + List<String> extensions; + ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); + if (extensions.find(p_file.get_extension())) { + Ref<Script> scr = ResourceLoader::load(p_file); + if (!scr.is_valid()) { + editor->show_warning(TTR("Could not load file at:") + "\n\n" + p_file, TTR("Error!")); + return RES(); + } + + edit(scr); + return scr; + } + + Error error; + Ref<TextFile> text_file = _load_text_file(p_file, &error); + if (error != OK) { + editor->show_warning(TTR("Could not load file at:") + "\n\n" + p_file, TTR("Error!")); + return RES(); + } + + if (text_file.is_valid()) { + edit(text_file); + return text_file; + } + return RES(); +} + void ScriptEditor::_editor_stop() { for (int i = 0; i < tab_container->get_child_count(); i++) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 6d9b27e0be..e0c7e668ce 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -366,6 +366,7 @@ class ScriptEditor : public PanelContainer { void _add_callback(Object *p_obj, const String &p_function, const PackedStringArray &p_args); void _res_saved_callback(const Ref<Resource> &p_res); + bool open_textfile_after_create = true; bool trim_trailing_whitespace_on_save; bool use_space_indentation; bool convert_indent_on_save; @@ -472,6 +473,8 @@ public: bool is_scripts_panel_toggled(); void apply_scripts() const; void open_script_create_dialog(const String &p_base_name, const String &p_base_path); + void open_text_file_create_dialog(const String &p_base_path, const String &p_base_name = ""); + RES open_file(const String &p_file); void ensure_select_current(); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 22ca5592bd..a88e24c0d0 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -131,9 +131,9 @@ void ShaderTextEditor::_load_theme_settings() { List<String> built_ins; if (shader.is_valid()) { - for (const Map<StringName, ShaderLanguage::FunctionInfo>::Element *E = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())).front(); E; E = E->next()) { - for (const Map<StringName, ShaderLanguage::BuiltInInfo>::Element *F = E->get().built_ins.front(); F; F = F->next()) { - built_ins.push_back(F->key()); + for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()))) { + for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) { + built_ins.push_back(F.key); } } diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 165a381407..19e1b40a0d 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -437,8 +437,8 @@ void ThemeItemImportTree::_update_total_selected(Theme::DataType p_data_type) { } int count = 0; - for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) { - ThemeItem ti = E->key(); + for (const KeyValue<ThemeItem, ItemCheckedState> &E : selected_items) { + ThemeItem ti = E.key; if (ti.data_type == p_data_type) { count++; } @@ -759,7 +759,7 @@ void ThemeItemImportTree::_import_selected() { ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size() + 2); int idx = 0; - for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) { + for (KeyValue<ThemeItem, ItemCheckedState> &E : selected_items) { // Arbitrary number of items to skip from reporting. // Reduces the number of UI updates that this causes when copying large themes. if (idx % 10 == 0) { @@ -769,8 +769,8 @@ void ThemeItemImportTree::_import_selected() { ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Importing items {n}/{n}").format(arr, "{n}"), idx); } - ItemCheckedState cs = E->get(); - ThemeItem ti = E->key(); + ItemCheckedState cs = E.value; + ThemeItem ti = E.key; if (cs == SELECT_IMPORT_DEFINITION || cs == SELECT_IMPORT_FULL) { Variant item_value = Variant(); @@ -3333,7 +3333,7 @@ ThemeEditor::ThemeEditor() { preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL); preview_tabbar_hb->add_child(preview_tabs); preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab)); - preview_tabs->connect("right_button_pressed", callable_mp(this, &ThemeEditor::_remove_preview_tab)); + preview_tabs->connect("tab_rmb_clicked", callable_mp(this, &ThemeEditor::_remove_preview_tab)); HBoxContainer *add_preview_button_hb = memnew(HBoxContainer); preview_tabbar_hb->add_child(add_preview_button_hb); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index e98bd74b62..f21d5098d3 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -522,10 +522,10 @@ void TileAtlasView::_update_alternative_tiles_rect_cache() { } Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const { - for (Map<Vector2, Map<int, Rect2i>>::Element *E_coords = alternative_tiles_rect_cache.front(); E_coords; E_coords = E_coords->next()) { - for (Map<int, Rect2i>::Element *E_alternative = E_coords->value().front(); E_alternative; E_alternative = E_alternative->next()) { - if (E_alternative->value().has_point(p_pos)) { - return Vector3i(E_coords->key().x, E_coords->key().y, E_alternative->key()); + for (const KeyValue<Vector2, Map<int, Rect2i>> &E_coords : alternative_tiles_rect_cache) { + for (const KeyValue<int, Rect2i> &E_alternative : E_coords.value) { + if (E_alternative.value.has_point(p_pos)) { + return Vector3i(E_coords.key.x, E_coords.key.y, E_alternative.key); } } } diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 5f72cfe313..1a69d19d3c 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -756,10 +756,10 @@ Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_s } void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), p_new_value); } } @@ -1191,10 +1191,10 @@ Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_ } void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), p_new_value); } } @@ -1312,8 +1312,8 @@ void TileDataCollisionEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_ dummy_object->set(vformat("polygon_%d_one_way", i), tile_data->is_collision_polygon_one_way(physics_layer, i)); dummy_object->set(vformat("polygon_%d_one_way_margin", i), tile_data->get_collision_polygon_one_way_margin(physics_layer, i)); } - for (Map<StringName, EditorProperty *>::Element *E = property_editors.front(); E; E = E->next()) { - E->get()->update_property(); + for (const KeyValue<StringName, EditorProperty *> &E : property_editors) { + E.value->update_property(); } polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate()); @@ -1359,24 +1359,24 @@ Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { Array new_array = p_new_value; - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Array old_array = E->get(); + for (KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Array old_array = E.value; - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), old_array.size()); + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E.key.alternative_tile, physics_layer), old_array.size()); for (int i = 0; i < old_array.size(); i++) { Dictionary dict = old_array[i]; - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["points"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way_margin"]); } - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), new_array.size()); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E.key.alternative_tile, physics_layer), new_array.size()); for (int i = 0; i < new_array.size(); i++) { Dictionary dict = new_array[i]; - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["points"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way_margin"]); } } } @@ -2021,16 +2021,16 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t drag_type = DRAG_TYPE_NONE; } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) { undo_redo->create_action(TTR("Painting Terrain Set")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -2041,17 +2041,17 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t int terrain_set = int(painted["terrain_set"]); int terrain = int(painted["terrain"]); undo_redo->create_action(TTR("Painting Terrain")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain); } if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -2304,14 +2304,14 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi } else { if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) { undo_redo->create_action(TTR("Painting Tiles Property")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } undo_redo->commit_action(false); @@ -2321,17 +2321,17 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi int terrain_set = int(painted["terrain_set"]); int terrain = int(painted["terrain"]); undo_redo->create_action(TTR("Painting Terrain")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain); } if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -2443,10 +2443,10 @@ Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atla } void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), p_new_value); } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index a248f23517..cc5ff90541 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -455,15 +455,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p switch (drag_type) { case DRAG_TYPE_PAINT: { Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } break; case DRAG_TYPE_BUCKET: { @@ -471,15 +471,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed()); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } @@ -531,15 +531,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p drag_start_mouse_pos = mpos; drag_modified.clear(); Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } else if (tool_buttons_group->get_pressed_button() == line_tool_button) { drag_type = DRAG_TYPE_LINE; @@ -557,15 +557,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed()); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } @@ -710,8 +710,8 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Expand the grid if needed if (expand_grid && !preview.is_empty()) { drawn_grid_rect = Rect2i(preview.front()->key(), Vector2i(1, 1)); - for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { - drawn_grid_rect.expand_to(E->key()); + for (const KeyValue<Vector2i, TileMapCell> &E : preview) { + drawn_grid_rect.expand_to(E.key); } } } @@ -748,23 +748,23 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } // Draw the preview. - for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { + for (const KeyValue<Vector2i, TileMapCell> &E : preview) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(E->key())); + tile_xform.set_origin(tile_map->map_to_world(E.key)); tile_xform.set_scale(tile_set->get_tile_size()); if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) { tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } else { - if (tile_set->has_source(E->get().source_id)) { - TileSetSource *source = *tile_set->get_source(E->get().source_id); + if (tile_set->has_source(E.value.source_id)) { + TileSetSource *source = *tile_set->get_source(E.value.source_id); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { // Get tile data. - TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(E->get().get_atlas_coords(), E->get().alternative_tile)); + TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(E.value.get_atlas_coords(), E.value.alternative_tile)); // Compute the offset - Rect2i source_rect = atlas_source->get_tile_texture_region(E->get().get_atlas_coords()); - Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E->get().get_atlas_coords(), E->get().alternative_tile); + Rect2i source_rect = atlas_source->get_tile_texture_region(E.value.get_atlas_coords()); + Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E.value.get_atlas_coords(), E.value.alternative_tile); // Compute the destination rectangle in the CanvasItem. Rect2 dest_rect; @@ -772,9 +772,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over bool transpose = tile_data->get_transpose(); if (transpose) { - dest_rect.position = (tile_map->map_to_world(E->key()) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_world(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); } else { - dest_rect.position = (tile_map->map_to_world(E->key()) - dest_rect.size / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_world(E.key) - dest_rect.size / 2 - tile_offset); } dest_rect = xform.xform(dest_rect); @@ -1165,11 +1165,11 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } undo_redo->create_action(TTR("Move tiles")); // Move the tiles. - for (Map<Vector2i, TileMapCell>::Element *E = cells_do.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } - for (Map<Vector2i, TileMapCell>::Element *E = cells_undo.front(); E; E = E->next()) { - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) { + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } // Update the selection. @@ -1205,41 +1205,41 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } break; case DRAG_TYPE_PAINT: { undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; case DRAG_TYPE_LINE: { Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos); undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); } undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos)); undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); } undo_redo->commit_action(); } break; case DRAG_TYPE_BUCKET: { undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; @@ -1364,17 +1364,17 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( } int vertical_offset = 0; - for (Map<int, List<const TileMapCell *>>::Element *E_source = per_source.front(); E_source; E_source = E_source->next()) { + for (const KeyValue<int, List<const TileMapCell *>> &E_source : per_source) { // Per source. List<const TileMapCell *> unorganized; Rect2i encompassing_rect_coords; Map<Vector2i, const TileMapCell *> organized_pattern; - TileSetSource *source = *tile_set->get_source(E_source->key()); + TileSetSource *source = *tile_set->get_source(E_source.key); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { // Organize using coordinates. - for (const TileMapCell *current : E_source->get()) { + for (const TileMapCell *current : E_source.value) { if (current->alternative_tile == 0) { organized_pattern[current->get_atlas_coords()] = current; } else { @@ -1393,14 +1393,14 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( } } else { // Add everything unorganized. - for (const TileMapCell *cell : E_source->get()) { + for (const TileMapCell *cell : E_source.value) { unorganized.push_back(cell); } } // Now add everything to the output pattern. - for (Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); E_cell; E_cell = E_cell->next()) { - selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); + for (const KeyValue<Vector2i, const TileMapCell *> &E_cell : organized_pattern) { + selection_pattern->set_cell(E_cell.key - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell.value->source_id, E_cell.value->get_atlas_coords(), E_cell.value->alternative_tile); } Vector2i organized_size = selection_pattern->get_size(); int unorganized_index = 0; @@ -2308,14 +2308,14 @@ Set<TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTerrainsPlugi // Returns all tiles compatible with the given constraints. Set<TerrainsTilePattern> compatible_terrain_tile_patterns; - for (Map<TerrainsTilePattern, Set<TileMapCell>>::Element *E = per_terrain_terrains_tile_patterns_tiles[p_terrain_set].front(); E; E = E->next()) { + for (const KeyValue<TerrainsTilePattern, Set<TileMapCell>> &E : per_terrain_terrains_tile_patterns_tiles[p_terrain_set]) { int valid = true; int in_pattern_count = 0; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) { // Check if the bit is compatible with the constraints. - Constraint terrain_bit_constraint = Constraint(tile_map, p_position, bit, E->key()[in_pattern_count]); + Constraint terrain_bit_constraint = Constraint(tile_map, p_position, bit, E.key[in_pattern_count]); Set<Constraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint); if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { @@ -2327,7 +2327,7 @@ Set<TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTerrainsPlugi } if (valid) { - compatible_terrain_tile_patterns.insert(E->key()); + compatible_terrain_tile_patterns.insert(E.key); } } @@ -2368,15 +2368,15 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c // Count the number of occurrences per terrain. Map<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); - for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_overlapping = overlapping_terrain_bits.front(); E_overlapping; E_overlapping = E_overlapping->next()) { - if (!p_to_replace.has(E_overlapping->key())) { - TileMapCell neighbor_cell = tile_map->get_cell(tile_map_layer, E_overlapping->key()); + for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) { + if (!p_to_replace.has(E_overlapping.key)) { + TileMapCell neighbor_cell = tile_map->get_cell(tile_map_layer, E_overlapping.key); TileData *neighbor_tile_data = nullptr; if (terrain_tiles.has(neighbor_cell) && terrain_tiles[neighbor_cell]->get_terrain_set() == p_terrain_set) { neighbor_tile_data = terrain_tiles[neighbor_cell]; } - int terrain = neighbor_tile_data ? neighbor_tile_data->get_peering_bit_terrain(TileSet::CellNeighbor(E_overlapping->get())) : -1; + int terrain = neighbor_tile_data ? neighbor_tile_data->get_peering_bit_terrain(TileSet::CellNeighbor(E_overlapping.value)) : -1; if (terrain_count.has(terrain)) { terrain_count[terrain] = 0; } @@ -2387,10 +2387,10 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c // Get the terrain with the max number of occurrences. int max = 0; int max_terrain = -1; - for (Map<int, int>::Element *E_terrain_count = terrain_count.front(); E_terrain_count; E_terrain_count = E_terrain_count->next()) { - if (E_terrain_count->get() > max) { - max = E_terrain_count->get(); - max_terrain = E_terrain_count->key(); + for (const KeyValue<int, int> &E_terrain_count : terrain_count) { + if (E_terrain_count.value > max) { + max = E_terrain_count.value; + max_terrain = E_terrain_count.key; } } @@ -2458,15 +2458,15 @@ Map<Vector2i, TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTer while (!to_replace.is_empty()) { // Compute the minimum number of tile possibilities for each cell. int min_nb_possibilities = 100000000; - for (Map<Vector2i, Set<TerrainsTilePattern>>::Element *E = per_cell_acceptable_tiles.front(); E; E = E->next()) { - min_nb_possibilities = MIN(min_nb_possibilities, E->get().size()); + for (const KeyValue<Vector2i, Set<TerrainsTilePattern>> &E : per_cell_acceptable_tiles) { + min_nb_possibilities = MIN(min_nb_possibilities, E.value.size()); } // Get the set of possible cells to fill. LocalVector<Vector2i> to_choose_from; - for (Map<Vector2i, Set<TerrainsTilePattern>>::Element *E = per_cell_acceptable_tiles.front(); E; E = E->next()) { - if (E->get().size() == min_nb_possibilities) { - to_choose_from.push_back(E->key()); + for (const KeyValue<Vector2i, Set<TerrainsTilePattern>> &E : per_cell_acceptable_tiles) { + if (E.value.size() == min_nb_possibilities) { + to_choose_from.push_back(E.key); } } @@ -2584,9 +2584,9 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map // Add the constraints from the added tiles. Set<TileMapEditorTerrainsPlugin::Constraint> added_tiles_constraints_set; - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - Vector2i coords = E_to_paint->key(); - TerrainsTilePattern terrains_tile_pattern = E_to_paint->get(); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + Vector2i coords = E_to_paint.key; + TerrainsTilePattern terrains_tile_pattern = E_to_paint.value; Set<TileMapEditorTerrainsPlugin::Constraint> cell_constraints = _get_constraints_from_added_tile(coords, p_terrain_set, terrains_tile_pattern); for (Set<TileMapEditorTerrainsPlugin::Constraint>::Element *E = cell_constraints.front(); E; E = E->next()) { @@ -2596,8 +2596,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map // Build the list of potential tiles to replace. Set<Vector2i> potential_to_replace; - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - Vector2i coords = E_to_paint->key(); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + Vector2i coords = E_to_paint.key; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { if (tile_map->is_existing_neighbor(TileSet::CellNeighbor(i))) { Vector2i neighbor = tile_map->get_neighbor_cell(coords, TileSet::CellNeighbor(i)); @@ -2612,8 +2612,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Set<Vector2i> to_replace; // Add the central tiles to the one to replace. TODO: maybe change that. - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - to_replace.insert(E_to_paint->key()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + to_replace.insert(E_to_paint.key); } // Add the constraints from the surroundings of the modified areas. @@ -2627,9 +2627,9 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Map<Constraint, Set<Vector2i>> source_tiles_of_constraint; for (Set<Constraint>::Element *E = removed_cells_constraints_set.front(); E; E = E->next()) { Map<Vector2i, TileSet::CellNeighbor> sources_of_constraint = E->get().get_overlapping_coords_and_peering_bits(); - for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_source_tile_of_constraint = sources_of_constraint.front(); E_source_tile_of_constraint; E_source_tile_of_constraint = E_source_tile_of_constraint->next()) { - if (potential_to_replace.has(E_source_tile_of_constraint->key())) { - source_tiles_of_constraint[E->get()].insert(E_source_tile_of_constraint->key()); + for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_source_tile_of_constraint : sources_of_constraint) { + if (potential_to_replace.has(E_source_tile_of_constraint.key)) { + source_tiles_of_constraint[E->get()].insert(E_source_tile_of_constraint.key); } } } @@ -2646,8 +2646,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map potential_to_replace.erase(to_add_to_remove); to_replace.insert(to_add_to_remove); to_replace_modified = true; - for (Map<Constraint, Set<Vector2i>>::Element *E_source_tiles_of_constraint = source_tiles_of_constraint.front(); E_source_tiles_of_constraint; E_source_tiles_of_constraint = E_source_tiles_of_constraint->next()) { - E_source_tiles_of_constraint->get().erase(to_add_to_remove); + for (KeyValue<Constraint, Set<Vector2i>> &E_source_tiles_of_constraint : source_tiles_of_constraint) { + E_source_tiles_of_constraint.value.erase(to_add_to_remove); } break; } @@ -2665,13 +2665,13 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Map<Vector2i, TerrainsTilePattern> wfc_output = _wave_function_collapse(to_replace, p_terrain_set, constraints); // Use the WFC run for the output. - for (Map<Vector2i, TerrainsTilePattern>::Element *E = wfc_output.front(); E; E = E->next()) { - output[E->key()] = _get_random_tile_from_pattern(p_terrain_set, E->get()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E : wfc_output) { + output[E.key] = _get_random_tile_from_pattern(p_terrain_set, E.value); } // Override the WFC results to make sure at least the painted tiles are actually painted. - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - output[E_to_paint->key()] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint->get()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + output[E_to_paint.key] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint.value); } return output; @@ -2749,9 +2749,9 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { } break; case DRAG_TYPE_PAINT: { undo_redo->create_action(TTR("Paint terrain")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; @@ -2825,11 +2825,11 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> to_draw[line[i]] = selected_terrains_tile_pattern; } Map<Vector2i, TileMapCell> modified = _draw_terrains(to_draw, selected_terrain_set); - for (Map<Vector2i, TileMapCell>::Element *E = modified.front(); E; E = E->next()) { - if (!drag_modified.has(E->key())) { - drag_modified[E->key()] = tile_map->get_cell(tile_map_layer, E->key()); + for (const KeyValue<Vector2i, TileMapCell> &E : modified) { + if (!drag_modified.has(E.key)) { + drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); } - tile_map->set_cell(tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } break; @@ -2864,9 +2864,9 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> terrains_to_draw[tile_map->world_to_map(mpos)] = selected_terrains_tile_pattern; Map<Vector2i, TileMapCell> to_draw = _draw_terrains(terrains_to_draw, selected_terrain_set); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - drag_modified[E->key()] = tile_map->get_cell(tile_map_layer, E->key()); - tile_map->set_cell(tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); + tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 1f1408016b..bc026146ef 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -674,9 +674,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { #undef ADD_TILE_DATA_EDITOR // Add tile data editors as children. - for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) { + for (KeyValue<String, TileDataEditor *> &E : tile_data_editors) { // Tile Data Editor. - TileDataEditor *tile_data_editor = E->get(); + TileDataEditor *tile_data_editor = E.value; if (!tile_data_editor->is_inside_tree()) { tile_data_painting_editor_container->add_child(tile_data_editor); } @@ -716,9 +716,9 @@ void TileSetAtlasSourceEditor::_update_current_tile_data_editor() { } // Hide all editors but the current one. - for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) { - E->get()->hide(); - E->get()->get_toolbar()->hide(); + for (const KeyValue<String, TileDataEditor *> &E : tile_data_editors) { + E.value->hide(); + E.value->get_toolbar()->hide(); } if (tile_data_editors.has(property)) { current_tile_data_editor = tile_data_editors[property]; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 27f30479cf..b1b64564bb 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -123,9 +123,9 @@ void VisualShaderGraphPlugin::set_connections(List<VisualShader::Connection> &p_ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id) { if (visual_shader->get_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].output_ports.has(p_port_id)) { - for (Map<int, Port>::Element *E = links[p_node_id].output_ports.front(); E; E = E->next()) { - if (E->value().preview_button != nullptr) { - E->value().preview_button->set_pressed(false); + for (const KeyValue<int, Port> &E : links[p_node_id].output_ports) { + if (E.value.preview_button != nullptr) { + E.value.preview_button->set_pressed(false); } } @@ -264,11 +264,11 @@ void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, } void VisualShaderGraphPlugin::update_uniform_refs() { - for (Map<int, Link>::Element *E = links.front(); E; E = E->next()) { - VisualShaderNodeUniformRef *ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().visual_node); + for (KeyValue<int, Link> &E : links) { + VisualShaderNodeUniformRef *ref = Object::cast_to<VisualShaderNodeUniformRef>(E.value.visual_node); if (ref) { - remove_node(E->get().type, E->key()); - add_node(E->get().type, E->key()); + remove_node(E.value.type, E.key); + add_node(E.value.type, E.key); } } } diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index 3441060fad..95a5646013 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -63,9 +63,9 @@ void BackgroundProgress::_add_task(const String &p_task, const String &p_label, void BackgroundProgress::_update() { _THREAD_SAFE_METHOD_ - for (Map<String, int>::Element *E = updates.front(); E; E = E->next()) { - if (tasks.has(E->key())) { - _task_step(E->key(), E->get()); + for (const KeyValue<String, int> &E : updates) { + if (tasks.has(E.key)) { + _task_step(E.key, E.value); } } diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 14158b02c8..ad9c81458f 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -752,6 +752,9 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem if (p_only_scenes && type != "PackedScene") { continue; } + if (type == "TextFile") { + continue; + } TreeItem *file = include_files->create_item(p_item); file->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index d2e8880bf9..a100e9fc55 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -517,8 +517,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup); - for (Map<const Node *, Node *>::Element *E2 = duplimap.front(); E2; E2 = E2->next()) { - Node *d = E2->value(); + for (KeyValue<const Node *, Node *> &E2 : duplimap) { + Node *d = E2.value; editor_data->get_undo_redo().add_do_method(d, "set_owner", owner); } @@ -848,8 +848,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } Ref<MultiNodeEdit> mne = memnew(MultiNodeEdit); - for (const Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) { - mne->add_node(root->get_path_to(E->key())); + for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) { + mne->add_node(root->get_path_to(E.key)); } EditorNode::get_singleton()->push_item(mne.ptr()); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 4cbc859e0c..1e19d9bd47 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -425,8 +425,8 @@ void ScriptCreateDialog::_lang_changed(int l) { templates[i].id = new_id; } // Disable overridden - for (Map<String, Vector<int>>::Element *E = template_overrides.front(); E; E = E->next()) { - const Vector<int> &overrides = E->get(); + for (const KeyValue<String, Vector<int>> &E : template_overrides) { + const Vector<int> &overrides = E.value; if (overrides.size() == 1) { continue; // doesn't override anything diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index f024589ef1..9062169e06 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -193,35 +193,25 @@ void EditorSettingsDialog::_event_config_confirmed() { return; } - if (editing_action) { - if (current_action_event_index == -1) { - // Add new event - current_action_events.push_back(k); - } else { - // Edit existing event - current_action_events[current_action_event_index] = k; - } + if (current_event_index == -1) { + // Add new event + current_events.push_back(k); + } else { + // Edit existing event + current_events[current_event_index] = k; + } - _update_builtin_action(current_action, current_action_events); + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, current_events); } else { - k = k->duplicate(); - Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(shortcut_being_edited); - - undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_being_edited + "'"); - undo_redo->add_do_method(current_sc.ptr(), "set_event", k); - undo_redo->add_undo_method(current_sc.ptr(), "set_event", current_sc->get_event()); - undo_redo->add_do_method(this, "_update_shortcuts"); - undo_redo->add_undo_method(this, "_update_shortcuts"); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - undo_redo->commit_action(); + _update_shortcut_events(current_edited_identifier, current_events); } } void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) { - Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(current_action); + Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name); - undo_redo->create_action(TTR("Edit Built-in Action")); + undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'"); undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events); undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array); undo_redo->add_do_method(this, "_settings_changed"); @@ -231,15 +221,125 @@ void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Ar _update_shortcuts(); } +void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const Array &p_events) { + Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(p_path); + + undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'"); + undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events); + undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events()); + undo_redo->add_do_method(this, "_update_shortcuts"); + undo_redo->add_undo_method(this, "_update_shortcuts"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +Array EditorSettingsDialog::_event_list_to_array_helper(List<Ref<InputEvent>> &p_events) { + Array events; + + // Convert the list to an array, and only keep key events as this is for the editor. + for (List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) { + Ref<InputEventKey> k = E->get(); + if (k.is_valid()) { + events.append(E->get()); + } + } + + return events; +} + +void EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_action, bool p_is_collapsed) { + TreeItem *shortcut_item = shortcuts->create_item(p_parent); + shortcut_item->set_collapsed(p_is_collapsed); + shortcut_item->set_text(0, p_display); + + Ref<InputEvent> primary = p_events.size() > 0 ? Ref<InputEvent>(p_events[0]) : Ref<InputEvent>(); + Ref<InputEvent> secondary = p_events.size() > 1 ? Ref<InputEvent>(p_events[1]) : Ref<InputEvent>(); + + String sc_text = "None"; + if (primary.is_valid()) { + sc_text = primary->as_text(); + + if (secondary.is_valid()) { + sc_text += ", " + secondary->as_text(); + + if (p_events.size() > 2) { + sc_text += " (+" + itos(p_events.size() - 2) + ")"; + } + } + } + + shortcut_item->set_text(1, sc_text); + if (sc_text == "None") { + // Fade out unassigned shortcut labels for easier visual grepping. + shortcut_item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5)); + } + + if (p_allow_revert) { + shortcut_item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), SHORTCUT_REVERT); + } + + shortcut_item->add_button(1, shortcuts->get_theme_icon("Add", "EditorIcons"), SHORTCUT_ADD); + shortcut_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); + + shortcut_item->set_meta("is_action", p_is_action); + shortcut_item->set_meta("type", "shortcut"); + shortcut_item->set_meta("shortcut_identifier", p_shortcut_identifier); + shortcut_item->set_meta("events", p_events); + + // Shortcut Input Events + for (int i = 0; i < p_events.size(); i++) { + Ref<InputEvent> ie = p_events[i]; + if (ie.is_null()) { + continue; + } + + TreeItem *event_item = shortcuts->create_item(shortcut_item); + + event_item->set_text(0, shortcut_item->get_child_count() == 1 ? "Primary" : ""); + event_item->set_text(1, ie->as_text()); + + event_item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), SHORTCUT_EDIT); + event_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); + + event_item->set_custom_bg_color(0, shortcuts->get_theme_color("dark_color_3", "Editor")); + event_item->set_custom_bg_color(1, shortcuts->get_theme_color("dark_color_3", "Editor")); + + event_item->set_meta("is_action", p_is_action); + event_item->set_meta("type", "event"); + event_item->set_meta("event_index", i); + } +} + void EditorSettingsDialog::_update_shortcuts() { // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated. Map<String, bool> collapsed; if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) { - for (TreeItem *item = shortcuts->get_root()->get_first_child(); item; item = item->get_next()) { - collapsed[item->get_text(0)] = item->is_collapsed(); + TreeItem *ti = shortcuts->get_root()->get_first_child(); + while (ti) { + // Not all items have valid or unique text in the first column - so if it has an identifier, use that, as it should be unique. + if (ti->get_first_child() && ti->has_meta("shortcut_identifier")) { + collapsed[ti->get_meta("shortcut_identifier")] = ti->is_collapsed(); + } else { + collapsed[ti->get_text(0)] = ti->is_collapsed(); + } + + // Try go down tree + TreeItem *ti_next = ti->get_first_child(); + // Try go across tree + if (!ti_next) { + ti_next = ti->get_next(); + } + // Try go up tree, to next node + if (!ti_next) { + ti_next = ti->get_parent()->get_next(); + } + + ti = ti_next; } } + shortcuts->clear(); TreeItem *root = shortcuts->create_item(); @@ -247,7 +347,6 @@ void EditorSettingsDialog::_update_shortcuts() { // Set up section for Common/Built-in actions TreeItem *common_section = shortcuts->create_item(root); - sections["Common"] = common_section; common_section->set_text(0, TTR("Common")); common_section->set_selectable(0, false); @@ -262,7 +361,6 @@ void EditorSettingsDialog::_update_shortcuts() { OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map(); for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) { String action_name = E.key(); - InputMap::Action action = E.get(); Array events; // Need to get the list of events into an array so it can be set as metadata on the item. @@ -278,21 +376,6 @@ void EditorSettingsDialog::_update_shortcuts() { } } - bool same_as_defaults = key_default_events.size() == action.inputs.size(); // Initially this is set to just whether the arrays are equal. Later we check the events if needed. - - int count = 0; - for (List<Ref<InputEvent>>::Element *I = action.inputs.front(); I; I = I->next()) { - // Add event and event text to respective arrays. - events.push_back(I->get()); - event_strings.push_back(I->get()->as_text()); - - // Only check if the events have been the same so far - once one fails, we don't need to check any more. - if (same_as_defaults && !key_default_events[count]->is_match(I->get())) { - same_as_defaults = false; - } - count++; - } - // Join the text of the events with a delimiter so they can all be displayed in one cell. String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings); @@ -300,25 +383,12 @@ void EditorSettingsDialog::_update_shortcuts() { continue; } - TreeItem *item = shortcuts->create_item(common_section); - item->set_text(0, action_name); - item->set_text(1, events_display_string); - - if (!same_as_defaults) { - item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2); - } - - if (events_display_string == "None") { - // Fade out unassigned shortcut labels for easier visual grepping. - item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5)); - } + Array action_events = _event_list_to_array_helper(action.inputs); + Array default_events = _event_list_to_array_helper(all_default_events); + bool same_as_defaults = Shortcut::is_event_array_equal(default_events, action_events); + bool collapse = !collapsed.has(action_name) || (collapsed.has(action_name) && collapsed[action_name]); - item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0); - item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1); - item->set_tooltip(0, action_name); - item->set_tooltip(1, events_display_string); - item->set_metadata(0, "Common"); - item->set_metadata(1, events); + _create_shortcut_treeitem(common_section, action_name, action_name, action_events, !same_as_defaults, true, collapse); } // Editor Shortcuts @@ -332,11 +402,10 @@ void EditorSettingsDialog::_update_shortcuts() { continue; } - Ref<InputEvent> original = sc->get_meta("original"); - - String section_name = E.get_slice("/", 0); + // Shortcut Section TreeItem *section; + String section_name = E.get_slice("/", 0); if (sections.has(section_name)) { section = sections[section_name]; @@ -357,33 +426,23 @@ void EditorSettingsDialog::_update_shortcuts() { sections[section_name] = section; } - // Don't match unassigned shortcuts when searching for assigned keys in search results. - // This prevents all unassigned shortcuts from appearing when searching a string like "no". - if (shortcut_filter.is_subsequence_ofi(sc->get_name()) || (sc->get_as_text() != "None" && shortcut_filter.is_subsequence_ofi(sc->get_as_text()))) { - TreeItem *item = shortcuts->create_item(section); - - item->set_text(0, sc->get_name()); - item->set_text(1, sc->get_as_text()); + // Shortcut Item - if (!sc->matches_event(original) && !(sc->get_event().is_null() && original.is_null())) { - item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2); - } + if (!shortcut_filter.is_subsequence_ofi(sc->get_name())) { + continue; + } - if (sc->get_as_text() == "None") { - // Fade out unassigned shortcut labels for easier visual grepping. - item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5)); - } + Array original = sc->get_meta("original"); + Array shortcuts_array = sc->get_events(); + bool same_as_defaults = Shortcut::is_event_array_equal(original, shortcuts_array); + bool collapse = !collapsed.has(E) || (collapsed.has(E) && collapsed[E]); - item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0); - item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1); - item->set_tooltip(0, E); - item->set_metadata(0, E); - } + _create_shortcut_treeitem(section, E, sc->get_name(), shortcuts_array, !same_as_defaults, false, collapse); } // remove sections with no shortcuts - for (Map<String, TreeItem *>::Element *E = sections.front(); E; E = E->next()) { - TreeItem *section = E->get(); + for (KeyValue<String, TreeItem *> &E : sections) { + TreeItem *section = E.value; if (section->get_first_child() == nullptr) { root->remove_child(section); } @@ -392,123 +451,130 @@ void EditorSettingsDialog::_update_shortcuts() { void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx) { TreeItem *ti = Object::cast_to<TreeItem>(p_item); - ERR_FAIL_COND(!ti); - - button_idx = p_idx; + ERR_FAIL_COND_MSG(!ti, "Object passed is not a TreeItem"); - if (ti->get_metadata(0) == "Common") { - // Editing a Built-in action, which can have multiple bindings. - editing_action = true; - current_action = ti->get_text(0); + ShortcutButton button_idx = (ShortcutButton)p_idx; - switch (button_idx) { - case SHORTCUT_REVERT: { - Array events; - List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_action]; + is_editing_action = ti->get_meta("is_action"); - // Convert the list to an array, and only keep key events as this is for the editor. - for (const Ref<InputEvent> &k : defaults) { - if (k.is_valid()) { - events.append(k); - } - } + String type = ti->get_meta("type"); - _update_builtin_action(current_action, events); - } break; - case SHORTCUT_EDIT: - case SHORTCUT_ERASE: { - // For Edit end Delete, we will show a popup which displays each event so the user can select which one to edit/delete. - current_action_events = ti->get_metadata(1); - action_popup->clear(); - - for (int i = 0; i < current_action_events.size(); i++) { - Ref<InputEvent> ie = current_action_events[i]; - action_popup->add_item(ie->as_text()); - action_popup->set_item_metadata(i, ie); - } - - if (button_idx == SHORTCUT_EDIT) { - // If editing, add a button which can be used to add an additional event. - action_popup->add_icon_item(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add")); - } + if (type == "event") { + current_edited_identifier = ti->get_parent()->get_meta("shortcut_identifier"); + current_events = ti->get_parent()->get_meta("events"); + current_event_index = ti->get_meta("event_index"); + } else { // Type is "shortcut" + current_edited_identifier = ti->get_meta("shortcut_identifier"); + current_events = ti->get_meta("events"); + current_event_index = -1; + } - action_popup->set_position(get_position() + get_mouse_position()); - action_popup->take_mouse_focus(); - action_popup->popup(); - action_popup->set_as_minsize(); - } break; - default: - break; - } - } else { - // Editing an Editor Shortcut, which can only have 1 binding. - String item = ti->get_metadata(0); - Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(item); - editing_action = false; - - switch (button_idx) { - case EditorSettingsDialog::SHORTCUT_EDIT: - shortcut_editor->popup_and_configure(sc->get_event()); - shortcut_being_edited = item; - break; - case EditorSettingsDialog::SHORTCUT_ERASE: { - if (!sc.is_valid()) { - return; //pointless, there is nothing + switch (button_idx) { + case EditorSettingsDialog::SHORTCUT_ADD: { + // Only for "shortcut" types + shortcut_editor->popup_and_configure(); + } break; + case EditorSettingsDialog::SHORTCUT_EDIT: { + // Only for "event" types + shortcut_editor->popup_and_configure(current_events[current_event_index]); + } break; + case EditorSettingsDialog::SHORTCUT_ERASE: { + if (type == "shortcut") { + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, Array()); + } else { + _update_shortcut_events(current_edited_identifier, Array()); } + } else if (type == "event") { + current_events.remove(current_event_index); - undo_redo->create_action(TTR("Erase Shortcut")); - undo_redo->add_do_method(sc.ptr(), "set_event", Ref<InputEvent>()); - undo_redo->add_undo_method(sc.ptr(), "set_event", sc->get_event()); - undo_redo->add_do_method(this, "_update_shortcuts"); - undo_redo->add_undo_method(this, "_update_shortcuts"); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - undo_redo->commit_action(); - } break; - case EditorSettingsDialog::SHORTCUT_REVERT: { - if (!sc.is_valid()) { - return; //pointless, there is nothing + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, current_events); + } else { + _update_shortcut_events(current_edited_identifier, current_events); } + } + } break; + case EditorSettingsDialog::SHORTCUT_REVERT: { + // Only for "shortcut" types + if (is_editing_action) { + List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_edited_identifier]; + Array events = _event_list_to_array_helper(defaults); - Ref<InputEvent> original = sc->get_meta("original"); - - undo_redo->create_action(TTR("Restore Shortcut")); - undo_redo->add_do_method(sc.ptr(), "set_event", original); - undo_redo->add_undo_method(sc.ptr(), "set_event", sc->get_event()); - undo_redo->add_do_method(this, "_update_shortcuts"); - undo_redo->add_undo_method(this, "_update_shortcuts"); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - undo_redo->commit_action(); - } break; - default: - break; - } - } -} - -void EditorSettingsDialog::_builtin_action_popup_index_pressed(int p_index) { - switch (button_idx) { - case SHORTCUT_EDIT: { - if (p_index == action_popup->get_item_count() - 1) { - // Selected last item in list (Add button), therefore add new - current_action_event_index = -1; - shortcut_editor->popup_and_configure(); + _update_builtin_action(current_edited_identifier, events); } else { - // Configure existing - current_action_event_index = p_index; - shortcut_editor->popup_and_configure(action_popup->get_item_metadata(p_index)); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(current_edited_identifier); + Array original = sc->get_meta("original"); + _update_shortcut_events(current_edited_identifier, original); } } break; - case SHORTCUT_ERASE: { - current_action_events.remove(p_index); - _update_builtin_action(current_action, current_action_events); - } break; default: break; } } +Variant EditorSettingsDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + TreeItem *selected = shortcuts->get_selected(); + + // Only allow drag for events + if (!selected || !selected->has_meta("type") || selected->get_meta("type") != "event") { + return Variant(); + } + + String label_text = "Event " + itos(selected->get_meta("event_index")); + Label *label = memnew(Label(label_text)); + label->set_modulate(Color(1, 1, 1, 1.0f)); + shortcuts->set_drag_preview(label); + + shortcuts->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); + + return Dictionary(); // No data required +} + +bool EditorSettingsDialog::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + TreeItem *selected = shortcuts->get_selected(); + TreeItem *item = shortcuts->get_item_at_position(p_point); + if (!selected || !item || item == selected || !item->has_meta("type") || item->get_meta("type") != "event") { + return false; + } + + // Don't allow moving an events in-between shortcuts. + if (selected->get_parent()->get_meta("shortcut_identifier") != item->get_parent()->get_meta("shortcut_identifier")) { + return false; + } + + return true; +} + +void EditorSettingsDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) { + return; + } + + TreeItem *selected = shortcuts->get_selected(); + TreeItem *target = shortcuts->get_item_at_position(p_point); + + if (!target) { + return; + } + + int target_event_index = target->get_meta("event_index"); + int index_moving_from = selected->get_meta("event_index"); + + Array events = selected->get_parent()->get_meta("events"); + + Variant event_moved = events[index_moving_from]; + events.remove(index_moving_from); + events.insert(target_event_index, event_moved); + + String ident = selected->get_parent()->get_meta("shortcut_identifier"); + if (selected->get_meta("is_action")) { + _update_builtin_action(ident, events); + } else { + _update_shortcut_events(ident, events); + } +} + void EditorSettingsDialog::_tabs_tab_changed(int p_tab) { _focus_current_search_box(); } @@ -544,13 +610,13 @@ void EditorSettingsDialog::_editor_restart_close() { void EditorSettingsDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts); ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed); + + ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &EditorSettingsDialog::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorSettingsDialog::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorSettingsDialog::drop_data_fw); } EditorSettingsDialog::EditorSettingsDialog() { - action_popup = memnew(PopupMenu); - action_popup->connect("index_pressed", callable_mp(this, &EditorSettingsDialog::_builtin_action_popup_index_pressed)); - add_child(action_popup); - set_title(TTR("Editor Settings")); undo_redo = memnew(UndoRedo); @@ -628,6 +694,8 @@ EditorSettingsDialog::EditorSettingsDialog() { shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed)); tab_shortcuts->add_child(shortcuts); + shortcuts->set_drag_forwarding(this); + // Adding event dialog shortcut_editor = memnew(InputEventConfigurationDialog); shortcut_editor->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_event_config_confirmed)); diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h index 2b6c9b3e1d..7317a014b2 100644 --- a/editor/settings_config_dialog.h +++ b/editor/settings_config_dialog.h @@ -53,29 +53,28 @@ class EditorSettingsDialog : public AcceptDialog { LineEdit *shortcut_search_box; SectionedInspector *inspector; + // Shortcuts enum ShortcutButton { + SHORTCUT_ADD, SHORTCUT_EDIT, SHORTCUT_ERASE, SHORTCUT_REVERT }; - int button_idx; - int current_action_event_index = -1; - bool editing_action = false; - String current_action; - Array current_action_events; - PopupMenu *action_popup; + Tree *shortcuts; + String shortcut_filter; + + InputEventConfigurationDialog *shortcut_editor; + + bool is_editing_action = false; + String current_edited_identifier; + Array current_events; + int current_event_index = -1; Timer *timer; UndoRedo *undo_redo; - // Shortcuts - String shortcut_filter; - Tree *shortcuts; - InputEventConfigurationDialog *shortcut_editor; - String shortcut_being_edited; - virtual void cancel_pressed() override; virtual void ok_pressed() override; @@ -89,7 +88,14 @@ class EditorSettingsDialog : public AcceptDialog { void _event_config_confirmed(); + void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed); + Array _event_list_to_array_helper(List<Ref<InputEvent>> &p_events); void _update_builtin_action(const String &p_name, const Array &p_events); + void _update_shortcut_events(const String &p_path, const Array &p_events); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); void _tabs_tab_changed(int p_tab); void _focus_current_search_box(); |