diff options
Diffstat (limited to 'editor')
24 files changed, 1796 insertions, 32 deletions
diff --git a/editor/editor_network_profiler.cpp b/editor/editor_network_profiler.cpp new file mode 100644 index 0000000000..b90fe96cee --- /dev/null +++ b/editor/editor_network_profiler.cpp @@ -0,0 +1,192 @@ +/*************************************************************************/ +/* editor_network_profiler.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_network_profiler.h" + +#include "core/os/os.h" +#include "editor_scale.h" +#include "editor_settings.h" + +void EditorNetworkProfiler::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_frame"), &EditorNetworkProfiler::_update_frame); + ClassDB::bind_method(D_METHOD("_activate_pressed"), &EditorNetworkProfiler::_activate_pressed); + ClassDB::bind_method(D_METHOD("_clear_pressed"), &EditorNetworkProfiler::_clear_pressed); + ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable"))); +} + +void EditorNetworkProfiler::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + activate->set_icon(get_icon("Play", "EditorIcons")); + clear_button->set_icon(get_icon("Clear", "EditorIcons")); + } +} + +void EditorNetworkProfiler::_update_frame() { + + counters_display->clear(); + + TreeItem *root = counters_display->create_item(); + + for (Map<ObjectID, MultiplayerAPI::ProfilingInfo>::Element *E = nodes_data.front(); E; E = E->next()) { + + 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)); + } +} + +void EditorNetworkProfiler::_activate_pressed() { + + if (activate->is_pressed()) { + activate->set_icon(get_icon("Stop", "EditorIcons")); + activate->set_text(TTR("Stop")); + } else { + activate->set_icon(get_icon("Play", "EditorIcons")); + activate->set_text(TTR("Start")); + } + emit_signal("enable_profiling", activate->is_pressed()); +} + +void EditorNetworkProfiler::_clear_pressed() { + nodes_data.clear(); + set_bandwidth(0, 0); + if (frame_delay->is_stopped()) { + frame_delay->set_wait_time(0.1); + frame_delay->start(); + } +} + +void EditorNetworkProfiler::add_node_frame_data(const MultiplayerAPI::ProfilingInfo p_frame) { + + if (!nodes_data.has(p_frame.node)) { + nodes_data.insert(p_frame.node, p_frame); + } else { + nodes_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc; + nodes_data[p_frame.node].incoming_rset += p_frame.incoming_rset; + nodes_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc; + nodes_data[p_frame.node].outgoing_rset += p_frame.outgoing_rset; + } + + if (frame_delay->is_stopped()) { + frame_delay->set_wait_time(0.1); + frame_delay->start(); + } +} + +void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) { + + incoming_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_incoming))); + outgoing_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_outgoing))); +} + +bool EditorNetworkProfiler::is_profiling() { + return activate->is_pressed(); +} + +EditorNetworkProfiler::EditorNetworkProfiler() { + + HBoxContainer *hb = memnew(HBoxContainer); + hb->add_constant_override("separation", 8 * EDSCALE); + add_child(hb); + + activate = memnew(Button); + activate->set_toggle_mode(true); + activate->set_text(TTR("Start")); + activate->connect("pressed", this, "_activate_pressed"); + hb->add_child(activate); + + clear_button = memnew(Button); + clear_button->set_text(TTR("Clear")); + clear_button->connect("pressed", this, "_clear_pressed"); + hb->add_child(clear_button); + + hb->add_spacer(); + + Label *lb = memnew(Label); + lb->set_text("Down "); + hb->add_child(lb); + + incoming_bandwidth_text = memnew(LineEdit); + incoming_bandwidth_text->set_editable(false); + incoming_bandwidth_text->set_custom_minimum_size(Size2(100, 0)); + incoming_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT); + incoming_bandwidth_text->set_text("0.0 B/s"); + hb->add_child(incoming_bandwidth_text); + + lb = memnew(Label); + lb->set_text("Up "); + hb->add_child(lb); + + outgoing_bandwidth_text = memnew(LineEdit); + outgoing_bandwidth_text->set_editable(false); + outgoing_bandwidth_text->set_custom_minimum_size(Size2(100, 0)); + outgoing_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT); + outgoing_bandwidth_text->set_text("0.0 B/s"); + hb->add_child(outgoing_bandwidth_text); + + counters_display = memnew(Tree); + counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE); + counters_display->set_v_size_flags(SIZE_EXPAND_FILL); + counters_display->set_hide_folding(true); + counters_display->set_hide_root(true); + counters_display->set_columns(5); + counters_display->set_column_titles_visible(true); + counters_display->set_column_title(0, TTR("Node")); + counters_display->set_column_expand(0, true); + counters_display->set_column_min_width(0, 60); + counters_display->set_column_title(1, TTR("Incoming RPC")); + counters_display->set_column_expand(1, false); + counters_display->set_column_min_width(1, 120 * EDSCALE); + counters_display->set_column_title(2, TTR("Incoming RSET")); + counters_display->set_column_expand(2, false); + counters_display->set_column_min_width(2, 120 * EDSCALE); + counters_display->set_column_title(3, TTR("Outgoing RPC")); + counters_display->set_column_expand(3, false); + counters_display->set_column_min_width(3, 120 * EDSCALE); + counters_display->set_column_title(4, TTR("Outgoing RSET")); + counters_display->set_column_expand(4, false); + counters_display->set_column_min_width(4, 120 * EDSCALE); + add_child(counters_display); + + frame_delay = memnew(Timer); + frame_delay->set_wait_time(0.1); + frame_delay->set_one_shot(true); + add_child(frame_delay); + frame_delay->connect("timeout", this, "_update_frame"); +} diff --git a/editor/editor_network_profiler.h b/editor/editor_network_profiler.h new file mode 100644 index 0000000000..85fec340fd --- /dev/null +++ b/editor/editor_network_profiler.h @@ -0,0 +1,72 @@ +/*************************************************************************/ +/* editor_network_profiler.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITORNETWORKPROFILER_H +#define EDITORNETWORKPROFILER_H + +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/label.h" +#include "scene/gui/split_container.h" +#include "scene/gui/tree.h" + +class EditorNetworkProfiler : public VBoxContainer { + + GDCLASS(EditorNetworkProfiler, VBoxContainer) + +private: + Button *activate; + Button *clear_button; + Tree *counters_display; + LineEdit *incoming_bandwidth_text; + LineEdit *outgoing_bandwidth_text; + + Timer *frame_delay; + + Map<ObjectID, MultiplayerAPI::ProfilingInfo> nodes_data; + + void _update_frame(); + + void _activate_pressed(); + void _clear_pressed(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void add_node_frame_data(const MultiplayerAPI::ProfilingInfo p_frame); + void set_bandwidth(int p_incoming, int p_outgoing); + bool is_profiling(); + + EditorNetworkProfiler(); +}; + +#endif //EDITORNETWORKPROFILER_H diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 98f5fcbeec..a1998a1d7c 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -60,6 +60,7 @@ #include "editor/import/editor_import_collada.h" #include "editor/import/editor_scene_importer_gltf.h" #include "editor/import/resource_importer_bitmask.h" +#include "editor/import/resource_importer_csv.h" #include "editor/import/resource_importer_csv_translation.h" #include "editor/import/resource_importer_image.h" #include "editor/import/resource_importer_layered_texture.h" @@ -122,6 +123,7 @@ #include "editor/plugins/theme_editor_plugin.h" #include "editor/plugins/tile_map_editor_plugin.h" #include "editor/plugins/tile_set_editor_plugin.h" +#include "editor/plugins/version_control_editor_plugin.h" #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/pvrtc_compress.h" #include "editor/register_exporters.h" @@ -184,6 +186,20 @@ void EditorNode::_update_scene_tabs() { } } +void EditorNode::_version_control_menu_option(int p_idx) { + + switch (vcs_actions_menu->get_item_id(p_idx)) { + case RUN_VCS_SETTINGS: { + + VersionControlEditorPlugin::get_singleton()->popup_vcs_set_up_dialog(gui_base); + } break; + case RUN_VCS_SHUT_DOWN: { + + VersionControlEditorPlugin::get_singleton()->shut_down(); + } break; + } +} + void EditorNode::_update_title() { String appname = ProjectSettings::get_singleton()->get("application/config/name"); @@ -1835,6 +1851,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { String main_scene; String run_filename; String args; + bool skip_breakpoints; if (p_current || (editor_data.get_edited_scene_root() && p_custom == editor_data.get_edited_scene_root()->get_filename())) { @@ -1900,8 +1917,9 @@ void EditorNode::_run(bool p_current, const String &p_custom) { editor_data.get_editor_breakpoints(&breakpoints); args = ProjectSettings::get_singleton()->get("editor/main_run_args"); + skip_breakpoints = ScriptEditor::get_singleton()->get_debugger()->is_skip_breakpoints(); - Error error = editor_run.run(run_filename, args, breakpoints); + Error error = editor_run.run(run_filename, args, breakpoints, skip_breakpoints); if (error != OK) { @@ -3523,6 +3541,7 @@ void EditorNode::register_editor_types() { ClassDB::register_class<EditorResourcePreviewGenerator>(); ClassDB::register_virtual_class<EditorFileSystem>(); ClassDB::register_class<EditorFileSystemDirectory>(); + ClassDB::register_class<EditorVCSInterface>(); ClassDB::register_virtual_class<ScriptEditor>(); ClassDB::register_virtual_class<EditorInterface>(); ClassDB::register_class<EditorExportPlugin>(); @@ -5312,6 +5331,7 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files); ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant())); ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); + ClassDB::bind_method("_version_control_menu_option", &EditorNode::_version_control_menu_option); ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource); ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); @@ -5540,6 +5560,10 @@ EditorNode::EditorNode() { import_csv_translation.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); + Ref<ResourceImporterCSV> import_csv; + import_csv.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_csv); + Ref<ResourceImporterWAV> import_wav; import_wav.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_wav); @@ -5998,6 +6022,15 @@ EditorNode::EditorNode() { p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings...")), RUN_SETTINGS); p->connect("id_pressed", this, "_menu_option"); + vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel(); + vcs_actions_menu->set_name("Version Control"); + vcs_actions_menu->connect("index_pressed", this, "_version_control_menu_option"); + p->add_separator(); + p->add_child(vcs_actions_menu); + p->add_submenu_item(TTR("Version Control"), "Version Control"); + vcs_actions_menu->add_item(TTR("Set Up Version Control"), RUN_VCS_SETTINGS); + vcs_actions_menu->add_item(TTR("Shut Down Version Control"), RUN_VCS_SHUT_DOWN); + p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT); p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); @@ -6007,7 +6040,6 @@ EditorNode::EditorNode() { plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); gui_base->add_child(plugin_config_dialog); - p->add_separator(); tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); tool_menu->connect("index_pressed", this, "_tool_menu_option"); @@ -6472,6 +6504,7 @@ EditorNode::EditorNode() { //more visually meaningful to have this later raise_bottom_panel_item(AnimationPlayerEditor::singleton); + add_editor_plugin(VersionControlEditorPlugin::get_singleton()); add_editor_plugin(memnew(ShaderEditorPlugin(this))); add_editor_plugin(memnew(VisualShaderEditorPlugin(this))); diff --git a/editor/editor_node.h b/editor/editor_node.h index 54bcf14c1b..5ecb472e64 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -178,8 +178,12 @@ private: RUN_DEBUG_NAVIGATION, RUN_DEPLOY_REMOTE_DEBUG, RUN_RELOAD_SCRIPTS, + RUN_VCS_SETTINGS, + RUN_VCS_SHUT_DOWN, SETTINGS_UPDATE_CONTINUOUSLY, SETTINGS_UPDATE_WHEN_CHANGED, + SETTINGS_UPDATE_ALWAYS, + SETTINGS_UPDATE_CHANGES, SETTINGS_UPDATE_SPINNER_HIDE, SETTINGS_PREFERENCES, SETTINGS_LAYOUT_SAVE, @@ -322,6 +326,7 @@ private: EditorSettingsDialog *settings_config_dialog; RunSettingsDialog *run_settings_dialog; ProjectSettingsEditor *project_settings; + PopupMenu *vcs_actions_menu; EditorFileDialog *file; ExportTemplateManager *export_template_manager; EditorFeatureProfileManager *feature_profile_manager; @@ -477,6 +482,7 @@ private: void _get_scene_metadata(const String &p_file); void _update_title(); void _update_scene_tabs(); + void _version_control_menu_option(int p_idx); void _close_messages(); void _show_messages(); void _vp_resized(); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 23d28261d1..12510e27de 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -78,9 +78,6 @@ void EditorPath::_about_to_show() { } void EditorPath::update_path() { - set_text(""); - set_tooltip(""); - set_icon(NULL); for (int i = 0; i < history->get_path_size(); i++) { diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 4a7a9fb863..5c15ebb1eb 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -295,8 +295,9 @@ void EditorResourcePreview::_thread() { //update modified time f = FileAccess::open(file, FileAccess::WRITE); - f->store_line(itos(modtime)); + f->store_line(itos(thumbnail_size)); f->store_line(itos(has_small_texture)); + f->store_line(itos(modtime)); f->store_line(md5); memdelete(f); } diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index e4e32b2ce0..7b5ec9e772 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -37,7 +37,8 @@ EditorRun::Status EditorRun::get_status() const { return status; } -Error EditorRun::run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints) { + +Error EditorRun::run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints) { List<String> args; @@ -162,6 +163,10 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L args.push_back(bpoints); } + if (p_skip_breakpoints) { + args.push_back("--skip-breakpoints"); + } + if (p_scene != "") { args.push_back(p_scene); } diff --git a/editor/editor_run.h b/editor/editor_run.h index 9127c62030..42724630b5 100644 --- a/editor/editor_run.h +++ b/editor/editor_run.h @@ -51,7 +51,7 @@ private: public: Status get_status() const; - Error run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints); + Error run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints = false); void run_native_notify() { status = STATUS_PLAY; } void stop(); diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp new file mode 100644 index 0000000000..8da1777871 --- /dev/null +++ b/editor/editor_vcs_interface.cpp @@ -0,0 +1,203 @@ +/*************************************************************************/ +/* editor_vcs_interface.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_vcs_interface.h" + +EditorVCSInterface *EditorVCSInterface::singleton = NULL; + +void EditorVCSInterface::_bind_methods() { + + // Proxy end points that act as fallbacks to unavailability of a function in the VCS addon + ClassDB::bind_method(D_METHOD("_initialize", "project_root_path"), &EditorVCSInterface::_initialize); + ClassDB::bind_method(D_METHOD("_get_is_vcs_intialized"), &EditorVCSInterface::_get_is_vcs_intialized); + ClassDB::bind_method(D_METHOD("_get_vcs_name"), &EditorVCSInterface::_get_vcs_name); + ClassDB::bind_method(D_METHOD("_shut_down"), &EditorVCSInterface::_shut_down); + ClassDB::bind_method(D_METHOD("_get_project_name"), &EditorVCSInterface::_get_project_name); + ClassDB::bind_method(D_METHOD("_get_modified_files_data"), &EditorVCSInterface::_get_modified_files_data); + ClassDB::bind_method(D_METHOD("_commit", "msg"), &EditorVCSInterface::_commit); + ClassDB::bind_method(D_METHOD("_get_file_diff", "file_path"), &EditorVCSInterface::_get_file_diff); + ClassDB::bind_method(D_METHOD("_stage_file", "file_path"), &EditorVCSInterface::_stage_file); + ClassDB::bind_method(D_METHOD("_unstage_file", "file_path"), &EditorVCSInterface::_unstage_file); + + ClassDB::bind_method(D_METHOD("is_addon_ready"), &EditorVCSInterface::is_addon_ready); + + // API methods that redirect calls to the proxy end points + ClassDB::bind_method(D_METHOD("initialize", "project_root_path"), &EditorVCSInterface::initialize); + ClassDB::bind_method(D_METHOD("get_is_vcs_intialized"), &EditorVCSInterface::get_is_vcs_intialized); + ClassDB::bind_method(D_METHOD("get_modified_files_data"), &EditorVCSInterface::get_modified_files_data); + ClassDB::bind_method(D_METHOD("stage_file", "file_path"), &EditorVCSInterface::stage_file); + ClassDB::bind_method(D_METHOD("unstage_file", "file_path"), &EditorVCSInterface::unstage_file); + ClassDB::bind_method(D_METHOD("commit", "msg"), &EditorVCSInterface::commit); + ClassDB::bind_method(D_METHOD("get_file_diff", "file_path"), &EditorVCSInterface::get_file_diff); + ClassDB::bind_method(D_METHOD("shut_down"), &EditorVCSInterface::shut_down); + ClassDB::bind_method(D_METHOD("get_project_name"), &EditorVCSInterface::get_project_name); + ClassDB::bind_method(D_METHOD("get_vcs_name"), &EditorVCSInterface::get_vcs_name); +} + +bool EditorVCSInterface::_initialize(String p_project_root_path) { + + WARN_PRINT("Selected VCS addon does not implement an initialization function. This warning will be suppressed.") + return true; +} + +bool EditorVCSInterface::_get_is_vcs_intialized() { + + return false; +} + +Dictionary EditorVCSInterface::_get_modified_files_data() { + + return Dictionary(); +} + +void EditorVCSInterface::_stage_file(String p_file_path) { + + return; +} + +void EditorVCSInterface::_unstage_file(String p_file_path) { + + return; +} + +void EditorVCSInterface::_commit(String p_msg) { + + return; +} + +Array EditorVCSInterface::_get_file_diff(String p_file_path) { + + return Array(); +} + +bool EditorVCSInterface::_shut_down() { + + return false; +} + +String EditorVCSInterface::_get_project_name() { + + return String(); +} + +String EditorVCSInterface::_get_vcs_name() { + + return ""; +} + +bool EditorVCSInterface::initialize(String p_project_root_path) { + + is_initialized = call("_initialize", p_project_root_path); + return is_initialized; +} + +bool EditorVCSInterface::get_is_vcs_intialized() { + + return call("_get_is_vcs_intialized"); +} + +Dictionary EditorVCSInterface::get_modified_files_data() { + + return call("_get_modified_files_data"); +} + +void EditorVCSInterface::stage_file(String p_file_path) { + + if (is_addon_ready()) { + + call("_stage_file", p_file_path); + } + return; +} + +void EditorVCSInterface::unstage_file(String p_file_path) { + + if (is_addon_ready()) { + + call("_unstage_file", p_file_path); + } + return; +} + +bool EditorVCSInterface::is_addon_ready() { + + return is_initialized; +} + +void EditorVCSInterface::commit(String p_msg) { + + if (is_addon_ready()) { + + call("_commit", p_msg); + } + return; +} + +Array EditorVCSInterface::get_file_diff(String p_file_path) { + + if (is_addon_ready()) { + + return call("_get_file_diff", p_file_path); + } + return Array(); +} + +bool EditorVCSInterface::shut_down() { + + return call("_shut_down"); +} + +String EditorVCSInterface::get_project_name() { + + return call("_get_project_name"); +} + +String EditorVCSInterface::get_vcs_name() { + + return call("_get_vcs_name"); +} + +EditorVCSInterface::EditorVCSInterface() { + + is_initialized = false; +} + +EditorVCSInterface::~EditorVCSInterface() { +} + +EditorVCSInterface *EditorVCSInterface::get_singleton() { + + return singleton; +} + +void EditorVCSInterface::set_singleton(EditorVCSInterface *p_singleton) { + + singleton = p_singleton; +} diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h new file mode 100644 index 0000000000..896193ed92 --- /dev/null +++ b/editor/editor_vcs_interface.h @@ -0,0 +1,83 @@ +/*************************************************************************/ +/* editor_vcs_interface.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_VCS_INTERFACE_H +#define EDITOR_VCS_INTERFACE_H + +#include "core/object.h" +#include "core/ustring.h" +#include "scene/gui/panel_container.h" + +class EditorVCSInterface : public Object { + + GDCLASS(EditorVCSInterface, Object) + + bool is_initialized; + +protected: + static EditorVCSInterface *singleton; + + static void _bind_methods(); + + // Implemented by addons as end points for the proxy functions + bool _initialize(String p_project_root_path); + bool _get_is_vcs_intialized(); + Dictionary _get_modified_files_data(); + void _stage_file(String p_file_path); + void _unstage_file(String p_file_path); + void _commit(String p_msg); + Array _get_file_diff(String p_file_path); + bool _shut_down(); + String _get_project_name(); + String _get_vcs_name(); + +public: + static EditorVCSInterface *get_singleton(); + static void set_singleton(EditorVCSInterface *p_singleton); + + bool is_addon_ready(); + + // Proxy functions to the editor for use + bool initialize(String p_project_root_path); + bool get_is_vcs_intialized(); + Dictionary get_modified_files_data(); + void stage_file(String p_file_path); + void unstage_file(String p_file_path); + void commit(String p_msg); + Array get_file_diff(String p_file_path); + bool shut_down(); + String get_project_name(); + String get_vcs_name(); + + EditorVCSInterface(); + virtual ~EditorVCSInterface(); +}; + +#endif // !EDITOR_VCS_INTERFACE_H diff --git a/editor/icons/icon_debug_skip_breakpoints_off.svg b/editor/icons/icon_debug_skip_breakpoints_off.svg new file mode 100644 index 0000000000..2a0b949aa9 --- /dev/null +++ b/editor/icons/icon_debug_skip_breakpoints_off.svg @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="17" + height="17" + version="1.1" + viewBox="0 0 17 17" + id="svg3801" + sodipodi:docname="icon_debug_skip_breakpoints_off.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + <metadata + id="metadata3807"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs3805" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1887" + inkscape:window-height="2103" + id="namedview3803" + showgrid="false" + inkscape:measure-start="15.5563,28.7373" + inkscape:measure-end="0,0" + inkscape:zoom="32" + inkscape:cx="8.5156226" + inkscape:cy="-9.0970543" + inkscape:window-x="1953" + inkscape:window-y="27" + inkscape:window-maximized="0" + inkscape:current-layer="svg3801" /> + <path + id="path3835" + sodipodi:type="arc" + sodipodi:cx="3.2790968" + sodipodi:cy="3.006855" + sodipodi:rx="1.6192284" + sodipodi:ry="1.3289529" + sodipodi:start="0" + sodipodi:end="0.0073006075" + sodipodi:open="true" + d="m 4.8983252,3.006855 a 1.6192284,1.3289529 0 0 1 -4.31e-5,0.0097" + style="fill:#000000;stroke-width:0.62631863" /> + <path + style="fill:#000000;stroke-width:0.62631863" + id="path3837" + sodipodi:type="arc" + sodipodi:cx="6.233613" + sodipodi:cy="5.0553513" + sodipodi:rx="2.563139" + sodipodi:ry="3.6270869" + sodipodi:start="0" + sodipodi:end="0.0073006075" + sodipodi:open="true" + d="m 8.796752,5.0553513 a 2.563139,3.6270869 0 0 1 -6.83e-5,0.02648" /> + <path + style="fill:#ff8585;fill-opacity:0.99607843;stroke-width:1.01912296" + id="path3839" + sodipodi:type="arc" + sodipodi:cx="8.4689026" + sodipodi:cy="8.479969" + sodipodi:rx="6.1594577" + sodipodi:ry="6.0545759" + sodipodi:start="5.5685493" + sodipodi:end="5.2409356" + d="M 13.121337,4.512148 A 6.1594577,6.0545759 0 0 1 12.87255,12.713238 6.1594577,6.0545759 0 0 1 4.5370096,13.140453 6.1594577,6.0545759 0 0 1 3.4219038,5.0092664 6.1594577,6.0545759 0 0 1 11.574987,3.2515951" + sodipodi:open="true" /> +</svg> diff --git a/editor/icons/icon_debug_skip_breakpoints_on.svg b/editor/icons/icon_debug_skip_breakpoints_on.svg new file mode 100644 index 0000000000..186778a1b4 --- /dev/null +++ b/editor/icons/icon_debug_skip_breakpoints_on.svg @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="17" + height="17" + version="1.1" + viewBox="0 0 17 17" + id="svg3801" + sodipodi:docname="icon_debug_skip_breakpoints_on.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + <metadata + id="metadata3807"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs3805" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1887" + inkscape:window-height="2105" + id="namedview3803" + showgrid="false" + inkscape:measure-start="15.5563,28.7373" + inkscape:measure-end="0,0" + inkscape:zoom="40.96" + inkscape:cx="12.825686" + inkscape:cy="-5.1961973" + inkscape:window-x="1953" + inkscape:window-y="27" + inkscape:window-maximized="0" + inkscape:current-layer="layer1" /> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="bg" /> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="fg"> + <path + id="path3835" + sodipodi:type="arc" + sodipodi:cx="3.2790968" + sodipodi:cy="3.006855" + sodipodi:rx="1.6192284" + sodipodi:ry="1.3289529" + sodipodi:start="0" + sodipodi:end="0.0073006075" + sodipodi:open="true" + d="m 4.8983252,3.006855 a 1.6192284,1.3289529 0 0 1 -4.31e-5,0.0097" + style="fill:#000000;stroke-width:0.62631863" /> + <path + style="fill:#000000;stroke-width:0.62631863" + id="path3837" + sodipodi:type="arc" + sodipodi:cx="6.233613" + sodipodi:cy="5.0553513" + sodipodi:rx="2.563139" + sodipodi:ry="3.6270869" + sodipodi:start="0" + sodipodi:end="0.0073006075" + sodipodi:open="true" + d="m 8.796752,5.0553513 a 2.563139,3.6270869 0 0 1 -6.83e-5,0.02648" /> + <path + style="fill:#ff8585;fill-opacity:0.99607843;stroke-width:1.01912296" + id="path3839" + sodipodi:type="arc" + sodipodi:cx="8.4689026" + sodipodi:cy="8.479969" + sodipodi:rx="6.1594577" + sodipodi:ry="6.0545759" + sodipodi:start="5.5685493" + sodipodi:end="5.2409356" + d="M 13.121337,4.512148 A 6.1594577,6.0545759 0 0 1 12.87255,12.713238 6.1594577,6.0545759 0 0 1 4.5370096,13.140453 6.1594577,6.0545759 0 0 1 3.4219038,5.0092664 6.1594577,6.0545759 0 0 1 11.574987,3.2515951" + sodipodi:open="true" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke-width:1.1873318" + id="rect5375" + width="18.575495" + height="2.5187109" + x="-9.2906752" + y="10.816157" + transform="matrix(0.70605846,-0.70815355,0.70605846,0.70815355,0,0)" /> + </g> +</svg> diff --git a/editor/import/resource_importer_csv.cpp b/editor/import/resource_importer_csv.cpp new file mode 100644 index 0000000000..64b5309cab --- /dev/null +++ b/editor/import/resource_importer_csv.cpp @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* resource_importer_csv.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "resource_importer_csv.h" + +#include "core/io/resource_saver.h" +#include "core/os/file_access.h" + +String ResourceImporterCSV::get_importer_name() const { + + return "csv"; +} + +String ResourceImporterCSV::get_visible_name() const { + + return "CSV"; +} +void ResourceImporterCSV::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("csv"); +} + +String ResourceImporterCSV::get_save_extension() const { + return ""; //does not save a single resource +} + +String ResourceImporterCSV::get_resource_type() const { + + return "TextFile"; +} + +bool ResourceImporterCSV::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + + return true; +} + +int ResourceImporterCSV::get_preset_count() const { + return 0; +} +String ResourceImporterCSV::get_preset_name(int p_idx) const { + + return ""; +} + +void ResourceImporterCSV::get_import_options(List<ImportOption> *r_options, int p_preset) const { +} + +Error ResourceImporterCSV::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + return OK; +} + +ResourceImporterCSV::ResourceImporterCSV() { +} diff --git a/editor/import/resource_importer_csv.h b/editor/import/resource_importer_csv.h new file mode 100644 index 0000000000..7d06bdb188 --- /dev/null +++ b/editor/import/resource_importer_csv.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* resource_importer_csv.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RESOURCEIMPORTERCSV_H +#define RESOURCEIMPORTERCSV_H + +#include "core/io/resource_importer.h" + +class ResourceImporterCSV : public ResourceImporter { + GDCLASS(ResourceImporterCSV, ResourceImporter); + +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; + virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; + + virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL); + + ResourceImporterCSV(); +}; + +#endif // RESOURCEIMPORTERCSV_H diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 8a0812973f..8ba7d9fba7 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -408,6 +408,10 @@ void InspectorDock::update(Object *p_object) { warning->hide(); search->set_editable(false); + editor_path->set_text(""); + editor_path->set_tooltip(""); + editor_path->set_icon(NULL); + return; } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 60b5f017d2..3d161dc5b9 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -578,7 +578,6 @@ void EditorAssetLibrary::_notification(int p_what) { case NOTIFICATION_READY: { error_tr->set_texture(get_icon("Error", "EditorIcons")); - reverse->set_icon(get_icon("Sort", "EditorIcons")); filter->set_right_icon(get_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); @@ -612,7 +611,6 @@ void EditorAssetLibrary::_notification(int p_what) { library_scroll_bg->add_style_override("panel", get_stylebox("bg", "Tree")); downloads_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); error_tr->set_texture(get_icon("Error", "EditorIcons")); - reverse->set_icon(get_icon("Sort", "EditorIcons")); filter->set_right_icon(get_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); } break; @@ -645,23 +643,27 @@ void EditorAssetLibrary::_install_asset() { } const char *EditorAssetLibrary::sort_key[SORT_MAX] = { - "downloads", + "updated", + "updated", "name", + "name", + "cost", "cost", - "updated" }; const char *EditorAssetLibrary::sort_text[SORT_MAX] = { - "Downloads", - "Name", - "License", // "cost" stores the SPDX license name in the Godot Asset Library. - "Updated" + "Recently Updated", + "Least Recently Updated", + "Name (A-Z)", + "Name (Z-A)", + "License (A-Z)", // "cost" stores the SPDX license name in the Godot Asset Library. + "License (Z-A)", // "cost" stores the SPDX license name in the Godot Asset Library. }; const char *EditorAssetLibrary::support_key[SUPPORT_MAX] = { "official", "community", - "testing" + "testing", }; void EditorAssetLibrary::_select_author(int p_id) { @@ -928,8 +930,8 @@ void EditorAssetLibrary::_search(int p_page) { args += "&category=" + itos(categories->get_item_metadata(categories->get_selected())); } - if (reverse->is_pressed()) { - + // Sorting options with an odd index are always the reverse of the previous one + if (sort->get_selected() % 2 == 1) { args += "&reverse=true"; } @@ -1381,12 +1383,6 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { sort->set_h_size_flags(SIZE_EXPAND_FILL); sort->connect("item_selected", this, "_rerun_search"); - reverse = memnew(ToolButton); - reverse->set_toggle_mode(true); - reverse->connect("toggled", this, "_rerun_search"); - reverse->set_tooltip(TTR("Reverse sorting.")); - search_hb2->add_child(reverse); - search_hb2->add_child(memnew(VSeparator)); search_hb2->add_child(memnew(Label(TTR("Category:") + " "))); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 6a3158889e..7e934ac6cb 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -190,7 +190,6 @@ class EditorAssetLibrary : public PanelContainer { OptionButton *categories; OptionButton *repository; OptionButton *sort; - ToolButton *reverse; Button *search; HBoxContainer *error_hb; TextureRect *error_tr; @@ -216,10 +215,12 @@ class EditorAssetLibrary : public PanelContainer { }; enum SortOrder { - SORT_DOWNLOADS, + SORT_UPDATED, + SORT_UPDATED_REVERSE, SORT_NAME, + SORT_NAME_REVERSE, SORT_COST, - SORT_UPDATED, + SORT_COST_REVERSE, SORT_MAX }; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 413843d536..8b6bab374c 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -538,6 +538,10 @@ void ScriptEditor::_open_recent_script(int p_idx) { // if it's a path then it's most likely a deleted file not help } else if (path.find("::") != -1) { // built-in script + String scene_path = path.get_slice("::", 0); + if (!EditorNode::get_singleton()->is_scene_open(scene_path)) { + EditorNode::get_singleton()->load_scene(scene_path); + } Ref<Script> script = ResourceLoader::load(path); if (script.is_valid()) { edit(script, true); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp new file mode 100644 index 0000000000..c059977487 --- /dev/null +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -0,0 +1,595 @@ +/*************************************************************************/ +/* version_control_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "version_control_editor_plugin.h" +#include "core/script_language.h" +#include "editor/editor_file_system.h" +#include "editor/editor_node.h" + +VersionControlEditorPlugin *VersionControlEditorPlugin::singleton = NULL; + +void VersionControlEditorPlugin::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_selected_a_vcs"), &VersionControlEditorPlugin::_selected_a_vcs); + ClassDB::bind_method(D_METHOD("_initialize_vcs"), &VersionControlEditorPlugin::_initialize_vcs); + ClassDB::bind_method(D_METHOD("_send_commit_msg"), &VersionControlEditorPlugin::_send_commit_msg); + ClassDB::bind_method(D_METHOD("_refresh_stage_area"), &VersionControlEditorPlugin::_refresh_stage_area); + ClassDB::bind_method(D_METHOD("_stage_all"), &VersionControlEditorPlugin::_stage_all); + ClassDB::bind_method(D_METHOD("_stage_selected"), &VersionControlEditorPlugin::_stage_selected); + ClassDB::bind_method(D_METHOD("_view_file_diff"), &VersionControlEditorPlugin::_view_file_diff); + ClassDB::bind_method(D_METHOD("_refresh_file_diff"), &VersionControlEditorPlugin::_refresh_file_diff); + ClassDB::bind_method(D_METHOD("popup_vcs_set_up_dialog"), &VersionControlEditorPlugin::popup_vcs_set_up_dialog); + + // Used to track the status of files in the staging area + BIND_ENUM_CONSTANT(CHANGE_TYPE_NEW); + BIND_ENUM_CONSTANT(CHANGE_TYPE_MODIFIED); + BIND_ENUM_CONSTANT(CHANGE_TYPE_RENAMED); + BIND_ENUM_CONSTANT(CHANGE_TYPE_DELETED); + BIND_ENUM_CONSTANT(CHANGE_TYPE_TYPECHANGE); +} + +void VersionControlEditorPlugin::_selected_a_vcs(int p_id) { + + List<StringName> available_addons = get_available_vcs_names(); + const StringName selected_vcs = set_up_choice->get_item_text(p_id); + + if (available_addons.find(selected_vcs) != NULL) { + + set_up_init_button->set_disabled(false); + } else { + + set_up_init_button->set_disabled(true); + } +} + +void VersionControlEditorPlugin::_populate_available_vcs_names() { + + static bool called = false; + + if (!called) { + + set_up_choice->add_item("Select an available VCS"); + + fetch_available_vcs_addon_names(); + List<StringName> available_addons = get_available_vcs_names(); + for (int i = 0; i < available_addons.size(); i++) { + + set_up_choice->add_item(available_addons[i]); + } + + called = true; + } +} + +VersionControlEditorPlugin *VersionControlEditorPlugin::get_singleton() { + + return singleton ? singleton : memnew(VersionControlEditorPlugin); +} + +void VersionControlEditorPlugin::popup_vcs_set_up_dialog(const Control *p_gui_base) { + + Size2 popup_size = Size2(400, 100); + Size2 window_size = p_gui_base->get_viewport_rect().size; + popup_size.x = MIN(window_size.x * 0.5, popup_size.x); + popup_size.y = MIN(window_size.y * 0.5, popup_size.y); + + if (get_is_vcs_intialized()) { + + set_up_init_button->set_disabled(true); + } + + _populate_available_vcs_names(); + + set_up_dialog->popup_centered_clamped(popup_size * EDSCALE); +} + +void VersionControlEditorPlugin::_initialize_vcs() { + + register_editor(); + + if (EditorVCSInterface::get_singleton()) { + + ERR_EXPLAIN(EditorVCSInterface::get_singleton()->get_vcs_name() + " is already active"); + return; + } + + int id = set_up_choice->get_selected_id(); + String selected_addon = set_up_choice->get_item_text(id); + + String path = ScriptServer::get_global_class_path(selected_addon); + Ref<Script> script = ResourceLoader::load(path); + if (!script.is_valid()) { + + ERR_EXPLAIN("VCS Addon path is invalid"); + } + + EditorVCSInterface *vcs_interface = memnew(EditorVCSInterface); + ScriptInstance *addon_script_instance = script->instance_create(vcs_interface); + if (!addon_script_instance) { + + ERR_FAIL_NULL(addon_script_instance); + return; + } + + // The addon is attached as a script to the VCS interface as a proxy end-point + vcs_interface->set_script_and_instance(script.get_ref_ptr(), addon_script_instance); + + EditorVCSInterface::set_singleton(vcs_interface); + EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_refresh_stage_area"); + + String res_dir = OS::get_singleton()->get_resource_dir(); + if (!EditorVCSInterface::get_singleton()->initialize(res_dir)) { + + ERR_EXPLAIN("VCS was not initialized"); + } + + _refresh_stage_area(); +} + +void VersionControlEditorPlugin::_send_commit_msg() { + + String msg = commit_message->get_text(); + if (msg == "") { + + commit_status->set_text(TTR("No commit message was provided")); + return; + } + + if (EditorVCSInterface::get_singleton()) { + + if (staged_files_count == 0) { + + commit_status->set_text(TTR("No files added to stage")); + return; + } + + EditorVCSInterface::get_singleton()->commit(msg); + + commit_message->set_text(""); + version_control_dock_button->set_pressed(false); + } else { + + WARN_PRINT("No VCS addon is initialized. Select a Version Control Addon from Project menu"); + } + + _update_commit_status(); + _refresh_stage_area(); + _clear_file_diff(); +} + +void VersionControlEditorPlugin::_refresh_stage_area() { + + if (EditorVCSInterface::get_singleton()) { + + staged_files_count = 0; + clear_stage_area(); + + Dictionary modified_file_paths = EditorVCSInterface::get_singleton()->get_modified_files_data(); + String file_path; + for (int i = 0; i < modified_file_paths.size(); i++) { + + file_path = modified_file_paths.get_key_at_index(i); + TreeItem *found = stage_files->search_item_text(file_path, 0, true); + if (!found) { + + ChangeType change_index = (ChangeType)(int)modified_file_paths.get_value_at_index(i); + String change_text = file_path + " (" + change_type_to_strings[change_index] + ")"; + Color &change_color = change_type_to_color[change_index]; + TreeItem *new_item = stage_files->create_item(stage_files->get_root()); + new_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + new_item->set_text(0, change_text); + new_item->set_metadata(0, file_path); + new_item->set_custom_color(0, change_color); + new_item->set_checked(0, true); + new_item->set_editable(0, true); + } else { + + if (found->get_metadata(0) == diff_file_name->get_text()) { + + _refresh_file_diff(); + } + } + commit_status->set_text("New changes detected"); + } + } else { + + WARN_PRINT("No VCS addon is initialized. Select a Version Control Addon from Project menu.") + } +} + +void VersionControlEditorPlugin::_stage_selected() { + + if (!EditorVCSInterface::get_singleton()) { + + WARN_PRINT("No VCS addon is initialized. Select a Version Control Addon from Project menu"); + return; + } + + staged_files_count = 0; + TreeItem *root = stage_files->get_root(); + if (root) { + + TreeItem *file_entry = root->get_children(); + while (file_entry) { + + if (file_entry->is_checked(0)) { + + EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + staged_files_count++; + } else { + + EditorVCSInterface::get_singleton()->unstage_file(file_entry->get_metadata(0)); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + } + + file_entry = file_entry->get_next(); + } + } + + _update_stage_status(); +} + +void VersionControlEditorPlugin::_stage_all() { + + if (!EditorVCSInterface::get_singleton()) { + + WARN_PRINT("No VCS addon is initialized. Select a Version Control Addon from Project menu"); + return; + } + + staged_files_count = 0; + TreeItem *root = stage_files->get_root(); + if (root) { + + TreeItem *file_entry = root->get_children(); + while (file_entry) { + + EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + file_entry->set_checked(0, true); + staged_files_count++; + + file_entry = file_entry->get_next(); + } + } + + _update_stage_status(); +} + +void VersionControlEditorPlugin::_view_file_diff() { + + version_control_dock_button->set_pressed(true); + + String file_path = stage_files->get_selected()->get_metadata(0); + + _display_file_diff(file_path); +} + +void VersionControlEditorPlugin::_display_file_diff(String p_file_path) { + + Array diff_content = EditorVCSInterface::get_singleton()->get_file_diff(p_file_path); + + diff_file_name->set_text(p_file_path); + + diff->clear(); + diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); + for (int i = 0; i < diff_content.size(); i++) { + + Dictionary line_result = diff_content[i]; + + if (line_result["status"] == "+") { + + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + } else if (line_result["status"] == "-") { + + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + } else { + + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Label")); + } + + diff->add_text((String)line_result["content"]); + + diff->pop(); + } + diff->pop(); +} + +void VersionControlEditorPlugin::_refresh_file_diff() { + + String open_file = diff_file_name->get_text(); + if (open_file != "") { + + _display_file_diff(diff_file_name->get_text()); + } +} + +void VersionControlEditorPlugin::_clear_file_diff() { + + diff->clear(); + diff_file_name->set_text(""); + version_control_dock_button->set_pressed(false); +} + +void VersionControlEditorPlugin::_update_stage_status() { + + String status; + if (staged_files_count == 1) { + + status = "Stage contains 1 file"; + } else { + + status = "Stage contains " + String::num_int64(staged_files_count) + " files"; + } + commit_status->set_text(status); +} + +void VersionControlEditorPlugin::_update_commit_status() { + + String status; + if (staged_files_count == 1) { + + status = "Committed 1 file"; + } else { + + status = "Committed " + String::num_int64(staged_files_count) + " files "; + } + commit_status->set_text(status); + staged_files_count = 0; +} + +void VersionControlEditorPlugin::register_editor() { + + if (!EditorVCSInterface::get_singleton()) { + + EditorNode::get_singleton()->add_control_to_dock(EditorNode::DOCK_SLOT_RIGHT_UL, version_commit_dock); + TabContainer *dock_vbc = (TabContainer *)version_commit_dock->get_parent_control(); + dock_vbc->set_tab_title(version_commit_dock->get_index(), TTR("Commit")); + + ToolButton *vc = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); + set_version_control_tool_button(vc); + } +} + +void VersionControlEditorPlugin::fetch_available_vcs_addon_names() { + + ScriptServer::get_global_class_list(&available_addons); +} + +void VersionControlEditorPlugin::clear_stage_area() { + + stage_files->get_root()->clear_children(); +} + +void VersionControlEditorPlugin::shut_down() { + + if (EditorVCSInterface::get_singleton()) { + + EditorFileSystem::get_singleton()->disconnect("filesystem_changed", this, "_refresh_stage_area"); + EditorVCSInterface::get_singleton()->shut_down(); + memdelete(EditorVCSInterface::get_singleton()); + EditorVCSInterface::set_singleton(NULL); + + EditorNode::get_singleton()->remove_control_from_dock(version_commit_dock); + EditorNode::get_singleton()->remove_bottom_panel_item(version_control_dock); + } +} + +bool VersionControlEditorPlugin::get_is_vcs_intialized() const { + + return EditorVCSInterface::get_singleton() ? EditorVCSInterface::get_singleton()->get_is_vcs_intialized() : false; +} + +const String VersionControlEditorPlugin::get_vcs_name() const { + + return EditorVCSInterface::get_singleton() ? EditorVCSInterface::get_singleton()->get_vcs_name() : ""; +} + +VersionControlEditorPlugin::VersionControlEditorPlugin() { + + singleton = this; + staged_files_count = 0; + + version_control_actions = memnew(PopupMenu); + version_control_actions->set_v_size_flags(BoxContainer::SIZE_SHRINK_CENTER); + + set_up_dialog = memnew(AcceptDialog); + set_up_dialog->set_title(TTR("Set Up Version Control")); + set_up_dialog->set_custom_minimum_size(Size2(400, 100)); + version_control_actions->add_child(set_up_dialog); + + set_up_ok_button = set_up_dialog->get_ok(); + set_up_ok_button->set_disabled(false); + set_up_ok_button->set_text(TTR("Close")); + + set_up_vbc = memnew(VBoxContainer); + set_up_vbc->set_alignment(VBoxContainer::ALIGN_CENTER); + set_up_dialog->add_child(set_up_vbc); + + set_up_hbc = memnew(HBoxContainer); + set_up_hbc->set_h_size_flags(HBoxContainer::SIZE_EXPAND_FILL); + set_up_vbc->add_child(set_up_hbc); + + set_up_vcs_status = memnew(RichTextLabel); + set_up_vcs_status->set_text(TTR("VCS Addon is not initialized")); + set_up_vbc->add_child(set_up_vcs_status); + + set_up_vcs_label = memnew(Label); + set_up_vcs_label->set_text(TTR("Version Control System")); + set_up_hbc->add_child(set_up_vcs_label); + + set_up_choice = memnew(OptionButton); + set_up_choice->set_h_size_flags(HBoxContainer::SIZE_EXPAND_FILL); + set_up_choice->connect("item_selected", this, "_selected_a_vcs"); + set_up_hbc->add_child(set_up_choice); + + set_up_init_settings = NULL; + + set_up_init_button = memnew(Button); + set_up_init_button->set_disabled(true); + set_up_init_button->set_text(TTR("Initialize")); + set_up_init_button->connect("pressed", this, "_initialize_vcs"); + set_up_vbc->add_child(set_up_init_button); + + version_control_actions->set_v_size_flags(PopupMenu::SIZE_EXPAND_FILL); + version_control_actions->set_h_size_flags(PopupMenu::SIZE_EXPAND_FILL); + + version_commit_dock = memnew(VBoxContainer); + version_commit_dock->set_visible(false); + + commit_box_vbc = memnew(VBoxContainer); + commit_box_vbc->set_alignment(VBoxContainer::ALIGN_BEGIN); + commit_box_vbc->set_h_size_flags(VBoxContainer::SIZE_EXPAND_FILL); + commit_box_vbc->set_v_size_flags(VBoxContainer::SIZE_EXPAND_FILL); + version_commit_dock->add_child(commit_box_vbc); + + stage_tools = memnew(HSplitContainer); + stage_tools->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED); + commit_box_vbc->add_child(stage_tools); + + staging_area_label = memnew(Label); + staging_area_label->set_h_size_flags(Label::SIZE_EXPAND_FILL); + staging_area_label->set_text(TTR("Staging area")); + stage_tools->add_child(staging_area_label); + + refresh_button = memnew(Button); + refresh_button->set_tooltip(TTR("Detect new changes")); + refresh_button->set_text(TTR("Refresh")); + refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Reload", "EditorIcons")); + refresh_button->connect("pressed", this, "_refresh_stage_area"); + stage_tools->add_child(refresh_button); + + stage_files = memnew(Tree); + stage_files->set_h_size_flags(Tree::SIZE_EXPAND_FILL); + stage_files->set_v_size_flags(Tree::SIZE_EXPAND_FILL); + stage_files->set_columns(1); + stage_files->set_column_title(0, TTR("Changes")); + stage_files->set_column_titles_visible(true); + stage_files->set_allow_reselect(true); + stage_files->set_allow_rmb_select(true); + stage_files->set_select_mode(Tree::SelectMode::SELECT_MULTI); + stage_files->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); + stage_files->connect("cell_selected", this, "_view_file_diff"); + stage_files->create_item(); + stage_files->set_hide_root(true); + commit_box_vbc->add_child(stage_files); + + change_type_to_strings[CHANGE_TYPE_NEW] = TTR("New"); + change_type_to_strings[CHANGE_TYPE_MODIFIED] = TTR("Modified"); + change_type_to_strings[CHANGE_TYPE_RENAMED] = TTR("Renamed"); + change_type_to_strings[CHANGE_TYPE_DELETED] = TTR("Deleted"); + change_type_to_strings[CHANGE_TYPE_TYPECHANGE] = TTR("Typechange"); + + change_type_to_color[CHANGE_TYPE_NEW] = EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor"); + change_type_to_color[CHANGE_TYPE_MODIFIED] = EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"); + change_type_to_color[CHANGE_TYPE_RENAMED] = EditorNode::get_singleton()->get_gui_base()->get_color("disabled_font_color", "Editor"); + change_type_to_color[CHANGE_TYPE_DELETED] = EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"); + change_type_to_color[CHANGE_TYPE_TYPECHANGE] = EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Editor"); + + stage_buttons = memnew(HSplitContainer); + stage_buttons->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED); + commit_box_vbc->add_child(stage_buttons); + + stage_selected_button = memnew(Button); + stage_selected_button->set_h_size_flags(Button::SIZE_EXPAND_FILL); + stage_selected_button->set_text(TTR("Stage Selected")); + stage_selected_button->connect("pressed", this, "_stage_selected"); + stage_buttons->add_child(stage_selected_button); + + stage_all_button = memnew(Button); + stage_all_button->set_text(TTR("Stage All")); + stage_all_button->connect("pressed", this, "_stage_all"); + stage_buttons->add_child(stage_all_button); + + commit_box_vbc->add_child(memnew(HSeparator)); + + commit_message = memnew(TextEdit); + commit_message->set_h_size_flags(Control::SIZE_EXPAND_FILL); + commit_message->set_h_grow_direction(Control::GrowDirection::GROW_DIRECTION_BEGIN); + commit_message->set_v_grow_direction(Control::GrowDirection::GROW_DIRECTION_END); + commit_message->set_custom_minimum_size(Size2(200, 100)); + commit_message->set_wrap_enabled(true); + commit_message->set_text(TTR("Add a commit message")); + commit_box_vbc->add_child(commit_message); + + commit_button = memnew(Button); + commit_button->set_text(TTR("Commit Changes")); + commit_button->connect("pressed", this, "_send_commit_msg"); + commit_box_vbc->add_child(commit_button); + + commit_status = memnew(Label); + commit_status->set_align(Label::ALIGN_CENTER); + commit_box_vbc->add_child(commit_status); + + version_control_dock = memnew(PanelContainer); + version_control_dock->set_v_size_flags(Control::SIZE_EXPAND_FILL); + version_control_dock->hide(); + + diff_vbc = memnew(VBoxContainer); + diff_vbc->set_h_size_flags(HBoxContainer::SIZE_FILL); + diff_vbc->set_v_size_flags(HBoxContainer::SIZE_FILL); + version_control_dock->add_child(diff_vbc); + + diff_hbc = memnew(HBoxContainer); + diff_hbc->set_h_size_flags(HBoxContainer::SIZE_FILL); + diff_vbc->add_child(diff_hbc); + + diff_heading = memnew(Label); + diff_heading->set_text(TTR("Status")); + diff_heading->set_tooltip(TTR("View file diffs before commiting them to the latest version")); + diff_hbc->add_child(diff_heading); + + diff_file_name = memnew(Label); + diff_file_name->set_text(TTR("No file diff is active")); + diff_file_name->set_h_size_flags(Label::SIZE_EXPAND_FILL); + diff_file_name->set_align(Label::ALIGN_RIGHT); + diff_hbc->add_child(diff_file_name); + + diff_refresh_button = memnew(Button); + diff_refresh_button->set_tooltip(TTR("Detect changes in file diff")); + diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Reload", "EditorIcons")); + diff_refresh_button->connect("pressed", this, "_refresh_file_diff"); + diff_hbc->add_child(diff_refresh_button); + + diff = memnew(RichTextLabel); + diff->set_h_size_flags(TextEdit::SIZE_EXPAND_FILL); + diff->set_v_size_flags(TextEdit::SIZE_EXPAND_FILL); + diff->set_selection_enabled(true); + diff_vbc->add_child(diff); +} + +VersionControlEditorPlugin::~VersionControlEditorPlugin() { + + shut_down(); + memdelete(version_control_dock); + memdelete(version_commit_dock); + memdelete(version_control_actions); +} diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h new file mode 100644 index 0000000000..450ebccce1 --- /dev/null +++ b/editor/plugins/version_control_editor_plugin.h @@ -0,0 +1,146 @@ +/*************************************************************************/ +/* version_control_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VERSION_CONTROL_EDITOR_PLUGIN_H +#define VERSION_CONTROL_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "editor/editor_vcs_interface.h" +#include "scene/gui/container.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/text_edit.h" +#include "scene/gui/tree.h" + +class VersionControlEditorPlugin : public EditorPlugin { + + GDCLASS(VersionControlEditorPlugin, EditorPlugin) + +public: + enum ChangeType { + + CHANGE_TYPE_NEW = 0, + CHANGE_TYPE_MODIFIED = 1, + CHANGE_TYPE_RENAMED = 2, + CHANGE_TYPE_DELETED = 3, + CHANGE_TYPE_TYPECHANGE = 4 + }; + +private: + static VersionControlEditorPlugin *singleton; + + int staged_files_count; + List<StringName> available_addons; + + PopupMenu *version_control_actions; + AcceptDialog *set_up_dialog; + VBoxContainer *set_up_vbc; + HBoxContainer *set_up_hbc; + Label *set_up_vcs_label; + OptionButton *set_up_choice; + PanelContainer *set_up_init_settings; + Button *set_up_init_button; + RichTextLabel *set_up_vcs_status; + Button *set_up_ok_button; + + HashMap<ChangeType, String> change_type_to_strings; + HashMap<ChangeType, Color> change_type_to_color; + + VBoxContainer *version_commit_dock; + VBoxContainer *commit_box_vbc; + HSplitContainer *stage_tools; + Tree *stage_files; + TreeItem *new_files; + TreeItem *modified_files; + TreeItem *renamed_files; + TreeItem *deleted_files; + TreeItem *typechange_files; + Label *staging_area_label; + HSplitContainer *stage_buttons; + Button *stage_all_button; + Button *stage_selected_button; + Button *refresh_button; + TextEdit *commit_message; + Button *commit_button; + Label *commit_status; + + PanelContainer *version_control_dock; + ToolButton *version_control_dock_button; + VBoxContainer *diff_vbc; + HBoxContainer *diff_hbc; + Button *diff_refresh_button; + Label *diff_file_name; + Label *diff_heading; + RichTextLabel *diff; + + void _populate_available_vcs_names(); + void _selected_a_vcs(int p_id); + void _initialize_vcs(); + void _send_commit_msg(); + void _refresh_stage_area(); + void _stage_selected(); + void _stage_all(); + void _view_file_diff(); + void _display_file_diff(String p_file_path); + void _refresh_file_diff(); + void _clear_file_diff(); + void _update_stage_status(); + void _update_commit_status(); + + friend class EditorVCSInterface; + +protected: + static void _bind_methods(); + +public: + static VersionControlEditorPlugin *get_singleton(); + + void popup_vcs_set_up_dialog(const Control *p_gui_base); + void set_version_control_tool_button(ToolButton *p_button) { version_control_dock_button = p_button; } + + PopupMenu *get_version_control_actions_panel() const { return version_control_actions; } + VBoxContainer *get_version_commit_dock() const { return version_commit_dock; } + PanelContainer *get_version_control_dock() const { return version_control_dock; } + + List<StringName> get_available_vcs_names() const { return available_addons; } + bool get_is_vcs_intialized() const; + const String get_vcs_name() const; + + void register_editor(); + void fetch_available_vcs_addon_names(); + void clear_stage_area(); + void shut_down(); + + VersionControlEditorPlugin(); + ~VersionControlEditorPlugin(); +}; + +VARIANT_ENUM_CAST(VersionControlEditorPlugin::ChangeType); + +#endif // !VERSION_CONTROL_EDITOR_PLUGIN_H diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 6b338ca02b..82baa99da2 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2367,6 +2367,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LessThanEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than or Equal (<=)")), VisualShaderNodeCompare::FUNC_LESS_THAN_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("NotEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Not Equal (!=)")), VisualShaderNodeCompare::FUNC_NOT_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("Switch", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated vector if the provided boolean value is true or false."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SwitchS", "Conditional", "Functions", "VisualShaderNodeScalarSwitch", TTR("Returns an associated scalar if the provided boolean value is true or false."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Compare", "Conditional", "Common", "VisualShaderNodeCompare", TTR("Returns the boolean result of the comparison between two parameters."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("Is", "Conditional", "Common", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between INF (or NaN) and a scalar parameter."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN)); @@ -2382,6 +2383,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_camera"), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_projection"), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Normal", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "normal"), "normal", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("OutputIsSRGB", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "output_is_srgb"), "output_is_srgb", VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "viewport_size"), "viewport_size", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL)); @@ -2412,6 +2414,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), "front_facing", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "side"), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index f0114b393d..16f1575757 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -759,7 +759,16 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { _delete_confirm(); } else { - delete_dialog->set_text(TTR("Delete Node(s)?")); + if (remove_list.size() > 1) { + delete_dialog->set_text(vformat(TTR("Delete %d nodes?"), remove_list.size())); + } else { + delete_dialog->set_text(vformat(TTR("Delete node \"%s\"?"), remove_list[0]->get_name())); + } + + // Resize the dialog to its minimum size. + // This prevents the dialog from being too wide after displaying + // a deletion confirmation for a node with a long name. + delete_dialog->set_size(Size2()); delete_dialog->popup_centered_minsize(); } diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index fc5aecdbe9..6ee09012a5 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -33,6 +33,7 @@ #include "core/io/marshalls.h" #include "core/project_settings.h" #include "core/ustring.h" +#include "editor_network_profiler.h" #include "editor_node.h" #include "editor_profiler.h" #include "editor_settings.h" @@ -201,6 +202,21 @@ void ScriptEditorDebugger::debug_copy() { OS::get_singleton()->set_clipboard(msg); } +void ScriptEditorDebugger::debug_skip_breakpoints() { + skip_breakpoints_value = !skip_breakpoints_value; + if (skip_breakpoints_value) + skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOn", "EditorIcons")); + else + skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOff", "EditorIcons")); + + if (connection.is_valid()) { + Array msg; + msg.push_back("set_skip_breakpoints"); + msg.push_back(skip_breakpoints_value); + ppeer->put_var(msg); + } +} + void ScriptEditorDebugger::debug_next() { ERR_FAIL_COND(!breaked); @@ -977,7 +993,20 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da profiler->add_frame_metric(metric, false); else profiler->add_frame_metric(metric, true); - + } else if (p_msg == "network_profile") { + int frame_size = 6; + for (int i = 0; i < p_data.size(); i += frame_size) { + MultiplayerAPI::ProfilingInfo pi; + pi.node = p_data[i + 0]; + pi.node_path = p_data[i + 1]; + pi.incoming_rpc = p_data[i + 2]; + pi.incoming_rset = p_data[i + 3]; + pi.outgoing_rpc = p_data[i + 4]; + pi.outgoing_rset = p_data[i + 5]; + network_profiler->add_node_frame_data(pi); + } + } else if (p_msg == "network_bandwidth") { + network_profiler->set_bandwidth(p_data[0], p_data[1]); } else if (p_msg == "kill_me") { editor->call_deferred("stop_child_process"); @@ -1083,7 +1112,7 @@ void ScriptEditorDebugger::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { inspector->edit(variables); - + skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOff", "EditorIcons")); copy->set_icon(get_icon("ActionCopy", "EditorIcons")); step->set_icon(get_icon("DebugStep", "EditorIcons")); @@ -1193,6 +1222,10 @@ void ScriptEditorDebugger::_notification(int p_what) { if (profiler->is_profiling()) { _profiler_activate(true); } + + if (network_profiler->is_profiling()) { + _network_profiler_activate(true); + } } } @@ -1376,7 +1409,7 @@ void ScriptEditorDebugger::stop() { profiler->set_enabled(true); inspect_scene_tree->clear(); - EditorNode::get_singleton()->edit_current(); + inspector->edit(NULL); EditorNode::get_singleton()->get_pause_button()->set_pressed(false); EditorNode::get_singleton()->get_pause_button()->set_disabled(true); EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree(); @@ -1412,6 +1445,25 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable) { } } +void ScriptEditorDebugger::_network_profiler_activate(bool p_enable) { + + if (!connection.is_valid()) + return; + + if (p_enable) { + Array msg; + msg.push_back("start_network_profiling"); + ppeer->put_var(msg); + print_verbose("Starting network profiling."); + + } else { + Array msg; + msg.push_back("stop_network_profiling"); + ppeer->put_var(msg); + print_verbose("Ending network profiling."); + } +} + void ScriptEditorDebugger::_profiler_seeked() { if (!connection.is_valid() || !connection->is_connected_to_host()) @@ -1785,6 +1837,10 @@ void ScriptEditorDebugger::reload_scripts() { } } +bool ScriptEditorDebugger::is_skip_breakpoints() { + return skip_breakpoints_value; +} + void ScriptEditorDebugger::_error_activated() { TreeItem *selected = error_tree->get_selected(); @@ -1980,6 +2036,7 @@ void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected); + ClassDB::bind_method(D_METHOD("debug_skip_breakpoints"), &ScriptEditorDebugger::debug_skip_breakpoints); ClassDB::bind_method(D_METHOD("debug_copy"), &ScriptEditorDebugger::debug_copy); ClassDB::bind_method(D_METHOD("debug_next"), &ScriptEditorDebugger::debug_next); @@ -2000,6 +2057,7 @@ void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_expand_errors_list"), &ScriptEditorDebugger::_expand_errors_list); ClassDB::bind_method(D_METHOD("_collapse_errors_list"), &ScriptEditorDebugger::_collapse_errors_list); ClassDB::bind_method(D_METHOD("_profiler_activate"), &ScriptEditorDebugger::_profiler_activate); + ClassDB::bind_method(D_METHOD("_network_profiler_activate"), &ScriptEditorDebugger::_network_profiler_activate); ClassDB::bind_method(D_METHOD("_profiler_seeked"), &ScriptEditorDebugger::_profiler_seeked); ClassDB::bind_method(D_METHOD("_clear_errors_list"), &ScriptEditorDebugger::_clear_errors_list); @@ -2067,6 +2125,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { hbc->add_child(memnew(VSeparator)); + skip_breakpoints = memnew(ToolButton); + hbc->add_child(skip_breakpoints); + skip_breakpoints->set_tooltip(TTR("Skip Breakpoints")); + skip_breakpoints->connect("pressed", this, "debug_skip_breakpoints"); + + hbc->add_child(memnew(VSeparator)); + copy = memnew(ToolButton); hbc->add_child(copy); copy->set_tooltip(TTR("Copy Error")); @@ -2218,6 +2283,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { profiler->connect("break_request", this, "_profiler_seeked"); } + { //network profiler + network_profiler = memnew(EditorNetworkProfiler); + network_profiler->set_name(TTR("Network Profiler")); + tabs->add_child(network_profiler); + network_profiler->connect("enable_profiling", this, "_network_profiler_activate"); + } + { //monitors HSplitContainer *hsp = memnew(HSplitContainer); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 947b0cca52..ce48edfe89 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -50,6 +50,7 @@ class TreeItem; class HSplitContainer; class ItemList; class EditorProfiler; +class EditorNetworkProfiler; class ScriptEditorDebuggerInspectedObject; @@ -109,12 +110,15 @@ class ScriptEditorDebugger : public Control { bool hide_on_stop; bool enable_external_editor; + + bool skip_breakpoints_value = false; Ref<Script> stack_script; TabContainer *tabs; Label *reason; + Button *skip_breakpoints; Button *copy; Button *step; Button *next; @@ -152,6 +156,7 @@ class ScriptEditorDebugger : public Control { Map<String, int> res_path_cache; EditorProfiler *profiler; + EditorNetworkProfiler *network_profiler; EditorNode *editor; @@ -196,6 +201,8 @@ class ScriptEditorDebugger : public Control { void _profiler_activate(bool p_enable); void _profiler_seeked(); + void _network_profiler_activate(bool p_enable); + void _paused(); void _set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj); @@ -219,6 +226,7 @@ public: void unpause(); void stop(); + void debug_skip_breakpoints(); void debug_copy(); void debug_next(); @@ -256,6 +264,8 @@ public: void reload_scripts(); + bool is_skip_breakpoints(); + virtual Size2 get_minimum_size() const; ScriptEditorDebugger(EditorNode *p_editor = NULL); ~ScriptEditorDebugger(); |