summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_editor.cpp4
-rw-r--r--editor/code_editor.cpp35
-rw-r--r--editor/code_editor.h2
-rw-r--r--editor/create_dialog.cpp4
-rw-r--r--editor/doc/doc_data.cpp8
-rw-r--r--editor/editor_autoload_settings.cpp29
-rw-r--r--editor/editor_autoload_settings.h3
-rw-r--r--editor/editor_file_dialog.cpp19
-rw-r--r--editor/editor_file_dialog.h1
-rw-r--r--editor/editor_help.cpp203
-rw-r--r--editor/editor_help.h25
-rw-r--r--editor/editor_node.cpp63
-rw-r--r--editor/editor_plugin.cpp59
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_plugin_settings.cpp2
-rw-r--r--editor/editor_resource_preview.cpp1
-rw-r--r--editor/editor_settings.cpp58
-rw-r--r--editor/editor_settings.h3
-rw-r--r--editor/editor_sub_scene.cpp8
-rw-r--r--editor/editor_sub_scene.h2
-rw-r--r--editor/export_template_manager.cpp28
-rw-r--r--editor/fileserver/editor_file_server.cpp2
-rw-r--r--editor/filesystem_dock.cpp36
-rw-r--r--editor/filesystem_dock.h4
-rw-r--r--editor/icons/SCsub8
-rw-r--r--editor/import/editor_import_plugin.cpp16
-rw-r--r--editor/import/editor_import_plugin.h2
-rw-r--r--editor/import/resource_importer_obj.cpp14
-rw-r--r--editor/import/resource_importer_scene.cpp23
-rw-r--r--editor/import/resource_importer_scene.h10
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp12
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp3287
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h126
-rw-r--r--editor/plugins/editor_preview_plugins.cpp68
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp29
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h5
-rw-r--r--editor/plugins/script_editor_plugin.cpp135
-rw-r--r--editor/plugins/script_editor_plugin.h6
-rw-r--r--editor/plugins/script_text_editor.cpp52
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp11
-rw-r--r--editor/plugins/spatial_editor_plugin.h1
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_editor_plugin.cpp3
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp5
-rw-r--r--editor/project_manager.cpp10
-rw-r--r--editor/project_settings_editor.cpp13
-rw-r--r--editor/project_settings_editor.h2
-rw-r--r--editor/property_editor.cpp32
-rw-r--r--editor/scene_tree_dock.cpp3
-rw-r--r--editor/scene_tree_editor.cpp51
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--editor/script_create_dialog.cpp33
-rw-r--r--editor/script_create_dialog.h2
-rw-r--r--editor/script_editor_debugger.cpp20
-rw-r--r--editor/script_editor_debugger.h3
-rw-r--r--editor/spatial_editor_gizmos.cpp14
-rw-r--r--editor/spatial_editor_gizmos.h10
57 files changed, 2368 insertions, 2246 deletions
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index 91aa189c8f..c064f9cbdf 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -1359,7 +1359,7 @@ void AnimationKeyEditor::_track_editor_draw() {
Color ncol = color;
if (n && editor_selection->is_selected(n))
ncol = track_select_color;
- te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5);
+ te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (left_check_ofs + sep) - (type_icon[0]->get_width() + sep) - 5);
// Draw separator line below track area
if (!obj)
@@ -3362,7 +3362,7 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id, int p_last_track) {
//wants a new tack
{
- //shitty hack
+ //hack
NodePath np;
animation->add_track(p_id.type);
animation->track_set_path(animation->get_track_count() - 1, p_id.path);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 70334c2343..9ae9ab1501 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -666,6 +666,7 @@ void CodeTextEditor::_reset_zoom() {
if (font.is_valid()) {
EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14);
font->set_size(14);
+ zoom_nb->set_text("100%");
}
}
@@ -727,6 +728,9 @@ bool CodeTextEditor::_add_font_size(int p_delta) {
if (font.is_valid()) {
int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE);
+
+ zoom_nb->set_text(itos(100 * new_size / 14) + "%");
+
if (new_size != font->get_size()) {
EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE);
font->set_size(new_size);
@@ -771,6 +775,14 @@ void CodeTextEditor::set_error(const String &p_error) {
void CodeTextEditor::_update_font() {
text_editor->add_font_override("font", get_font("source", "EditorFonts"));
+
+ Ref<Font> status_bar_font = get_font("status_source", "EditorFonts");
+ int count = status_bar->get_child_count();
+ for (int i = 0; i < count; i++) {
+ Control *n = Object::cast_to<Control>(status_bar->get_child(i));
+ if (n)
+ n->add_font_override("font", status_bar_font);
+ }
}
void CodeTextEditor::_on_settings_change() {
@@ -851,7 +863,7 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_brace_matching(true);
text_editor->set_auto_indent(true);
- HBoxContainer *status_bar = memnew(HBoxContainer);
+ status_bar = memnew(HBoxContainer);
add_child(status_bar);
status_bar->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -878,6 +890,24 @@ CodeTextEditor::CodeTextEditor() {
status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible
+ Label *zoom_txt = memnew(Label);
+ status_bar->add_child(zoom_txt);
+ zoom_txt->set_align(Label::ALIGN_RIGHT);
+ zoom_txt->set_valign(Label::VALIGN_CENTER);
+ zoom_txt->set_v_size_flags(SIZE_FILL);
+ zoom_txt->set_text(TTR("Zoom:"));
+ zoom_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
+
+ zoom_nb = memnew(Label);
+ status_bar->add_child(zoom_nb);
+ zoom_nb->set_valign(Label::VALIGN_CENTER);
+ zoom_nb->set_v_size_flags(SIZE_FILL);
+ zoom_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch
+ zoom_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch
+ zoom_nb->set_custom_minimum_size(Size2(60, 1) * EDSCALE);
+ zoom_nb->set_align(Label::ALIGN_RIGHT);
+ zoom_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
+
Label *line_txt = memnew(Label);
status_bar->add_child(line_txt);
line_txt->set_align(Label::ALIGN_RIGHT);
@@ -931,7 +961,8 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->connect("timeout", this, "_code_complete_timer_timeout");
font_resize_val = 0;
- font_size = -1;
+ font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
+ zoom_nb->set_text(itos(100 * font_size / 14) + "%");
font_resize_timer = memnew(Timer);
add_child(font_resize_timer);
font_resize_timer->set_one_shot(true);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index db2e25b922..a860ad24e2 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -141,9 +141,11 @@ class CodeTextEditor : public VBoxContainer {
TextEdit *text_editor;
FindReplaceBar *find_replace_bar;
+ HBoxContainer *status_bar;
Label *line_nb;
Label *col_nb;
+ Label *zoom_nb;
Label *info;
Timer *idle;
Timer *code_complete_timer;
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 48ceb82dc3..fdc58e6292 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -316,6 +316,10 @@ void CreateDialog::_update_search() {
}
}
+ if (search_box->get_text() == "") {
+ to_select = root;
+ }
+
if (to_select) {
to_select->select(0);
search_options->scroll_to_item(to_select);
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
index 58eaab78ed..3a418e5f33 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -611,6 +611,14 @@ void DocData::generate(bool p_basic_types) {
ArgumentDoc ad;
argument_doc_from_arginfo(ad, mi.arguments[i]);
+
+ int darg_idx = i - (mi.arguments.size() - mi.default_arguments.size());
+
+ if (darg_idx >= 0) {
+ Variant default_arg = E->get().default_arguments[darg_idx];
+ ad.default_value = default_arg.get_construct_string();
+ }
+
md.arguments.push_back(ad);
}
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 393c33c1b0..d3e697ac35 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -246,7 +246,9 @@ void EditorAutoloadSettings::_autoload_button_pressed(Object *p_item, int p_colu
UndoRedo *undo_redo = EditorNode::get_undo_redo();
switch (p_button) {
-
+ case BUTTON_OPEN: {
+ _autoload_open(ti->get_text(1));
+ } break;
case BUTTON_MOVE_UP:
case BUTTON_MOVE_DOWN: {
@@ -305,6 +307,21 @@ void EditorAutoloadSettings::_autoload_button_pressed(Object *p_item, int p_colu
}
}
+void EditorAutoloadSettings::_autoload_activated() {
+ TreeItem *ti = tree->get_selected();
+ if (!ti)
+ return;
+ _autoload_open(ti->get_text(1));
+}
+
+void EditorAutoloadSettings::_autoload_open(const String &fpath) {
+ if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
+ EditorNode::get_singleton()->open_request(fpath);
+ } else {
+ EditorNode::get_singleton()->load_resource(fpath);
+ }
+ ProjectSettingsEditor::get_singleton()->hide();
+}
void EditorAutoloadSettings::_autoload_file_callback(const String &p_path) {
autoload_add_name->set_text(p_path.get_file().get_basename());
@@ -356,13 +373,13 @@ void EditorAutoloadSettings::update_autoload() {
item->set_editable(0, true);
item->set_text(1, path);
- item->set_selectable(1, false);
+ item->set_selectable(1, true);
item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
item->set_editable(2, true);
item->set_text(2, TTR("Enable"));
item->set_checked(2, global);
-
+ item->add_button(3, get_icon("FileList", "EditorIcons"), BUTTON_OPEN);
item->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP);
item->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN);
item->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_DELETE);
@@ -529,6 +546,8 @@ void EditorAutoloadSettings::_bind_methods() {
ClassDB::bind_method("_autoload_edited", &EditorAutoloadSettings::_autoload_edited);
ClassDB::bind_method("_autoload_button_pressed", &EditorAutoloadSettings::_autoload_button_pressed);
ClassDB::bind_method("_autoload_file_callback", &EditorAutoloadSettings::_autoload_file_callback);
+ ClassDB::bind_method("_autoload_activated", &EditorAutoloadSettings::_autoload_activated);
+ ClassDB::bind_method("_autoload_open", &EditorAutoloadSettings::_autoload_open);
ClassDB::bind_method("get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw);
ClassDB::bind_method("can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw);
@@ -595,12 +614,12 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
tree->set_column_min_width(2, 80);
tree->set_column_expand(3, false);
- tree->set_column_min_width(3, 80);
+ tree->set_column_min_width(3, 120);
tree->connect("cell_selected", this, "_autoload_selected");
tree->connect("item_edited", this, "_autoload_edited");
tree->connect("button_pressed", this, "_autoload_button_pressed");
-
+ tree->connect("item_activated", this, "_autoload_activated");
tree->set_v_size_flags(SIZE_EXPAND_FILL);
add_child(tree, true);
diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h
index 39f902179c..2e34a8b17f 100644
--- a/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
@@ -40,6 +40,7 @@ class EditorAutoloadSettings : public VBoxContainer {
GDCLASS(EditorAutoloadSettings, VBoxContainer);
enum {
+ BUTTON_OPEN,
BUTTON_MOVE_UP,
BUTTON_MOVE_DOWN,
BUTTON_DELETE
@@ -72,6 +73,8 @@ class EditorAutoloadSettings : public VBoxContainer {
void _autoload_selected();
void _autoload_edited();
void _autoload_button_pressed(Object *p_item, int p_column, int p_button);
+ void _autoload_activated();
+ void _autoload_open(const String &fpath);
void _autoload_file_callback(const String &p_path);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_control);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index f356c16827..22b33cc98f 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -458,6 +458,23 @@ void EditorFileDialog::_item_selected(int p_item) {
get_ok()->set_disabled(_is_open_should_be_disabled());
}
+void EditorFileDialog::_multi_selected(int p_item, bool p_selected) {
+
+ int current = p_item;
+ if (current < 0 || current >= item_list->get_item_count())
+ return;
+
+ Dictionary d = item_list->get_item_metadata(current);
+
+ if (!d["dir"] && p_selected) {
+
+ file->set_text(d["name"]);
+ _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+ }
+
+ get_ok()->set_disabled(_is_open_should_be_disabled());
+}
+
void EditorFileDialog::_items_clear_selection() {
item_list->unselect_all();
@@ -1290,6 +1307,7 @@ void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorFileDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_item_selected"), &EditorFileDialog::_item_selected);
+ ClassDB::bind_method(D_METHOD("_multi_selected"), &EditorFileDialog::_multi_selected);
ClassDB::bind_method(D_METHOD("_items_clear_selection"), &EditorFileDialog::_items_clear_selection);
ClassDB::bind_method(D_METHOD("_item_list_item_rmb_selected"), &EditorFileDialog::_item_list_item_rmb_selected);
ClassDB::bind_method(D_METHOD("_item_list_rmb_clicked"), &EditorFileDialog::_item_list_rmb_clicked);
@@ -1598,6 +1616,7 @@ EditorFileDialog::EditorFileDialog() {
connect("confirmed", this, "_action_pressed");
item_list->connect("item_selected", this, "_item_selected", varray(), CONNECT_DEFERRED);
+ item_list->connect("multi_selected", this, "_multi_selected", varray(), CONNECT_DEFERRED);
item_list->connect("item_activated", this, "_item_db_selected", varray());
item_list->connect("nothing_selected", this, "_items_clear_selection");
dir->connect("text_entered", this, "_dir_entered");
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 05f66eadbf..b1f8f1108c 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -159,6 +159,7 @@ private:
void _recent_selected(int p_idx);
void _item_selected(int p_item);
+ void _multi_selected(int p_item, bool p_selected);
void _items_clear_selection();
void _item_dc_selected(int p_item);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 198a52fef2..7f76cf1af2 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -81,162 +81,147 @@ void EditorHelpSearch::_sbox_input(const Ref<InputEvent> &p_ie) {
}
}
-class EditorHelpSearch::IncrementalSearch : public Reference {
- String term;
- TreeItem *root;
+void EditorHelpSearch::IncrementalSearch::phase1(Map<String, DocData::ClassDoc>::Element *E) {
- EditorHelpSearch *search;
- Tree *search_options;
+ if (E->key().findn(term) != -1) {
- DocData *doc;
- Ref<Texture> def_icon;
-
- int phase;
- Map<String, DocData::ClassDoc>::Element *iterator;
-
- void phase1(Map<String, DocData::ClassDoc>::Element *E) {
-
- if (E->key().findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_name:" + E->key());
- item->set_text(0, E->key() + " (Class)");
- if (search->has_icon(E->key(), "EditorIcons"))
- item->set_icon(0, search->get_icon(E->key(), "EditorIcons"));
- else
- item->set_icon(0, def_icon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_name:" + E->key());
+ item->set_text(0, E->key() + " (Class)");
+ if (search->has_icon(E->key(), "EditorIcons"))
+ item->set_icon(0, search->get_icon(E->key(), "EditorIcons"));
+ else
+ item->set_icon(0, def_icon);
}
+}
- void phase2(Map<String, DocData::ClassDoc>::Element *E) {
+void EditorHelpSearch::IncrementalSearch::phase2(Map<String, DocData::ClassDoc>::Element *E) {
- DocData::ClassDoc &c = E->get();
+ DocData::ClassDoc &c = E->get();
- Ref<Texture> cicon;
- if (search->has_icon(E->key(), "EditorIcons"))
- cicon = search->get_icon(E->key(), "EditorIcons");
- else
- cicon = def_icon;
+ Ref<Texture> cicon;
+ if (search->has_icon(E->key(), "EditorIcons"))
+ cicon = search->get_icon(E->key(), "EditorIcons");
+ else
+ cicon = def_icon;
- for (int i = 0; i < c.methods.size(); i++) {
- if ((term.begins_with(".") && c.methods[i].name.begins_with(term.right(1))) || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name == term.substr(1, term.length() - 2).strip_edges()) || c.methods[i].name.findn(term) != -1) {
+ for (int i = 0; i < c.methods.size(); i++) {
+ if ((term.begins_with(".") && c.methods[i].name.begins_with(term.right(1))) || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name == term.substr(1, term.length() - 2).strip_edges()) || c.methods[i].name.findn(term) != -1) {
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_method:" + E->key() + ":" + c.methods[i].name);
- item->set_text(0, E->key() + "." + c.methods[i].name + " (Method)");
- item->set_icon(0, cicon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_method:" + E->key() + ":" + c.methods[i].name);
+ item->set_text(0, E->key() + "." + c.methods[i].name + " (Method)");
+ item->set_icon(0, cicon);
}
+ }
- for (int i = 0; i < c.signals.size(); i++) {
+ for (int i = 0; i < c.signals.size(); i++) {
- if (c.signals[i].name.findn(term) != -1) {
+ if (c.signals[i].name.findn(term) != -1) {
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_signal:" + E->key() + ":" + c.signals[i].name);
- item->set_text(0, E->key() + "." + c.signals[i].name + " (Signal)");
- item->set_icon(0, cicon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_signal:" + E->key() + ":" + c.signals[i].name);
+ item->set_text(0, E->key() + "." + c.signals[i].name + " (Signal)");
+ item->set_icon(0, cicon);
}
+ }
- for (int i = 0; i < c.constants.size(); i++) {
+ for (int i = 0; i < c.constants.size(); i++) {
- if (c.constants[i].name.findn(term) != -1) {
+ if (c.constants[i].name.findn(term) != -1) {
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_constant:" + E->key() + ":" + c.constants[i].name);
- item->set_text(0, E->key() + "." + c.constants[i].name + " (Constant)");
- item->set_icon(0, cicon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_constant:" + E->key() + ":" + c.constants[i].name);
+ item->set_text(0, E->key() + "." + c.constants[i].name + " (Constant)");
+ item->set_icon(0, cicon);
}
+ }
- for (int i = 0; i < c.properties.size(); i++) {
+ for (int i = 0; i < c.properties.size(); i++) {
- if (c.properties[i].name.findn(term) != -1) {
+ if (c.properties[i].name.findn(term) != -1) {
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_property:" + E->key() + ":" + c.properties[i].name);
- item->set_text(0, E->key() + "." + c.properties[i].name + " (Property)");
- item->set_icon(0, cicon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_property:" + E->key() + ":" + c.properties[i].name);
+ item->set_text(0, E->key() + "." + c.properties[i].name + " (Property)");
+ item->set_icon(0, cicon);
}
+ }
- for (int i = 0; i < c.theme_properties.size(); i++) {
+ for (int i = 0; i < c.theme_properties.size(); i++) {
- if (c.theme_properties[i].name.findn(term) != -1) {
+ if (c.theme_properties[i].name.findn(term) != -1) {
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_theme_item:" + E->key() + ":" + c.theme_properties[i].name);
- item->set_text(0, E->key() + "." + c.theme_properties[i].name + " (Theme Item)");
- item->set_icon(0, cicon);
- }
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0, "class_theme_item:" + E->key() + ":" + c.theme_properties[i].name);
+ item->set_text(0, E->key() + "." + c.theme_properties[i].name + " (Theme Item)");
+ item->set_icon(0, cicon);
}
}
+}
- bool slice() {
+bool EditorHelpSearch::IncrementalSearch::slice() {
- if (phase > 2)
- return true;
+ if (phase > 2)
+ return true;
- if (iterator) {
+ if (iterator) {
- switch (phase) {
+ switch (phase) {
- case 1: {
- phase1(iterator);
- } break;
- case 2: {
- phase2(iterator);
- } break;
- default: {
- WARN_PRINT("illegal phase in IncrementalSearch");
- return true;
- }
+ case 1: {
+ phase1(iterator);
+ } break;
+ case 2: {
+ phase2(iterator);
+ } break;
+ default: {
+ WARN_PRINT("illegal phase in IncrementalSearch");
+ return true;
}
-
- iterator = iterator->next();
- } else {
-
- phase += 1;
- iterator = doc->class_list.front();
}
- return false;
+ iterator = iterator->next();
+ } else {
+
+ phase += 1;
+ iterator = doc->class_list.front();
}
-public:
- IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term) :
- search(p_search),
- search_options(p_search_options) {
+ return false;
+}
- def_icon = search->get_icon("Node", "EditorIcons");
- doc = EditorHelp::get_doc_data();
+EditorHelpSearch::IncrementalSearch::IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term) :
+ search(p_search),
+ search_options(p_search_options) {
- term = p_term;
+ def_icon = search->get_icon("Node", "EditorIcons");
+ doc = EditorHelp::get_doc_data();
- root = search_options->create_item();
- phase = 0;
- iterator = 0;
- }
+ term = p_term;
- bool empty() const {
+ root = search_options->create_item();
+ phase = 0;
+ iterator = 0;
+}
- return root->get_children() == NULL;
- }
+bool EditorHelpSearch::IncrementalSearch::empty() const {
- bool work(uint64_t slot = 1000000 / 10) {
+ return root->get_children() == NULL;
+}
- const uint64_t until = OS::get_singleton()->get_ticks_usec() + slot;
+bool EditorHelpSearch::IncrementalSearch::work(uint64_t slot) {
- while (!slice()) {
+ const uint64_t until = OS::get_singleton()->get_ticks_usec() + slot;
- if (OS::get_singleton()->get_ticks_usec() > until)
- return false;
- }
+ while (!slice()) {
- return true;
+ if (OS::get_singleton()->get_ticks_usec() > until)
+ return false;
}
-};
+
+ return true;
+}
void EditorHelpSearch::_update_search() {
search_options->clear();
diff --git a/editor/editor_help.h b/editor/editor_help.h
index db4c33afb0..aa84aa611f 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -54,7 +54,30 @@ class EditorHelpSearch : public ConfirmationDialog {
Tree *search_options;
String base_type;
- class IncrementalSearch;
+ class IncrementalSearch : public Reference {
+ String term;
+ TreeItem *root;
+
+ EditorHelpSearch *search;
+ Tree *search_options;
+
+ DocData *doc;
+ Ref<Texture> def_icon;
+
+ int phase;
+ Map<String, DocData::ClassDoc>::Element *iterator;
+
+ void phase1(Map<String, DocData::ClassDoc>::Element *E);
+ void phase2(Map<String, DocData::ClassDoc>::Element *E);
+ bool slice();
+
+ public:
+ IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term);
+
+ bool empty() const;
+ bool work(uint64_t slot = 1000000 / 10);
+ };
+
Ref<IncrementalSearch> search;
void _update_search();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2f0c41c6e1..29912feb1f 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -217,6 +217,12 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
} else if (ED_IS_SHORTCUT("editor/editor_prev", p_event)) {
_editor_select_prev();
}
+
+ if (k->get_scancode() == KEY_ESCAPE) {
+ for (int i = 0; i < bottom_panel_items.size(); i++) {
+ _bottom_panel_switch(false, i);
+ }
+ }
}
}
@@ -339,7 +345,7 @@ void EditorNode::_notification(int p_what) {
if (ScriptEditor::get_singleton()->get_debugger()->is_visible())
bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
- //_update_icons
+ // update_icons
for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
Ref<Texture> icon = singleton->main_editor_buttons[i]->get_icon();
@@ -709,7 +715,7 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) {
case ERR_CANT_OPEN: {
- accept->set_text(vformat(TTR("Can't open '%s'."), p_file.get_file()));
+ accept->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()));
} break;
case ERR_PARSE_ERROR: {
@@ -1110,7 +1116,7 @@ void EditorNode::_dialog_action(String p_file) {
if (res.is_null()) {
current_option = -1;
- accept->get_ok()->set_text("ok :(");
+ accept->get_ok()->set_text("Ugh");
accept->set_text(TTR("Failed to load resource."));
return;
};
@@ -1145,6 +1151,7 @@ void EditorNode::_dialog_action(String p_file) {
_save_default_environment();
_save_scene_with_preview(p_file, scene_idx);
+ _add_to_recent_scenes(p_file);
if (scene_idx != -1)
_discard_changes();
@@ -1919,7 +1926,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (!scene) {
current_option = -1;
- //confirmation->get_cancel()->hide();
accept->get_ok()->set_text(TTR("I see.."));
accept->set_text(TTR("This operation can't be done without a tree root."));
accept->popup_centered_minsize();
@@ -1937,7 +1943,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
}
- //file->set_current_path(current_path);
if (scene->get_filename() != "") {
file->set_current_path(scene->get_filename());
if (extensions.size()) {
@@ -1987,7 +1992,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (!editor_data.get_edited_scene_root()) {
current_option = -1;
- //confirmation->get_cancel()->hide();
accept->get_ok()->set_text(TTR("I see.."));
accept->set_text(TTR("This operation can't be done without a scene."));
accept->popup_centered_minsize();
@@ -2036,8 +2040,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case FILE_IMPORT_SUBSCENE: {
- //import_subscene->popup_centered_ratio();
-
if (!editor_data.get_edited_scene_root()) {
current_option = -1;
@@ -2056,7 +2058,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (unsaved_cache && !p_confirmed) {
confirmation->get_ok()->set_text(TTR("Open"));
- //confirmation->get_cancel()->show();
confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
confirmation->popup_centered_minsize();
break;
@@ -2843,7 +2844,7 @@ void EditorNode::_remove_scene(int index) {
//Scene to remove is current scene
_remove_edited_scene();
} else {
- // Scene to remove is not active scene
+ //Scene to remove is not active scene
editor_data.remove_scene(index);
}
}
@@ -3240,48 +3241,47 @@ void EditorNode::_show_messages() {
void EditorNode::_add_to_recent_scenes(const String &p_scene) {
- String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::");
- Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
- String name = p_scene;
- name = name.replace("res://", "");
- if (rc.find(name) != -1)
- rc.erase(name);
- rc.insert(0, name);
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
+ if (rc.find(p_scene) != -1)
+ rc.erase(p_scene);
+ rc.push_front(p_scene);
if (rc.size() > 10)
rc.resize(10);
- EditorSettings::get_singleton()->set(base + "/_recent_scenes", rc);
- EditorSettings::get_singleton()->save();
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc);
_update_recent_scenes();
}
void EditorNode::_open_recent_scene(int p_idx) {
- String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::");
-
if (p_idx == recent_scenes->get_item_count() - 1) {
- EditorSettings::get_singleton()->erase(base + "/_recent_scenes");
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", Array());
call_deferred("_update_recent_scenes");
} else {
- Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
ERR_FAIL_INDEX(p_idx, rc.size());
- String path = "res://" + rc[p_idx];
- load_scene(path);
+ if (load_scene(rc[p_idx]) != OK) {
+
+ rc.remove(p_idx);
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc);
+ _update_recent_scenes();
+ }
}
}
void EditorNode::_update_recent_scenes() {
- String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::");
- Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
recent_scenes->clear();
+ String path;
for (int i = 0; i < rc.size(); i++) {
- recent_scenes->add_item(rc[i], i);
+ path = rc[i];
+ recent_scenes->add_item(path.replace("res://", ""), i);
}
recent_scenes->add_separator();
@@ -4815,6 +4815,10 @@ EditorNode::EditorNode() {
Ref<EditorSceneImporterGLTF> import_gltf;
import_gltf.instance();
import_scene->add_importer(import_gltf);
+
+ Ref<EditorSceneImporterESCN> import_escn;
+ import_escn.instance();
+ import_scene->add_importer(import_escn);
}
Ref<ResourceImporterBitMap> import_bitmap;
@@ -5114,7 +5118,6 @@ EditorNode::EditorNode() {
gui_base->add_child(dependency_fixer);
settings_config_dialog = memnew(EditorSettingsDialog);
- // settings_config_dialog->add_style_override("panel", gui_base->get_stylebox("EditorSettingsDialog", "EditorStyles"));
gui_base->add_child(settings_config_dialog);
project_settings = memnew(ProjectSettingsEditor(&editor_data));
@@ -5188,7 +5191,6 @@ EditorNode::EditorNode() {
p->add_item(TTR("Project Settings"), RUN_SETTINGS);
p->add_separator();
p->connect("id_pressed", this, "_menu_option");
- //p->add_item(TTR("Run Script"), FILE_RUN_SCRIPT, KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_R);
p->add_item(TTR("Export"), FILE_EXPORT_PROJECT);
PopupMenu *tool_menu = memnew(PopupMenu);
@@ -5279,7 +5281,6 @@ EditorNode::EditorNode() {
menu_hb->add_child(play_cc);
play_button_panel = memnew(PanelContainer);
- // play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
play_cc->add_child(play_button_panel);
HBoxContainer *play_hb = memnew(HBoxContainer);
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 9dd8a7232f..733680645f 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -235,6 +235,14 @@ Control *EditorInterface::get_base_control() {
return EditorNode::get_singleton()->get_gui_base();
}
+void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) {
+ EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled);
+}
+
+bool EditorInterface::is_plugin_enabled(const String &p_plugin) const {
+ return EditorNode::get_singleton()->is_addon_plugin_enabled(p_plugin);
+}
+
Error EditorInterface::save_scene() {
if (!get_edited_scene_root())
return ERR_CANT_CREATE;
@@ -271,6 +279,9 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("select_file", "p_file"), &EditorInterface::select_file);
ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path);
+ ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled);
+ ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled);
+
ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene);
ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true));
}
@@ -362,6 +373,53 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C
}
}
+void EditorPlugin::remove_control_from_container(CustomControlContainer p_location, Control *p_control) {
+
+ switch (p_location) {
+
+ case CONTAINER_TOOLBAR: {
+
+ EditorNode::get_menu_hb()->remove_child(p_control);
+ } break;
+
+ case CONTAINER_SPATIAL_EDITOR_MENU: {
+
+ SpatialEditor::get_singleton()->remove_control_from_menu_panel(p_control);
+
+ } break;
+ case CONTAINER_SPATIAL_EDITOR_SIDE: {
+
+ SpatialEditor::get_singleton()->get_palette_split()->remove_child(p_control);
+
+ } break;
+ case CONTAINER_SPATIAL_EDITOR_BOTTOM: {
+
+ SpatialEditor::get_singleton()->get_shader_split()->remove_child(p_control);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_MENU: {
+
+ CanvasItemEditor::get_singleton()->remove_control_from_menu_panel(p_control);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_SIDE: {
+
+ CanvasItemEditor::get_singleton()->get_palette_split()->remove_child(p_control);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_BOTTOM: {
+
+ CanvasItemEditor::get_singleton()->get_bottom_split()->remove_child(p_control);
+
+ } break;
+ case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
+
+ EditorNode::get_singleton()->get_property_editor_vb()->remove_child(p_control);
+
+ } break;
+ }
+}
+
void EditorPlugin::add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud) {
//EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud);
@@ -640,6 +698,7 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_control_to_dock", "slot", "control"), &EditorPlugin::add_control_to_dock);
ClassDB::bind_method(D_METHOD("remove_control_from_docks", "control"), &EditorPlugin::remove_control_from_docks);
ClassDB::bind_method(D_METHOD("remove_control_from_bottom_panel", "control"), &EditorPlugin::remove_control_from_bottom_panel);
+ ClassDB::bind_method(D_METHOD("remove_control_from_container", "container", "control"), &EditorPlugin::remove_control_from_container);
//ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu"), &EditorPlugin::add_tool_submenu_item);
//ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 145dccc2d5..e3e405479c 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -90,6 +90,9 @@ public:
Control *get_base_control();
+ void set_plugin_enabled(const String &p_plugin, bool p_enabled);
+ bool is_plugin_enabled(const String &p_plugin) const;
+
Error save_scene();
void save_scene_as(const String &p_scene, bool p_with_preview = true);
@@ -145,6 +148,7 @@ public:
//TODO: send a resource for editing to the editor node?
void add_control_to_container(CustomControlContainer p_location, Control *p_control);
+ void remove_control_from_container(CustomControlContainer p_location, Control *p_control);
ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title);
void add_control_to_dock(DockSlot p_slot, Control *p_control);
void remove_control_from_docks(Control *p_control);
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 8803a03f2d..ea1e0fe99e 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -83,8 +83,6 @@ void EditorPluginSettings::update_plugins() {
plugins.sort();
- Vector<String> active_plugins = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
-
for (int i = 0; i < plugins.size(); i++) {
Ref<ConfigFile> cf;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 93787a7a4c..aa67ea03d7 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -253,7 +253,6 @@ void EditorResourcePreview::_thread() {
img.instance();
if (img->load(cache_base + ".png") != OK) {
- //well fuck
cache_valid = false;
} else {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 433f501fc8..29363e29c1 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -256,8 +256,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
String best;
- for (int i = 0; i < translations.size(); i++) {
- String locale = translations[i]->get_locale();
+ EditorTranslationList *etl = _editor_translations;
+
+ while (etl->data) {
+
+ const String &locale = etl->lang;
lang_hint += ",";
lang_hint += locale;
@@ -268,6 +271,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
if (best == String() && host_lang.begins_with(locale)) {
best = locale;
}
+
+ etl++;
}
if (best == String()) {
@@ -382,8 +387,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
_initial_set("text_editor/files/restore_scripts_on_load", true);
_initial_set("text_editor/completion/complete_file_paths", true);
- _initial_set("text_editor/files/maximum_recent_files", 20);
- hints["text_editor/files/maximum_recent_files"] = PropertyInfo(Variant::INT, "text_editor/files/maximum_recent_files", PROPERTY_HINT_RANGE, "1, 200, 1");
_initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
_initial_set("docks/scene_tree/draw_relationship_lines", false);
@@ -885,11 +888,29 @@ void EditorSettings::setup_language() {
if (lang == "en")
return; //none to do
- for (int i = 0; i < translations.size(); i++) {
- if (translations[i]->get_locale() == lang) {
- TranslationServer::get_singleton()->set_tool_translation(translations[i]);
- break;
+ EditorTranslationList *etl = _editor_translations;
+
+ while (etl->data) {
+
+ if (etl->lang == lang) {
+
+ Vector<uint8_t> data;
+ data.resize(etl->uncomp_size);
+ Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
+
+ FileAccessMemory *fa = memnew(FileAccessMemory);
+ fa->open_custom(data.ptr(), data.size());
+
+ Ref<Translation> tr = TranslationLoaderPO::load_translation(fa, NULL, "translation_" + String(etl->lang));
+
+ if (tr.is_valid()) {
+ tr->set_locale(etl->lang);
+ TranslationServer::get_singleton()->set_tool_translation(tr);
+ break;
+ }
}
+
+ etl++;
}
}
@@ -1459,27 +1480,6 @@ EditorSettings::EditorSettings() {
optimize_save = true;
save_changed_setting = true;
- EditorTranslationList *etl = _editor_translations;
-
- while (etl->data) {
-
- Vector<uint8_t> data;
- data.resize(etl->uncomp_size);
- Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
-
- FileAccessMemory *fa = memnew(FileAccessMemory);
- fa->open_custom(data.ptr(), data.size());
-
- Ref<Translation> tr = TranslationLoaderPO::load_translation(fa, NULL, "translation_" + String(etl->lang));
-
- if (tr.is_valid()) {
- tr->set_locale(etl->lang);
- translations.push_back(tr);
- }
-
- etl++;
- }
-
_load_defaults();
}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 914316ee61..e196ca506e 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -95,7 +95,6 @@ private:
int last_order;
Ref<Resource> clipboard;
- Vector<Ref<Translation> > translations;
Map<String, Ref<ShortCut> > shortcuts;
String resource_path;
@@ -145,7 +144,7 @@ public:
bool has_setting(const String &p_setting) const;
void erase(const String &p_setting);
void raise_order(const String &p_setting);
- void set_initial_value(const StringName &p_setting, const Variant &p_value, bool update_current = false);
+ void set_initial_value(const StringName &p_setting, const Variant &p_value, bool p_update_current = false);
void set_manually(const StringName &p_setting, const Variant &p_value, bool p_emit_signal = false) {
if (p_emit_signal)
_set(p_setting, p_value);
diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp
index 7527b198b8..056ee59860 100644
--- a/editor/editor_sub_scene.cpp
+++ b/editor/editor_sub_scene.cpp
@@ -121,10 +121,10 @@ void EditorSubScene::_item_multi_selected(Object *p_object, int p_cell, bool p_s
}
}
-void EditorSubScene::_remove_selection_child(Node *n) {
- if (n->get_child_count() > 0) {
- for (int i = 0; i < n->get_child_count(); i++) {
- Node *c = n->get_child(i);
+void EditorSubScene::_remove_selection_child(Node *p_node) {
+ if (p_node->get_child_count() > 0) {
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ Node *c = p_node->get_child(i);
List<Node *>::Element *E = selection.find(c);
if (E) {
selection.move_to_back(E);
diff --git a/editor/editor_sub_scene.h b/editor/editor_sub_scene.h
index cf4d6fd5b9..202ba03cea 100644
--- a/editor/editor_sub_scene.h
+++ b/editor/editor_sub_scene.h
@@ -50,7 +50,7 @@ class EditorSubScene : public ConfirmationDialog {
void _fill_tree(Node *p_node, TreeItem *p_parent);
void _selected_changed();
void _item_multi_selected(Object *p_object, int p_cell, bool p_selected);
- void _remove_selection_child(Node *c);
+ void _remove_selection_child(Node *p_node);
void _reown(Node *p_node, List<Node *> *p_to_reown);
void ok_pressed();
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 6cbca3f733..41b016bdca 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -30,6 +30,8 @@
#include "export_template_manager.h"
+#include "core/os/input.h"
+#include "core/os/keyboard.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "io/json.h"
@@ -400,19 +402,10 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int
if (p_code != 200) {
template_list_state->set_text(TTR("Failed:") + " " + itos(p_code));
} else {
- String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz");
- FileAccess *f = FileAccess::open(path, FileAccess::WRITE);
- if (!f) {
- template_list_state->set_text(TTR("Can't write file."));
- } else {
- int size = p_data.size();
- PoolVector<uint8_t>::Read r = p_data.read();
- f->store_buffer(r.ptr(), size);
- memdelete(f);
- template_list_state->set_text(TTR("Download Complete."));
- template_downloader->hide();
- _install_from_file(path, false);
- }
+ String path = download_templates->get_download_file();
+ template_list_state->set_text(TTR("Download Complete."));
+ template_downloader->hide();
+ _install_from_file(path, false);
}
} break;
}
@@ -422,6 +415,11 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int
void ExportTemplateManager::_begin_template_download(const String &p_url) {
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ OS::get_singleton()->shell_open(p_url);
+ return;
+ }
+
for (int i = 0; i < template_list->get_child_count(); i++) {
BaseButton *b = Object::cast_to<BaseButton>(template_list->get_child(0));
if (b) {
@@ -430,6 +428,8 @@ void ExportTemplateManager::_begin_template_download(const String &p_url) {
}
download_data.clear();
+ download_templates->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz"));
+ download_templates->set_use_threads(true);
Error err = download_templates->request(p_url);
if (err != OK) {
@@ -576,7 +576,7 @@ ExportTemplateManager::ExportTemplateManager() {
template_downloader->add_child(vbc);
ScrollContainer *sc = memnew(ScrollContainer);
sc->set_custom_minimum_size(Size2(400, 200) * EDSCALE);
- vbc->add_margin_child(TTR("Select mirror from list: "), sc);
+ vbc->add_margin_child(TTR("Select mirror from list: (Shift+Click: Open in Browser)"), sc);
template_list = memnew(VBoxContainer);
sc->add_child(template_list);
sc->set_enable_v_scroll(true);
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 56fb7633e7..a218070933 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -55,7 +55,7 @@ void EditorFileServer::_subthread_start(void *s) {
ClientData *cd = (ClientData *)s;
- cd->connection->set_nodelay(true);
+ cd->connection->set_no_delay(true);
uint8_t buf4[8];
Error err = cd->connection->get_data(buf4, 4);
if (err != OK) {
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index cc9c9a11d7..e26f4ba449 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -30,6 +30,7 @@
#include "filesystem_dock.h"
+#include "core/os/keyboard.h"
#include "editor_node.h"
#include "editor_settings.h"
#include "io/resource_loader.h"
@@ -77,7 +78,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
return true;
}
-void FileSystemDock::_update_tree(bool keep_collapse_state) {
+void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_root) {
Vector<String> uncollapsed_paths;
if (keep_collapse_state) {
@@ -129,6 +130,10 @@ void FileSystemDock::_update_tree(bool keep_collapse_state) {
ti->set_metadata(0, fave);
}
+ if (p_uncollapse_root) {
+ uncollapsed_paths.push_back("res://");
+ }
+
_create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths);
tree->ensure_cursor_is_visible();
updating_tree = false;
@@ -154,6 +159,7 @@ void FileSystemDock::_notification(int p_what) {
} else {
tree->set_v_size_flags(SIZE_FILL);
+ button_tree->hide();
if (!tree->is_visible()) {
tree->show();
button_favorite->show();
@@ -163,7 +169,6 @@ void FileSystemDock::_notification(int p_what) {
if (!file_list_vb->is_visible()) {
file_list_vb->show();
- button_tree->hide();
_update_files(true);
}
}
@@ -204,7 +209,7 @@ void FileSystemDock::_notification(int p_what) {
if (EditorFileSystem::get_singleton()->is_scanning()) {
_set_scanning_mode();
} else {
- _update_tree(false);
+ _update_tree(false, true);
}
} break;
@@ -488,7 +493,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
Ref<Texture> folderIcon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog");
if (path != "res://") {
- files->add_item("..", folderIcon, false);
+ files->add_item("..", folderIcon, true);
String bd = path.get_base_dir();
if (bd != "res://" && !bd.ends_with("/"))
@@ -1637,6 +1642,23 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
call_deferred("_update_import_dock");
}
+void FileSystemDock::_files_gui_input(Ref<InputEvent> p_event) {
+
+ if (get_viewport()->get_modal_stack_top())
+ return; //ignore because of modal window
+
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
+ if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) {
+ _file_option(FILE_DUPLICATE);
+ } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) {
+ _file_option(FILE_COPY_PATH);
+ } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) {
+ _file_option(FILE_REMOVE);
+ }
+ }
+}
+
void FileSystemDock::_file_selected() {
import_dock_needs_update = true;
@@ -1693,6 +1715,7 @@ void FileSystemDock::_update_import_dock() {
void FileSystemDock::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_files_gui_input"), &FileSystemDock::_files_gui_input);
ClassDB::bind_method(D_METHOD("_update_tree"), &FileSystemDock::_update_tree);
ClassDB::bind_method(D_METHOD("_rescan"), &FileSystemDock::_rescan);
ClassDB::bind_method(D_METHOD("_favorites_pressed"), &FileSystemDock::_favorites_pressed);
@@ -1739,6 +1762,10 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
editor = p_editor;
path = "res://";
+ ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_C);
+ ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D);
+ ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE);
+
HBoxContainer *toolbar_hbc = memnew(HBoxContainer);
add_child(toolbar_hbc);
@@ -1845,6 +1872,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
files->set_select_mode(ItemList::SELECT_MULTI);
files->set_drag_forwarding(this);
files->connect("item_rmb_selected", this, "_files_list_rmb_select");
+ files->connect("gui_input", this, "_files_gui_input");
files->connect("item_selected", this, "_file_selected");
files->connect("multi_selected", this, "_file_multi_selected");
files->connect("rmb_clicked", this, "_rmb_pressed");
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index af80557465..377316d1ba 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -157,7 +157,9 @@ private:
bool import_dock_needs_update;
bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths);
- void _update_tree(bool keep_collapse_state);
+ void _update_tree(bool keep_collapse_state, bool p_uncollapse_root = false);
+
+ void _files_gui_input(Ref<InputEvent> p_event);
void _update_files(bool p_keep_selection);
void _update_file_display_toggle_button();
diff --git a/editor/icons/SCsub b/editor/icons/SCsub
index 9bd036dfa9..64992a9f90 100644
--- a/editor/icons/SCsub
+++ b/editor/icons/SCsub
@@ -34,7 +34,7 @@ def make_editor_icons_action(target, source, env):
s.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
s.write("#ifndef _EDITOR_ICONS_H\n")
s.write("#define _EDITOR_ICONS_H\n")
- s.write("static const int editor_icons_count = %s;\n" % len(svg_icons))
+ s.write("static const int editor_icons_count = {};\n".format(len(svg_icons)))
s.write("static const char *editor_icons_sources[] = {\n")
s.write(icons_string.getvalue())
s.write('};\n\n')
@@ -57,7 +57,7 @@ def make_editor_icons_action(target, source, env):
if icon_name.endswith("BigThumb"): # don't know a better way to handle this
thumb_big_indices.append(str(index))
- s.write('\t"%s"' % icon_name)
+ s.write('\t"{0}"'.format(icon_name))
if fname != svg_icons[-1]:
s.write(",")
@@ -69,13 +69,13 @@ def make_editor_icons_action(target, source, env):
if thumb_medium_indices:
s.write("\n\n")
- s.write("static const int editor_md_thumbs_count = %s;\n" % len(thumb_medium_indices))
+ s.write("static const int editor_md_thumbs_count = {};\n".format(len(thumb_medium_indices)))
s.write("static const int editor_md_thumbs_indices[] = {")
s.write(", ".join(thumb_medium_indices))
s.write("};\n")
if thumb_big_indices:
s.write("\n\n")
- s.write("static const int editor_bg_thumbs_count = %s;\n" % len(thumb_big_indices))
+ s.write("static const int editor_bg_thumbs_count = {};\n".format(len(thumb_big_indices)))
s.write("static const int editor_bg_thumbs_indices[] = {")
s.write(", ".join(thumb_big_indices))
s.write("};\n")
diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp
index 07c77a9df0..c1c1183692 100644
--- a/editor/import/editor_import_plugin.cpp
+++ b/editor/import/editor_import_plugin.cpp
@@ -72,6 +72,20 @@ String EditorImportPlugin::get_resource_type() const {
return get_script_instance()->call("get_resource_type");
}
+float EditorImportPlugin::get_priority() const {
+ if (!(get_script_instance() && get_script_instance()->has_method("get_priority"))) {
+ return ResourceImporter::get_priority();
+ }
+ return get_script_instance()->call("get_priority");
+}
+
+int EditorImportPlugin::get_import_order() const {
+ if (!(get_script_instance() && get_script_instance()->has_method("get_import_order"))) {
+ return ResourceImporter::get_import_order();
+ }
+ return get_script_instance()->call("get_import_order");
+}
+
void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options, int p_preset) const {
ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("get_import_options")));
@@ -148,6 +162,8 @@ void EditorImportPlugin::_bind_methods() {
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_import_options", PropertyInfo(Variant::INT, "preset")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_save_extension"));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type"));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::REAL, "get_priority"));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_import_order"));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "get_option_visibility", PropertyInfo(Variant::STRING, "option"), PropertyInfo(Variant::DICTIONARY, "options")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "import", PropertyInfo(Variant::STRING, "source_file"), PropertyInfo(Variant::STRING, "save_path"), PropertyInfo(Variant::DICTIONARY, "options"), PropertyInfo(Variant::ARRAY, "r_platform_variants"), PropertyInfo(Variant::ARRAY, "r_gen_files")));
}
diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h
index 61a0a944f5..92d83158ef 100644
--- a/editor/import/editor_import_plugin.h
+++ b/editor/import/editor_import_plugin.h
@@ -47,6 +47,8 @@ public:
virtual int get_preset_count() const;
virtual String get_save_extension() const;
virtual String get_resource_type() const;
+ virtual float get_priority() const;
+ virtual int get_import_order() const;
virtual void get_import_options(List<ImportOption> *r_options, int p_preset) 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);
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 78fc9ec9bd..21803a2184 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -188,7 +188,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati
return OK;
}
-static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, List<String> *r_missing_deps) {
+static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, Vector3 p_scale_mesh, List<String> *r_missing_deps) {
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
@@ -198,6 +198,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p
mesh.instance();
bool generate_tangents = p_generate_tangents;
+ Vector3 scale_mesh = p_scale_mesh;
bool flip_faces = false;
//bool flip_faces = p_options["force/flip_faces"];
//bool force_smooth = p_options["force/smooth_shading"];
@@ -227,9 +228,9 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p
Vector<String> v = l.split(" ", false);
ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
Vector3 vtx;
- vtx.x = v[1].to_float();
- vtx.y = v[2].to_float();
- vtx.z = v[3].to_float();
+ vtx.x = v[1].to_float() * scale_mesh.x;
+ vtx.y = v[2].to_float() * scale_mesh.y;
+ vtx.z = v[3].to_float() * scale_mesh.z;
vertices.push_back(vtx);
} else if (l.begins_with("vt ")) {
//uv
@@ -401,7 +402,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
List<Ref<Mesh> > meshes;
- Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, r_missing_deps);
+ Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, Vector3(1, 1, 1), r_missing_deps);
if (err != OK) {
if (r_err) {
@@ -468,6 +469,7 @@ String ResourceImporterOBJ::get_preset_name(int p_idx) const {
void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1)));
}
bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
@@ -478,7 +480,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s
List<Ref<Mesh> > meshes;
- Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], NULL);
+ Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["scale_mesh"], NULL);
ERR_FAIL_COND_V(err != OK, err);
ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG);
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 060953d36a..44948b8209 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -46,6 +46,7 @@
#include "scene/resources/box_shape.h"
#include "scene/resources/plane_shape.h"
#include "scene/resources/ray_shape.h"
+#include "scene/resources/scene_format_text.h"
#include "scene/resources/sphere_shape.h"
uint32_t EditorSceneImporter::get_import_flags() const {
@@ -1395,3 +1396,25 @@ ResourceImporterScene *ResourceImporterScene::singleton = NULL;
ResourceImporterScene::ResourceImporterScene() {
singleton = this;
}
+///////////////////////////////////////
+
+uint32_t EditorSceneImporterESCN::get_import_flags() const {
+ return IMPORT_SCENE;
+}
+void EditorSceneImporterESCN::get_extensions(List<String> *r_extensions) const {
+ r_extensions->push_back("escn");
+}
+Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+
+ Error error;
+ Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error);
+ ERR_FAIL_COND_V(!ps.is_valid(), NULL);
+
+ Node *scene = ps->instance();
+ ERR_FAIL_COND_V(!scene, NULL);
+
+ return scene;
+}
+Ref<Animation> EditorSceneImporterESCN::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
+ ERR_FAIL_V(Ref<Animation>());
+}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index d5f9d53e91..9c3ec7a29b 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -155,4 +155,14 @@ public:
ResourceImporterScene();
};
+class EditorSceneImporterESCN : public EditorSceneImporter {
+ GDCLASS(EditorSceneImporterESCN, EditorSceneImporter);
+
+public:
+ virtual uint32_t get_import_flags() const;
+ virtual void get_extensions(List<String> *r_extensions) const;
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
+};
+
#endif // RESOURCEIMPORTERSCENE_H
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 915132c75c..26afc78825 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -308,7 +308,7 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
preview_hb->set_v_size_flags(SIZE_EXPAND_FILL);
previews->add_child(preview_hb);
- get_ok()->set_text(TTR("Install"));
+ get_ok()->set_text(TTR("Download"));
get_cancel()->set_text(TTR("Close"));
}
///////////////////////////////////////////////////////////////////////////////////
@@ -316,7 +316,6 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) {
String error_text;
- print_line("COMPLETED: " + itos(p_status) + " code: " + itos(p_code) + " data size: " + itos(p_data.size()));
switch (p_status) {
@@ -371,7 +370,6 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
progress->set_max(download->get_body_size());
progress->set_value(download->get_downloaded_bytes());
- print_line("max: " + itos(download->get_body_size()) + " bytes: " + itos(download->get_downloaded_bytes()));
install->set_disabled(false);
progress->set_value(download->get_downloaded_bytes());
@@ -747,8 +745,6 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (p_status == HTTPRequest::RESULT_SUCCESS) {
- print_line("GOT IMAGE YAY!");
-
if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
for (int i = 0; i < headers.size(); i++) {
if (headers[i].findn("ETag:") == 0) { // Save etag
@@ -811,7 +807,6 @@ void EditorAssetLibrary::_update_image_queue() {
}
}
- print_line("REQUEST ICON FOR: " + itos(E->get().asset_id));
Error err = E->get().request->request(E->get().image_url, headers);
if (err != OK) {
to_delete.push_back(E->key());
@@ -855,7 +850,6 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, String p_image_url, Imag
void EditorAssetLibrary::_repository_changed(int p_repository_id) {
host = repository->get_item_metadata(p_repository_id);
- print_line(".." + host);
if (templates_only) {
_api_request("configure", REQUESTING_CONFIG, "?type=project");
} else {
@@ -1066,8 +1060,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
return;
}
- print_line("response: " + itos(p_status) + " code: " + itos(p_code));
-
Dictionary d;
{
Variant js;
@@ -1077,8 +1069,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
d = js;
}
- print_line(Variant(d).get_construct_string());
-
RequestType requested = requesting;
requesting = REQUESTING_NONE;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 7d6025cb03..9680ad07e7 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -169,64 +169,10 @@ public:
}
};
-void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
- List<Node *> &selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action(TTR("Move Pivot"));
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- Node2D *n2d = Object::cast_to<Node2D>(E->get());
- if (n2d && n2d->_edit_use_pivot()) {
-
- Vector2 offset = n2d->_edit_get_pivot();
- Vector2 gpos = n2d->get_global_position();
-
- Vector2 local_mouse_pos = n2d->get_canvas_transform().affine_inverse().xform(mouse_pos);
-
- Vector2 motion_ofs = gpos - local_mouse_pos;
-
- undo_redo->add_do_method(n2d, "set_global_position", local_mouse_pos);
- undo_redo->add_do_method(n2d, "_edit_set_pivot", offset + n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs));
- undo_redo->add_undo_method(n2d, "set_global_position", gpos);
- undo_redo->add_undo_method(n2d, "_edit_set_pivot", offset);
- for (int i = 0; i < n2d->get_child_count(); i++) {
- Node2D *n2dc = Object::cast_to<Node2D>(n2d->get_child(i));
- if (!n2dc)
- continue;
-
- undo_redo->add_do_method(n2dc, "set_global_position", n2dc->get_global_position());
- undo_redo->add_undo_method(n2dc, "set_global_position", n2dc->get_global_position());
- }
- }
-
- Control *cnt = Object::cast_to<Control>(E->get());
- if (cnt) {
-
- Vector2 old_pivot = cnt->get_pivot_offset();
- Vector2 new_pivot = cnt->get_global_transform_with_canvas().affine_inverse().xform(mouse_pos);
- Vector2 old_pos = cnt->get_position();
-
- Vector2 top_pos = cnt->get_transform().get_origin(); //remember where top pos was
- cnt->set_pivot_offset(new_pivot);
- Vector2 new_top_pos = cnt->get_transform().get_origin(); //check where it is now
-
- Vector2 new_pos = old_pos - (new_top_pos - top_pos); //offset it back
-
- undo_redo->add_do_method(cnt, "set_pivot_offset", new_pivot);
- undo_redo->add_do_method(cnt, "set_position", new_pos);
- undo_redo->add_undo_method(cnt, "set_pivot_offset", old_pivot);
- undo_redo->add_undo_method(cnt, "set_position", old_pos);
- }
- }
-
- undo_redo->commit_action();
-}
-
void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius) {
float radius = p_radius / zoom;
float dist = Math::abs(p_value - p_target_snap);
- if (p_radius < 0 || dist < radius && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) {
+ if ((p_radius < 0 || dist < radius) && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) {
r_current_snap = p_target_snap;
r_snapped = true;
}
@@ -263,7 +209,6 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap,
}
Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) {
- Point2 dist[2];
bool snapped[2] = { false, false };
// Smart snap using the canvas position
@@ -271,12 +216,12 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
real_t rotation = 0.0;
if (p_canvas_item) {
- Point2 begin;
- Point2 end;
rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation();
+ // Parent sides and center
if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
- // Parent sides and center
+ Point2 begin;
+ Point2 end;
bool can_snap = false;
if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
@@ -295,23 +240,29 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
}
}
- // Self anchors (for sides)
+ // Self anchors
if ((snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
- begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
- end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
+ Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
+ Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
}
}
- // Self sides (for anchors)
+ // Self sides
if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
- begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
- end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
+ Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
+ Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
}
+
+ // Self center
+ if ((snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) {
+ Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0);
+ _snap_if_closer_point(p_target, center, output, snapped, rotation);
+ }
}
// Other nodes sides
@@ -340,11 +291,11 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
// Grid
Point2 offset = grid_offset;
if (snap_relative) {
- List<Node *> selection = editor_selection->get_selected_node_list();
+ List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
offset = Object::cast_to<Node2D>(selection[0])->get_global_position();
- } else {
- offset = _find_topleftmost_point();
+ } else if (selection.size() > 0) {
+ offset = _get_encompassing_rect_from_list(selection).position;
}
}
Point2 grid_output;
@@ -362,7 +313,6 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
}
float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
- float offset = snap_relative ? p_start : p_target;
return (snap_rotation && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
}
@@ -377,48 +327,20 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
return;
if (k->is_pressed() && !k->is_echo()) {
- if (drag_pivot_shortcut.is_valid() && drag_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) {
- //move drag pivot
- drag = DRAG_PIVOT;
- } else if (set_pivot_shortcut.is_valid() && set_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) {
- if (!Input::get_singleton()->is_mouse_button_pressed(0)) {
- List<Node *> selection = editor_selection->get_selected_node_list();
- Vector2 mouse_pos = viewport->get_local_mouse_position();
- if (selection.size() && viewport->get_rect().has_point(mouse_pos)) {
- //just in case, make it work if over viewport
- mouse_pos = transform.affine_inverse().xform(mouse_pos);
- mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item());
-
- _edit_set_pivot(mouse_pos);
- }
- }
- } else if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
+ if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
// Multiply the grid size
grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
- viewport_base->update();
viewport->update();
} else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
// Divide the grid size
Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0)
grid_step_multiplier--;
- viewport_base->update();
viewport->update();
}
}
}
-void CanvasItemEditor::_tool_select(int p_index) {
-
- ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, rotate_button, pivot_button, pan_button };
- for (int i = 0; i < TOOL_MAX; i++) {
- tb[i]->set_pressed(i == p_index);
- }
-
- viewport->update();
- tool = (Tool)p_index;
-}
-
Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
CanvasItem *ci = Object::cast_to<CanvasItem>(p_what);
@@ -428,220 +350,109 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
return memnew(CanvasItemEditorSelectedItem);
}
-Dictionary CanvasItemEditor::get_state() const {
+void CanvasItemEditor::_keying_changed() {
- Dictionary state;
- state["zoom"] = zoom;
- state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value());
- //state["ofs"]=-transform.get_origin();
- state["grid_offset"] = grid_offset;
- state["grid_step"] = grid_step;
- state["snap_rotation_offset"] = snap_rotation_offset;
- state["snap_rotation_step"] = snap_rotation_step;
- state["snap_active"] = snap_active;
- state["snap_node_parent"] = snap_node_parent;
- state["snap_node_anchors"] = snap_node_anchors;
- state["snap_node_sides"] = snap_node_sides;
- state["snap_other_nodes"] = snap_other_nodes;
- state["snap_grid"] = snap_grid;
- state["snap_guides"] = snap_guides;
- state["show_grid"] = show_grid;
- state["show_rulers"] = show_rulers;
- state["show_guides"] = show_guides;
- state["show_helpers"] = show_helpers;
- state["snap_rotation"] = snap_rotation;
- state["snap_relative"] = snap_relative;
- state["snap_pixel"] = snap_pixel;
- state["skeleton_show_bones"] = skeleton_show_bones;
- return state;
+ if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree())
+ animation_hb->show();
+ else
+ animation_hb->hide();
}
-void CanvasItemEditor::set_state(const Dictionary &p_state) {
- Dictionary state = p_state;
- if (state.has("zoom")) {
- zoom = p_state["zoom"];
- }
+Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) {
+ ERR_FAIL_COND_V(p_list.empty(), Rect2());
- if (state.has("ofs")) {
- _update_scrollbars(); // i wonder how safe is calling this here..
- Point2 ofs = p_state["ofs"];
- h_scroll->set_value(ofs.x);
- v_scroll->set_value(ofs.y);
- }
-
- if (state.has("grid_offset")) {
- grid_offset = state["grid_offset"];
- }
-
- if (state.has("grid_step")) {
- grid_step = state["grid_step"];
- }
-
- if (state.has("snap_rotation_step")) {
- snap_rotation_step = state["snap_rotation_step"];
- }
-
- if (state.has("snap_rotation_offset")) {
- snap_rotation_offset = state["snap_rotation_offset"];
- }
+ // Handles the first element
+ CanvasItem *canvas_item = p_list.front()->get();
+ Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2());
- if (state.has("snap_active")) {
- snap_active = state["snap_active"];
- snap_button->set_pressed(snap_active);
- }
-
- if (state.has("snap_node_parent")) {
- snap_node_parent = state["snap_node_parent"];
- int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
- smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
- }
-
- if (state.has("snap_node_anchors")) {
- snap_node_anchors = state["snap_node_anchors"];
- int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
- smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
- }
-
- if (state.has("snap_node_sides")) {
- snap_node_sides = state["snap_node_sides"];
- int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
- smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
- }
-
- if (state.has("snap_other_nodes")) {
- snap_other_nodes = state["snap_other_nodes"];
- int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
- smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
- }
-
- if (state.has("snap_guides")) {
- snap_guides = state["snap_guides"];
- int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
- smartsnap_config_popup->set_item_checked(idx, snap_guides);
- }
-
- if (state.has("snap_grid")) {
- snap_grid = state["snap_grid"];
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
- }
-
- if (state.has("show_grid")) {
- show_grid = state["show_grid"];
- int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
- view_menu->get_popup()->set_item_checked(idx, show_grid);
- }
-
- if (state.has("show_rulers")) {
- show_rulers = state["show_rulers"];
- int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
- view_menu->get_popup()->set_item_checked(idx, show_rulers);
+ // Handles the other ones
+ for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ Rect2 current_rect = canvas_item->_edit_get_rect();
+ Transform2D xform = canvas_item->get_global_transform_with_canvas();
+ rect.expand_to(xform.xform(current_rect.position));
+ rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0)));
+ rect.expand_to(xform.xform(current_rect.position + current_rect.size));
+ rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y)));
}
- if (state.has("show_guides")) {
- show_guides = state["show_guides"];
- int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
- view_menu->get_popup()->set_item_checked(idx, show_guides);
- }
+ return rect;
+}
- if (state.has("show_helpers")) {
- show_helpers = state["show_helpers"];
- int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
- view_menu->get_popup()->set_item_checked(idx, show_helpers);
- }
+void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
+ if (!p_node)
+ return;
+ if (Object::cast_to<Viewport>(p_node))
+ return;
- if (state.has("snap_rotation")) {
- snap_rotation = state["snap_rotation"];
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
- }
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
- if (state.has("snap_relative")) {
- snap_relative = state["snap_relative"];
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
- }
+ bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != "";
+ bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
+ bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
- if (state.has("snap_pixel")) {
- snap_pixel = state["snap_pixel"];
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
+ if (!lock_children && (!inherited || editable)) {
+ for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
+ if (canvas_item && !canvas_item->is_set_as_toplevel()) {
+ _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
+ } else {
+ CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
+ _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
+ }
+ }
}
- if (state.has("skeleton_show_bones")) {
- skeleton_show_bones = state["skeleton_show_bones"];
- int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
+ if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
+ Rect2 rect = canvas_item->_edit_get_rect();
+ Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
+ if (r_first) {
+ r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2());
+ r_first = false;
+ }
+ r_rect.expand_to(xform.xform(rect.position));
+ r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
+ r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
+ r_rect.expand_to(xform.xform(rect.position + rect.size));
}
-
- viewport->update();
-}
-
-void CanvasItemEditor::_add_canvas_item(CanvasItem *p_canvas_item) {
-
- editor_selection->add_node(p_canvas_item);
-}
-
-void CanvasItemEditor::_remove_canvas_item(CanvasItem *p_canvas_item) {
-
- editor_selection->remove_node(p_canvas_item);
-}
-void CanvasItemEditor::_clear_canvas_items() {
-
- editor_selection->clear();
}
-void CanvasItemEditor::_keying_changed() {
-
- if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree())
- animation_hb->show();
- else
- animation_hb->hide();
-}
-
-bool CanvasItemEditor::_is_part_of_subscene(CanvasItem *p_item) {
-
- Node *scene_node = get_tree()->get_edited_scene_root();
- Node *item_owner = p_item->get_owner();
-
- return item_owner && item_owner != scene_node && p_item != scene_node && item_owner->get_filename() != "";
+Rect2 CanvasItemEditor::_get_scene_encompassing_rect() {
+ Rect2 rect;
+ bool first = true;
+ _expand_encompassing_rect_using_children(rect, editor->get_edited_scene(), first);
+ return rect;
}
-void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit) {
+void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
if (Object::cast_to<Viewport>(p_node))
return;
const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
- CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_at_pos(p_pos, p_node->get_child(i), p_parent_xform * c->get_transform(), p_canvas_xform, r_items);
+ if (canvas_item && !canvas_item->is_set_as_toplevel())
+ _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
- _find_canvas_items_at_pos(p_pos, p_node->get_child(i), transform, cl ? cl->get_transform() : p_canvas_xform, r_items); //use base transform
+ _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); //use base transform
}
-
if (limit != 0 && r_items.size() >= limit)
return;
}
- if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) {
+ if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
- Rect2 rect = c->_edit_get_rect();
- Transform2D to_local = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse();
- Point2 local_pos = to_local.xform(p_pos);
- const real_t local_grab_distance = (to_local.xform(p_pos + Vector2(grab_distance, 0)) - local_pos).length();
- Rect2 local_pos_rect = Rect2(local_pos, Vector2(0, 0)).grow(local_grab_distance);
+ Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse();
+ const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length();
- if (rect.intersects(local_pos_rect) && c->_edit_is_selected_on_click(local_pos, local_grab_distance)) {
- Node2D *node = Object::cast_to<Node2D>(c);
+ if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) {
+ Node2D *node = Object::cast_to<Node2D>(canvas_item);
_SelectResult res;
- res.item = c;
+ res.item = canvas_item;
res.z_index = node ? node->get_z_index() : 0;
res.has_z = node;
r_items.push_back(res);
@@ -651,64 +462,45 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
return;
}
-void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, List<CanvasItem *> *r_items) {
-
+void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
if (Object::cast_to<Viewport>(p_node))
return;
- CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != "";
- bool editable = false;
- if (inherited) {
- editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
- }
+ bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
+
if (!lock_children && (!inherited || editable)) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_at_rect(p_rect, p_node->get_child(i), p_parent_xform * c->get_transform(), p_canvas_xform, r_items);
- else {
- CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
- _find_canvas_items_at_rect(p_rect, p_node->get_child(i), transform, cl ? cl->get_transform() : p_canvas_xform, r_items);
+ if (canvas_item && !canvas_item->is_set_as_toplevel()) {
+ _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
+ } else {
+ CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
+ _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
}
}
}
- if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) {
+ if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
- Rect2 rect = c->_edit_get_rect();
- Transform2D xform = p_parent_xform * p_canvas_xform * c->get_transform();
+ Rect2 rect = canvas_item->_edit_get_rect();
+ Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
if (p_rect.has_point(xform.xform(rect.position)) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) {
- r_items->push_back(c);
+ r_items->push_back(canvas_item);
}
}
}
-void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_append, bool p_box_selection) {
- if (!p_append) {
- editor_selection->clear();
- viewport->update();
- viewport_base->update();
- };
-
- if (p_box_selection) {
- // Start a box selection
- drag_from = transform.affine_inverse().xform(p_click_pos);
- box_selecting = true;
- box_selecting_to = drag_from;
- }
-}
-
-bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag) {
+bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) {
bool still_selected = true;
if (p_append) {
if (editor_selection->is_selected(item)) {
@@ -717,7 +509,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po
still_selected = false;
} else {
// Add the item to the selection
- _append_canvas_item(item);
+ editor_selection->add_node(item);
}
} else {
if (!editor_selection->is_selected(item)) {
@@ -730,216 +522,33 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po
}
}
}
-
- if (still_selected && p_drag) {
- // Drag the node(s) if requested
- _prepare_drag(p_click_pos);
- }
-
viewport->update();
- viewport_base->update();
return still_selected;
}
-void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode) {
-
- if (drag != DRAG_NONE)
- return;
-
- if (editor_selection->get_selected_node_list().empty())
- return;
-
- undo_redo->create_action(TTR("Move Action"), UndoRedo::MERGE_ENDS);
-
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- if (canvas_item->has_meta("_edit_lock_"))
- continue;
-
- Vector2 drag = p_dir;
- if (p_snap)
- drag *= grid_step * Math::pow(2.0, grid_step_multiplier);
-
- undo_redo->add_undo_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
-
- if (p_move_mode == MOVE_VIEW_BASE) {
-
- // drag = transform.affine_inverse().basis_xform(p_dir); // zoom sensitive
- drag = canvas_item->get_global_transform_with_canvas().affine_inverse().basis_xform(drag);
- Rect2 local_rect = canvas_item->_edit_get_rect();
- local_rect.position += drag;
- undo_redo->add_do_method(canvas_item, "_edit_set_rect", local_rect);
-
- } else { // p_move_mode==MOVE_LOCAL_BASE || p_move_mode==MOVE_LOCAL_WITH_ROT
-
- Node2D *node_2d = Object::cast_to<Node2D>(canvas_item);
- if (node_2d) {
-
- if (p_move_mode == MOVE_LOCAL_WITH_ROT) {
- Transform2D m;
- m.rotate(node_2d->get_rotation());
- drag = m.xform(drag);
- }
- node_2d->set_position(node_2d->get_position() + drag);
-
- } else {
- Control *control = Object::cast_to<Control>(canvas_item);
- if (control)
- control->set_position(control->get_position() + drag);
+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());
+ if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (!retreive_locked || !canvas_item->has_meta("_edit_lock_"))) {
+ CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (se) {
+ selection.push_back(canvas_item);
}
}
}
- undo_redo->commit_action();
-}
-
-Point2 CanvasItemEditor::_find_topleftmost_point() {
-
- Vector2 tl = Point2(1e10, 1e10);
- Rect2 r2;
- r2.position = tl;
-
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- Rect2 rect = canvas_item->_edit_get_rect();
- Transform2D xform = canvas_item->get_global_transform_with_canvas();
-
- r2.expand_to(xform.xform(rect.position));
- r2.expand_to(xform.xform(rect.position + Vector2(rect.size.x, 0)));
- r2.expand_to(xform.xform(rect.position + rect.size));
- r2.expand_to(xform.xform(rect.position + Vector2(0, rect.size.y)));
- }
-
- return r2.position;
-}
-
-int CanvasItemEditor::get_item_count() {
-
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- int ic = 0;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- ic++;
- };
-
- return ic;
-}
-
-CanvasItem *CanvasItemEditor::_get_single_item() {
-
- Map<Node *, Object *> &selection = editor_selection->get_selection();
-
- CanvasItem *single_item = NULL;
-
- for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (single_item)
- return NULL; //morethan one
-
- single_item = canvas_item;
- };
-
- return single_item;
-}
-
-CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
- // Returns a drag type if a resize handle is clicked
- CanvasItem *canvas_item = _get_single_item();
-
- ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
-
- Rect2 rect = canvas_item->_edit_get_rect();
- Transform2D xforml = canvas_item->get_global_transform_with_canvas();
- Transform2D xform = transform * xforml;
-
- Vector2 endpoints[4] = {
-
- xform.xform(rect.position),
- xform.xform(rect.position + Vector2(rect.size.x, 0)),
- xform.xform(rect.position + rect.size),
- xform.xform(rect.position + Vector2(0, rect.size.y))
- };
-
- Vector2 endpointsl[4] = {
-
- xforml.xform(rect.position),
- xforml.xform(rect.position + Vector2(rect.size.x, 0)),
- xforml.xform(rect.position + rect.size),
- xforml.xform(rect.position + Vector2(0, rect.size.y))
- };
-
- DragType dragger[] = {
- DRAG_TOP_LEFT,
- DRAG_TOP,
- DRAG_TOP_RIGHT,
- DRAG_RIGHT,
- DRAG_BOTTOM_RIGHT,
- DRAG_BOTTOM,
- DRAG_BOTTOM_LEFT,
- DRAG_LEFT
- };
-
- float radius = (select_handle->get_size().width / 2) * 1.5;
-
- for (int i = 0; i < 4; i++) {
-
- int prev = (i + 3) % 4;
- int next = (i + 1) % 4;
-
- r_point = endpointsl[i];
-
- Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
- ofs *= 1.4144 * (select_handle->get_size().width / 2);
-
- ofs += endpoints[i];
-
- if (ofs.distance_to(p_click) < radius)
- return dragger[i * 2];
-
- ofs = (endpoints[i] + endpoints[next]) / 2;
- ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
-
- r_point = (endpointsl[i] + endpointsl[next]) / 2;
-
- if (ofs.distance_to(p_click) < radius)
- return dragger[i * 2 + 1];
+ if (remove_canvas_item_if_parent_in_selection) {
+ List<CanvasItem *> filtered_selection;
+ for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
+ if (!selection.find(E->get()->get_parent())) {
+ filtered_selection.push_back(E->get());
+ }
+ }
+ return filtered_selection;
+ } else {
+ return selection;
}
-
- return DRAG_NONE;
}
Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) {
@@ -958,148 +567,90 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
return p_control->get_transform().xform(position) / parent_size;
}
-CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
- // Returns a drag type if an anchor handle is clicked
- CanvasItem *canvas_item = _get_single_item();
- ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
-
- Control *control = Object::cast_to<Control>(canvas_item);
- ERR_FAIL_COND_V(!control, DRAG_NONE);
-
- Vector2 anchor_pos[4];
- anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
- anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
- anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
- anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
-
- Rect2 anchor_rects[4];
- for (int i = 0; i < 4; i++) {
- anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
- anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
- anchor_rects[i].position -= anchor_handle->get_size() * Vector2(i == 0 || i == 3, i <= 1);
- }
-
- DragType dragger[] = {
- DRAG_ANCHOR_TOP_LEFT,
- DRAG_ANCHOR_TOP_RIGHT,
- DRAG_ANCHOR_BOTTOM_RIGHT,
- DRAG_ANCHOR_BOTTOM_LEFT,
- };
+void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
+ for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (se) {
+ se->undo_state = canvas_item->_edit_get_state();
+ se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
+ se->pre_drag_rect = canvas_item->_edit_get_rect();
+
+ se->pre_drag_bones_length = List<float>();
+ se->pre_drag_bones_undo_state = List<Dictionary>();
+
+ // If we have a bone, save the state of all nodes in the IK chain
+ Node2D *bone = Object::cast_to<Node2D>(canvas_item);
+ if (bone && bone->has_meta("_edit_bone_")) {
+ // Check if we have an IK chain
+ List<Node2D *> bone_ik_list;
+ bool ik_found;
+ bone = Object::cast_to<Node2D>(bone->get_parent());
+ while (bone) {
+ bone_ik_list.push_back(bone);
+ if (bone->has_meta("_edit_ik_")) {
+ ik_found = true;
+ break;
+ } else if (!bone->has_meta("_edit_bone_")) {
+ break;
+ }
+ bone = Object::cast_to<Node2D>(bone->get_parent());
+ }
- for (int i = 0; i < 4; i++) {
- if (anchor_rects[i].has_point(p_click)) {
- r_point = transform.affine_inverse().xform(anchor_pos[i]);
- if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(p_click) < anchor_handle->get_size().length() / 3.0)) {
- return DRAG_ANCHOR_ALL;
- } else {
- return dragger[i];
+ //Save the bone state and lenght if we have an IK chain
+ if (ik_found) {
+ bone = Object::cast_to<Node2D>(canvas_item);
+ Transform2D bone_xform = bone->get_global_transform();
+ for (List<Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) {
+ bone_xform = bone_xform * bone->get_transform().affine_inverse();
+ Node2D *parent_bone = bone_E->get();
+ se->pre_drag_bones_length.push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position()));
+ se->pre_drag_bones_undo_state.push_back(parent_bone->_edit_get_state());
+ bone = parent_bone;
+ }
+ }
}
}
}
-
- return DRAG_NONE;
}
-void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) {
-
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
+void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) {
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- se->undo_state = canvas_item->_edit_get_state();
- if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
- if (Object::cast_to<Control>(canvas_item))
- se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
-
- se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->_edit_get_rect();
- }
-
- if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0]) && bone_ik_list.size() == 0) {
- drag = DRAG_NODE_2D;
- drag_point_from = Object::cast_to<Node2D>(selection[0])->get_global_position();
- } else {
- drag = DRAG_ALL;
- drag_point_from = _find_topleftmost_point();
- }
- drag_from = transform.affine_inverse().xform(p_click_pos);
-}
-
-void CanvasItemEditor::incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric) {
-
- if (minsize < 0) {
-
- beg += inc;
- if (p_symmetric)
- end -= inc;
- } else {
-
- if (p_symmetric) {
- beg += inc;
- end -= inc;
- if (end - beg < minsize) {
- float center = (beg + end) / 2.0;
- beg = center - minsize / 2.0;
- end = center + minsize / 2.0;
+ canvas_item->_edit_set_state(se->undo_state);
+ if (restore_bones) {
+ for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) {
+ canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
+ canvas_item->_edit_set_state(E->get());
}
-
- } else {
- if (end - (beg + inc) < minsize)
- beg = end - minsize;
- else
- beg += inc;
}
}
}
-void CanvasItemEditor::incend(float &beg, float &end, float inc, float minsize, bool p_symmetric) {
-
- if (minsize < 0) {
-
- end += inc;
- if (p_symmetric)
- beg -= inc;
- } else {
-
- if (p_symmetric) {
-
- end += inc;
- beg -= inc;
- if (end - beg < minsize) {
- float center = (beg + end) / 2.0;
- beg = center - minsize / 2.0;
- end = center + minsize / 2.0;
+void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) {
+ undo_redo->create_action(action_name);
+ for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
+ if (commit_bones) {
+ for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) {
+ canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
+ undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", E->get());
}
-
- } else {
- if ((end + inc) - beg < minsize)
- end = beg + minsize;
- else
- end += inc;
}
}
-}
-
-void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) {
-
- editor_selection->add_node(p_item);
+ undo_redo->add_do_method(viewport, "update");
+ undo_redo->add_undo_method(viewport, "update");
+ undo_redo->commit_action();
}
void CanvasItemEditor::_snap_changed() {
((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
grid_step_multiplier = 0;
- viewport_base->update();
viewport->update();
}
@@ -1111,7 +662,7 @@ void CanvasItemEditor::_selection_result_pressed(int p_result) {
CanvasItem *item = selection_results[p_result].item;
if (item)
- _select_click_on_item(item, Point2(), additive_selection, false);
+ _select_click_on_item(item, Point2(), selection_menu_additive_selection);
}
void CanvasItemEditor::_selection_menu_hide() {
@@ -1121,124 +672,16 @@ void CanvasItemEditor::_selection_menu_hide() {
selection_menu->set_size(Vector2(0, 0));
}
-void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
-
- Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
-
- Node *scene = editor->get_edited_scene();
- if (!scene)
- return;
-
- _find_canvas_items_at_pos(click, scene, transform, Transform2D(), selection_results);
-
- for (int i = 0; i < selection_results.size(); i++) {
- CanvasItem *item = selection_results[i].item;
- if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) {
- //invalid result
- selection_results.remove(i);
- i--;
- }
- }
-
- if (selection_results.size() == 1) {
-
- CanvasItem *item = selection_results[0].item;
- selection_results.clear();
-
- additive_selection = b->get_shift();
-
- if (!_select_click_on_item(item, click, additive_selection, false))
- return;
-
- } else if (!selection_results.empty()) {
-
- selection_results.sort();
-
- NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
- StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
-
- for (int i = 0; i < selection_results.size(); i++) {
-
- CanvasItem *item = selection_results[i].item;
-
- Ref<Texture> icon;
- if (item->has_meta("_editor_icon"))
- icon = item->get_meta("_editor_icon");
- else
- icon = get_icon(has_icon(item->get_class(), "EditorIcons") ? item->get_class() : String("Object"), "EditorIcons");
-
- String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path());
-
- selection_menu->add_item(item->get_name());
- selection_menu->set_item_icon(i, icon);
- selection_menu->set_item_metadata(i, node_path);
- selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path);
- }
-
- additive_selection = b->get_shift();
-
- selection_menu->set_global_position(b->get_global_position());
- selection_menu->popup();
- selection_menu->call_deferred("grab_click_focus");
- selection_menu->set_invalidate_click_until_motion();
-
- return;
- }
-}
-
-void CanvasItemEditor::_update_cursor() {
-
- CursorShape c = CURSOR_ARROW;
- switch (drag) {
- case DRAG_NONE:
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
- c = CURSOR_DRAG;
- } else {
- switch (tool) {
- case TOOL_MOVE:
- c = CURSOR_MOVE;
- break;
- case TOOL_EDIT_PIVOT:
- c = CURSOR_CROSS;
- break;
- case TOOL_PAN:
- c = CURSOR_DRAG;
- break;
- }
- }
- break;
- case DRAG_LEFT:
- case DRAG_RIGHT:
- c = CURSOR_HSIZE;
- break;
- case DRAG_TOP:
- case DRAG_BOTTOM:
- c = CURSOR_VSIZE;
- break;
- case DRAG_TOP_LEFT:
- case DRAG_BOTTOM_RIGHT:
- c = CURSOR_FDIAGSIZE;
- break;
- case DRAG_TOP_RIGHT:
- case DRAG_BOTTOM_LEFT:
- c = CURSOR_BDIAGSIZE;
- break;
- case DRAG_ALL:
- case DRAG_NODE_2D:
- c = CURSOR_MOVE;
- break;
- }
- viewport->set_default_cursor_shape(c);
-}
-
-void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) {
-
+bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
- if (b.is_valid()) {
- if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ Ref<InputEventMouseMotion> m = p_event;
+
+ // Start draging a guide
+ if (drag_type == DRAG_NONE) {
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) {
Transform2D xform = viewport_scrollable->get_transform() * transform;
- // Retrieve the guide lists
+ // Retreive the guide lists
Array vguides;
if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
@@ -1251,48 +694,64 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event)
// Press button
if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) {
// Drag a new double guide
- drag = DRAG_DOUBLE_GUIDE;
- edited_guide_index = -1;
+ drag_type = DRAG_DOUBLE_GUIDE;
+ dragged_guide_index = -1;
+ return true;
} else if (b->get_position().x < RULER_WIDTH) {
// Check if we drag an existing horizontal guide
float minimum = 1e20;
- edited_guide_index = -1;
+ dragged_guide_index = -1;
for (int i = 0; i < hguides.size(); i++) {
if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) {
- edited_guide_index = i;
+ dragged_guide_index = i;
}
}
- if (edited_guide_index >= 0) {
+ if (dragged_guide_index >= 0) {
// Drag an existing horizontal guide
- drag = DRAG_H_GUIDE;
+ drag_type = DRAG_H_GUIDE;
} else {
// Drag a new vertical guide
- drag = DRAG_V_GUIDE;
+ drag_type = DRAG_V_GUIDE;
}
+ return true;
} else if (b->get_position().y < RULER_WIDTH) {
// Check if we drag an existing vertical guide
float minimum = 1e20;
- edited_guide_index = -1;
+ dragged_guide_index = -1;
for (int i = 0; i < vguides.size(); i++) {
if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) {
- edited_guide_index = i;
+ dragged_guide_index = i;
}
}
- if (edited_guide_index >= 0) {
+ if (dragged_guide_index >= 0) {
// Drag an existing vertical guide
- drag = DRAG_V_GUIDE;
+ drag_type = DRAG_V_GUIDE;
} else {
// Drag a new vertical guide
- drag = DRAG_H_GUIDE;
+ drag_type = DRAG_H_GUIDE;
}
+ drag_from = xform.affine_inverse().xform(b->get_position());
+ return true;
}
}
}
+ }
+
+ if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE || drag_type == DRAG_H_GUIDE) {
+ // Move the guide
+ if (m.is_valid()) {
+ Transform2D xform = viewport_scrollable->get_transform() * transform;
+ drag_to = xform.affine_inverse().xform(m->get_position());
+
+ dragged_guide_pos = xform.xform(snap_point(drag_to, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES));
+ viewport->update();
+ return true;
+ }
- if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
- // Release button
+ // Release confirms the guide move
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
if (show_guides && EditorNode::get_singleton()->get_edited_scene()) {
Transform2D xform = viewport_scrollable->get_transform() * transform;
@@ -1307,65 +766,65 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event)
}
Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES);
- if (drag == DRAG_V_GUIDE) {
+ if (drag_type == DRAG_V_GUIDE) {
Array prev_vguides = vguides.duplicate();
if (b->get_position().x > RULER_WIDTH) {
// Adds a new vertical guide
- if (edited_guide_index >= 0) {
- vguides[edited_guide_index] = edited.x;
+ if (dragged_guide_index >= 0) {
+ vguides[dragged_guide_index] = edited.x;
undo_redo->create_action(TTR("Move vertical guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
} else {
vguides.push_back(edited.x);
undo_redo->create_action(TTR("Create new vertical guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
}
} else {
- if (edited_guide_index >= 0) {
- vguides.remove(edited_guide_index);
+ if (dragged_guide_index >= 0) {
+ vguides.remove(dragged_guide_index);
undo_redo->create_action(TTR("Remove vertical guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
}
}
- } else if (drag == DRAG_H_GUIDE) {
+ } else if (drag_type == DRAG_H_GUIDE) {
Array prev_hguides = hguides.duplicate();
if (b->get_position().y > RULER_WIDTH) {
// Adds a new horizontal guide
- if (edited_guide_index >= 0) {
- hguides[edited_guide_index] = edited.y;
+ if (dragged_guide_index >= 0) {
+ hguides[dragged_guide_index] = edited.y;
undo_redo->create_action(TTR("Move horizontal guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
} else {
hguides.push_back(edited.y);
undo_redo->create_action(TTR("Create new horizontal guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
}
} else {
- if (edited_guide_index >= 0) {
- hguides.remove(edited_guide_index);
+ if (dragged_guide_index >= 0) {
+ hguides.remove(dragged_guide_index);
undo_redo->create_action(TTR("Remove horizontal guide"));
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
}
}
- } else if (drag == DRAG_DOUBLE_GUIDE) {
+ } else if (drag_type == DRAG_DOUBLE_GUIDE) {
Array prev_hguides = hguides.duplicate();
Array prev_vguides = vguides.duplicate();
if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) {
@@ -1377,96 +836,22 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event)
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
- undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
}
}
}
- if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE || drag == DRAG_H_GUIDE) {
- drag = DRAG_NONE;
- viewport_base->update();
- }
- }
- }
-
- Ref<InputEventMouseMotion> m = p_event;
- if (m.is_valid()) {
- if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
- viewport_base->call_deferred("grab_focus");
- }
- if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE || drag == DRAG_V_GUIDE) {
- Transform2D xform = viewport_scrollable->get_transform() * transform;
- Point2 mouse_pos = m->get_position();
- mouse_pos = xform.affine_inverse().xform(mouse_pos);
- mouse_pos = xform.xform(snap_point(mouse_pos, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES));
-
- edited_guide_pos = mouse_pos;
- viewport_base->update();
- }
- }
-
- Ref<InputEventKey> k = p_event;
- if (k.is_valid()) {
- if (k->is_pressed() && drag == DRAG_NONE) {
- // Move the object with the arrow keys
- KeyMoveMODE move_mode = MOVE_VIEW_BASE;
- if (k->get_alt()) move_mode = MOVE_LOCAL_BASE;
- if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT;
-
- if (k->get_scancode() == KEY_UP)
- _key_move(Vector2(0, -1), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_DOWN)
- _key_move(Vector2(0, 1), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_LEFT)
- _key_move(Vector2(-1, 0), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_RIGHT)
- _key_move(Vector2(1, 0), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_ESCAPE) {
- editor_selection->clear();
- viewport->update();
- } else
- return;
-
- accept_event();
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
}
}
+ return false;
}
-void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
-
- {
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty()) {
- bool discard = over_plugin_list->forward_gui_input(p_event);
- if (discard) {
- accept_event();
- return;
- }
- }
- }
-
- Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
- if (magnify_gesture.is_valid()) {
-
- _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
- return;
- }
-
- Ref<InputEventPanGesture> pan_gesture = p_event;
- if (pan_gesture.is_valid()) {
-
- const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
- h_scroll->set_value(h_scroll->get_value() + delta.x);
- v_scroll->set_value(v_scroll->get_value() + delta.y);
- return;
- }
-
+bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
- // Button event
-
if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
// Scroll or pan down
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
@@ -1476,8 +861,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
} else {
_zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position());
}
-
- return;
+ return true;
}
if (b->get_button_index() == BUTTON_WHEEL_UP) {
@@ -1489,768 +873,988 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
} else {
_zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position());
}
-
- return;
+ return true;
}
if (b->get_button_index() == BUTTON_WHEEL_LEFT) {
// Pan left
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
-
h_scroll->set_value(h_scroll->get_value() - int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor());
+ return true;
}
}
if (b->get_button_index() == BUTTON_WHEEL_RIGHT) {
// Pan right
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
-
h_scroll->set_value(h_scroll->get_value() + int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor());
+ return true;
}
}
+ }
- if (b->get_button_index() == BUTTON_RIGHT) {
+ Ref<InputEventMouseMotion> m = p_event;
+ if (m.is_valid()) {
+ if (drag_type == DRAG_NONE) {
+ if (((m->get_button_mask() & BUTTON_MASK_LEFT) && tool == TOOL_PAN) ||
+ (m->get_button_mask() & BUTTON_MASK_MIDDLE) ||
+ ((m->get_button_mask() & BUTTON_MASK_LEFT) && Input::get_singleton()->is_key_pressed(KEY_SPACE)) ||
+ (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ // Pan the viewport
+ Point2i relative;
+ if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
+ relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
+ } else {
+ relative = m->get_relative();
+ }
- if (b->is_pressed() && (tool == TOOL_SELECT && b->get_alt())) {
- // Open the selection list
- _list_select(b);
- return;
+ h_scroll->set_value(h_scroll->get_value() - relative.x / zoom);
+ v_scroll->set_value(v_scroll->get_value() - relative.y / zoom);
+ return true;
}
+ }
+ }
- if (get_item_count() > 0 && drag != DRAG_NONE) {
- // Cancel a drag
- if (bone_ik_list.size()) {
- for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) {
- E->get().node->_edit_set_state(E->get().orig_state);
- }
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+ // Zoom gesture
+ _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
+ return true;
+ }
- bone_ik_list.clear();
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+ // Pan gesture
+ const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
+ h_scroll->set_value(h_scroll->get_value() + delta.x);
+ v_scroll->set_value(v_scroll->get_value() + delta.y);
+ return true;
+ }
- } else {
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- canvas_item->_edit_set_state(se->undo_state);
- if (Object::cast_to<Node2D>(canvas_item))
- Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot);
- if (Object::cast_to<Control>(canvas_item))
- Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot);
- }
- }
+ return false;
+}
- drag = DRAG_NONE;
- viewport->update();
- can_move_pivot = false;
+bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> m = p_event;
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventKey> k = p_event;
- } else if (box_selecting) {
- // Cancel box selection
- box_selecting = false;
- viewport->update();
+ // Drag the pivot (in pivot mode / with V key)
+ if (drag_type == DRAG_NONE) {
+ if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
+ (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V)) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+
+ // Filters the selection with nodes that allow setting the pivot
+ drag_selection = List<CanvasItem *>();
+ for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ if (canvas_item->_edit_use_pivot()) {
+ drag_selection.push_back(canvas_item);
+ }
}
- return;
- }
- if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT) {
- if (b->is_pressed())
- // Open the selection list
- _list_select(b);
- return;
- }
+ // Start dragging if we still have nodes
+ if (drag_selection.size() > 0) {
+ drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position());
+ Vector2 new_pos;
+ if (drag_selection.size() == 1)
+ new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]);
+ else
+ new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
+ }
- if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) {
- if (b->is_pressed()) {
- // Set the pivot point
- Point2 mouse_pos = b->get_position();
- mouse_pos = transform.affine_inverse().xform(mouse_pos);
- mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item());
- _edit_set_pivot(mouse_pos);
+ drag_type = DRAG_PIVOT;
+ _save_canvas_item_state(drag_selection);
}
- return;
+ return true;
}
+ }
- if (tool == TOOL_PAN || b->get_button_index() != BUTTON_LEFT || Input::get_singleton()->is_key_pressed(KEY_SPACE))
- // Pan the view
- return;
-
- // -- From now we consider that the button is BUTTON_LEFT --
+ if (drag_type == DRAG_PIVOT) {
+ // Move the pivot
+ if (m.is_valid()) {
+ drag_to = transform.affine_inverse().xform(m->get_position());
+ _restore_canvas_item_state(drag_selection);
+ Vector2 new_pos;
+ if (drag_selection.size() == 1)
+ new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]);
+ else
+ new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
+ }
+ return true;
+ }
- if (!b->is_pressed()) {
+ // Confirm the pivot move
+ if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
+ (k.is_valid() && !k->is_pressed() && k->get_scancode() == KEY_V)) {
+ _commit_canvas_item_state(drag_selection, TTR("Move pivot"));
+ drag_type = DRAG_NONE;
+ return true;
+ }
- if (drag != DRAG_NONE) {
- // Stop dragging
- if (undo_redo) {
+ // Cancel a drag
+ if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ _restore_canvas_item_state(drag_selection);
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
+ }
+ return false;
+}
- if (bone_ik_list.size()) {
- undo_redo->create_action(TTR("Edit IK Chain"));
+void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) {
+ CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node);
+ if (se && !se->pre_drag_bones_undo_state.empty()) {
+
+ // Build the node list
+ Point2 leaf_pos = target_position;
+
+ List<Node2D *> joints_list;
+ List<Point2> joints_pos;
+ Node2D *joint = leaf_node;
+ Transform2D joint_transform = leaf_node->get_global_transform_with_canvas();
+ for (int i = 0; i < se->pre_drag_bones_undo_state.size() + 1; i++) {
+ joints_list.push_back(joint);
+ joints_pos.push_back(joint_transform.get_origin());
+ joint_transform = joint_transform * joint->get_transform().affine_inverse();
+ joint = Object::cast_to<Node2D>(joint->get_parent());
+ }
+ Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin();
- for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) {
+ // Restraints the node to a maximum distance is necessary
+ float total_len = 0;
+ for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
+ total_len += E->get();
+ }
+ if ((root_pos.distance_to(leaf_pos)) > total_len) {
+ Vector2 rel = leaf_pos - root_pos;
+ rel = rel.normalized() * total_len;
+ leaf_pos = root_pos + rel;
+ }
+ joints_pos[0] = leaf_pos;
+
+ // Run the solver
+ int solver_iterations = 64;
+ float solver_k = 0.3;
+
+ // Build the position list
+ for (int i = 0; i < solver_iterations; i++) {
+ // Handle the leaf joint
+ int node_id = 0;
+ for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
+ Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized();
+ int len = E->get();
+ if (E == se->pre_drag_bones_length.front()) {
+ joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k);
+ } else if (E == se->pre_drag_bones_length.back()) {
+ joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k);
+ } else {
+ Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0;
+ joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k);
+ joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k);
+ }
+ node_id++;
+ }
+ }
- undo_redo->add_do_method(E->get().node, "_edit_set_state", E->get().node->_edit_get_state());
- undo_redo->add_undo_method(E->get().node, "_edit_set_state", E->get().orig_state);
- }
+ // Set the position
+ float total_rot = 0.0f;
+ for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) {
+ Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized();
+ Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized();
+ float rot = current.angle_to(target);
+ if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) {
+ rot = -rot;
+ }
+ joints_list[node_id]->rotate(rot);
+ total_rot += rot;
+ }
- undo_redo->add_do_method(viewport, "update");
- undo_redo->add_undo_method(viewport, "update");
+ joints_list[0]->rotate(-total_rot);
+ }
+}
- bone_ik_list.clear();
+bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventMouseMotion> m = p_event;
- undo_redo->commit_action();
- } else {
- undo_redo->create_action(TTR("Edit CanvasItem"));
-
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- Variant state = canvas_item->_edit_get_state();
- undo_redo->add_do_method(canvas_item, "_edit_set_state", state);
- undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
- {
- Node2D *pvt = Object::cast_to<Node2D>(canvas_item);
- if (pvt && pvt->_edit_use_pivot()) {
- undo_redo->add_do_method(canvas_item, "_edit_set_pivot", pvt->_edit_get_pivot());
- undo_redo->add_undo_method(canvas_item, "_edit_set_pivot", se->undo_pivot);
- }
-
- Control *cnt = Object::cast_to<Control>(canvas_item);
- if (cnt) {
- undo_redo->add_do_method(canvas_item, "set_pivot_offset", cnt->get_pivot_offset());
- undo_redo->add_undo_method(canvas_item, "set_pivot_offset", se->undo_pivot);
- }
- }
- }
- undo_redo->commit_action();
- }
+ // Start rotation
+ if (drag_type == DRAG_NONE) {
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ drag_selection = _get_edited_canvas_items();
+ if (drag_selection.size() > 0 && ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE)) {
+ drag_type = DRAG_ROTATE;
+ drag_from = transform.affine_inverse().xform(b->get_position());
+ CanvasItem *canvas_item = drag_selection[0];
+ if (canvas_item->_edit_use_pivot()) {
+ drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot());
+ } else {
+ drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin();
}
+ _save_canvas_item_state(drag_selection);
+ return true;
+ }
+ }
+ }
- drag = DRAG_NONE;
+ if (drag_type == DRAG_ROTATE) {
+ // Rotate the node
+ if (m.is_valid()) {
+ _restore_canvas_item_state(drag_selection);
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ drag_to = transform.affine_inverse().xform(m->get_position());
+ canvas_item->_edit_set_rotation(snap_angle(canvas_item->_edit_get_rotation() + (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), canvas_item->_edit_get_rotation()));
viewport->update();
- can_move_pivot = false;
}
+ return true;
+ }
- if (box_selecting) {
- // Stop box selection
- Node *scene = editor->get_edited_scene();
- if (scene) {
-
- List<CanvasItem *> selitems;
-
- Point2 bsfrom = transform.xform(drag_from);
- Point2 bsto = transform.xform(box_selecting_to);
- if (bsfrom.x > bsto.x)
- SWAP(bsfrom.x, bsto.x);
- if (bsfrom.y > bsto.y)
- SWAP(bsfrom.y, bsto.y);
-
- _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, transform, Transform2D(), &selitems);
+ // Confirms the node rotation
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ _commit_canvas_item_state(drag_selection, TTR("Rotate CanvasItem"));
+ drag_type = DRAG_NONE;
+ return true;
+ }
- for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
+ // Cancel a drag
+ if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ _restore_canvas_item_state(drag_selection);
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
+ }
+ return false;
+}
- _append_canvas_item(E->get());
- }
- }
+bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
- box_selecting = false;
- viewport->update();
+ // Open a sub-scene on double-click
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (selection.size() == 1) {
+ CanvasItem *canvas_item = selection[0];
+ if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) {
+ editor->open_request(canvas_item->get_filename());
+ return true;
}
- return;
}
+ }
+ return false;
+}
- // -- From now we consider that the button is BUTTON_LEFT and that it is pressed --
+bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventMouseMotion> m = p_event;
- Map<ObjectID, BoneList>::Element *Cbone = NULL; //closest
+ // Starts anchor dragging if needed
+ if (drag_type == DRAG_NONE) {
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT && show_helpers) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (selection.size() == 1) {
+ Control *control = Object::cast_to<Control>(selection[0]);
+ if (control && !Object::cast_to<Container>(control->get_parent())) {
+ Vector2 anchor_pos[4];
+ anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
+ anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
+ anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
+ anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
- {
- bone_ik_list.clear();
- float closest_dist = 1e20;
- int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
- for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+ Rect2 anchor_rects[4];
+ for (int i = 0; i < 4; i++) {
+ anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
+ anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
+ anchor_rects[i].position -= anchor_handle->get_size() * Vector2(i == 0 || i == 3, i <= 1);
+ }
- if (E->get().from == E->get().to)
- continue;
- Vector2 s[2] = {
- E->get().from,
- E->get().to
- };
+ DragType dragger[] = {
+ DRAG_ANCHOR_TOP_LEFT,
+ DRAG_ANCHOR_TOP_RIGHT,
+ DRAG_ANCHOR_BOTTOM_RIGHT,
+ DRAG_ANCHOR_BOTTOM_LEFT,
+ };
- Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s);
- float d = p.distance_to(b->get_position());
- if (d < bone_width && d < closest_dist) {
- Cbone = E;
- closest_dist = d;
+ for (int i = 0; i < 4; i++) {
+ if (anchor_rects[i].has_point(b->get_position())) {
+ if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(b->get_position()) < anchor_handle->get_size().length() / 3.0)) {
+ drag_type = DRAG_ANCHOR_ALL;
+ } else {
+ drag_type = dragger[i];
+ }
+ drag_from = transform.affine_inverse().xform(b->get_position());
+ drag_selection = List<CanvasItem *>();
+ drag_selection.push_back(control);
+ _save_canvas_item_state(drag_selection);
+ return true;
+ }
+ }
}
}
+ }
+ }
- if (Cbone) {
- Node2D *b = Object::cast_to<Node2D>(ObjectDB::get_instance(Cbone->get().bone));
+ if (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT || drag_type == DRAG_ANCHOR_ALL) {
+ // Drag the anchor
+ if (m.is_valid()) {
+ _restore_canvas_item_state(drag_selection);
+ Control *control = Object::cast_to<Control>(drag_selection[0]);
- if (b) {
+ drag_to = transform.affine_inverse().xform(m->get_position());
- bool ik_found = false;
+ Transform2D xform = control->get_global_transform_with_canvas().affine_inverse();
- bool first = true;
+ Point2 previous_anchor;
+ previous_anchor.x = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT) ? control->get_anchor(MARGIN_LEFT) : control->get_anchor(MARGIN_RIGHT);
+ previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(MARGIN_TOP) : control->get_anchor(MARGIN_BOTTOM);
+ previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor));
- while (b) {
+ Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, control, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER));
+ new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001));
- CanvasItem *pi = b->get_parent_item();
- if (!pi)
- break;
+ bool use_single_axis = m->get_shift();
+ Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from);
+ bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
- float len = pi->get_global_transform().get_origin().distance_to(b->get_global_position());
- b = Object::cast_to<Node2D>(pi);
- if (!b)
- break;
+ switch (drag_type) {
+ case DRAG_ANCHOR_TOP_LEFT:
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
+ break;
+ case DRAG_ANCHOR_TOP_RIGHT:
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
+ break;
+ case DRAG_ANCHOR_BOTTOM_RIGHT:
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
+ break;
+ case DRAG_ANCHOR_BOTTOM_LEFT:
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
+ break;
+ case DRAG_ANCHOR_ALL:
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
+ if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
+ if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
- if (first) {
+ // Confirms new anchor position
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ _commit_canvas_item_state(drag_selection, TTR("Move anchor"));
+ drag_type = DRAG_NONE;
+ return true;
+ }
- bone_orig_xform = b->get_global_transform();
- first = false;
- }
+ // Cancel a drag
+ if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ _restore_canvas_item_state(drag_selection);
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
+ }
+ return false;
+}
- BoneIK bik;
- bik.node = b;
- bik.len = len;
- bik.orig_state = b->_edit_get_state();
+bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventMouseMotion> m = p_event;
- bone_ik_list.push_back(bik);
+ // Drag resize handles
+ if (drag_type == DRAG_NONE) {
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (selection.size() == 1) {
+ CanvasItem *canvas_item = selection[0];
+
+ Rect2 rect = canvas_item->_edit_get_rect();
+ Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
+
+ Vector2 endpoints[4] = {
+ xform.xform(rect.position),
+ xform.xform(rect.position + Vector2(rect.size.x, 0)),
+ xform.xform(rect.position + rect.size),
+ xform.xform(rect.position + Vector2(0, rect.size.y))
+ };
- if (b->has_meta("_edit_ik_")) {
+ DragType dragger[] = {
+ DRAG_TOP_LEFT,
+ DRAG_TOP,
+ DRAG_TOP_RIGHT,
+ DRAG_RIGHT,
+ DRAG_BOTTOM_RIGHT,
+ DRAG_BOTTOM,
+ DRAG_BOTTOM_LEFT,
+ DRAG_LEFT
+ };
- ik_found = bone_ik_list.size() > 1;
- break;
- }
+ DragType resize_drag = DRAG_NONE;
+ float radius = (select_handle->get_size().width / 2) * 1.5;
- if (!pi->has_meta("_edit_bone_"))
- break;
- }
+ for (int i = 0; i < 4; i++) {
+ int prev = (i + 3) % 4;
+ int next = (i + 1) % 4;
+
+ Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
+ ofs *= (select_handle->get_size().width / 2);
+ ofs += endpoints[i];
+ if (ofs.distance_to(b->get_position()) < radius)
+ resize_drag = dragger[i * 2];
- if (!ik_found)
- bone_ik_list.clear();
+ ofs = (endpoints[i] + endpoints[next]) / 2;
+ ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
+ if (ofs.distance_to(b->get_position()) < radius)
+ resize_drag = dragger[i * 2 + 1];
+ }
+
+ if (resize_drag != DRAG_NONE) {
+ drag_type = resize_drag;
+ drag_from = transform.affine_inverse().xform(b->get_position());
+ drag_selection = List<CanvasItem *>();
+ drag_selection.push_back(canvas_item);
+ _save_canvas_item_state(drag_selection);
+ return true;
}
}
}
+ }
- // Single selected item
- CanvasItem *canvas_item = _get_single_item();
- if (canvas_item) {
+ if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
+ drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
+ // Resize the node
+ if (m.is_valid()) {
+ CanvasItem *canvas_item = drag_selection[0];
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- ERR_FAIL_COND(!se);
-
- Point2 click = b->get_position();
-
- // Rotation
- if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
- drag = DRAG_ROTATE;
- drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->_edit_get_state();
- if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
- if (Object::cast_to<Control>(canvas_item))
- se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
- se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->_edit_get_rect();
- return;
+ //Reset state
+ canvas_item->_edit_set_state(se->undo_state);
+
+ bool uniform = m->get_shift();
+ bool symmetric = m->get_alt();
+
+ Rect2 local_rect = canvas_item->_edit_get_rect();
+ float aspect = local_rect.get_size().y / local_rect.get_size().x;
+ Point2 current_begin = local_rect.get_position();
+ Point2 current_end = local_rect.get_position() + local_rect.get_size();
+ Point2 max_begin = (symmetric) ? (current_begin + current_end - canvas_item->_edit_get_minimum_size()) / 2.0 : current_end - canvas_item->_edit_get_minimum_size();
+ Point2 min_end = (symmetric) ? (current_begin + current_end + canvas_item->_edit_get_minimum_size()) / 2.0 : current_begin + canvas_item->_edit_get_minimum_size();
+ Point2 center = (current_begin + current_end) / 2.0;
+
+ drag_to = transform.affine_inverse().xform(m->get_position());
+
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse();
+
+ Point2 drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item);
+ Point2 drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item);
+ Point2 drag_begin = xform.xform(drag_to_snapped_begin);
+ Point2 drag_end = xform.xform(drag_to_snapped_end);
+
+ // Horizontal resize
+ if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
+ current_begin.x = MIN(drag_begin.x, max_begin.x);
+ } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
+ current_end.x = MAX(drag_end.x, min_end.x);
}
- if (tool == TOOL_SELECT) {
- // Open a sub-scene on double-click
- if (b->is_doubleclick()) {
- if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) {
- editor->open_request(canvas_item->get_filename());
- return;
+ // Vertical resize
+ if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
+ current_begin.y = MIN(drag_begin.y, max_begin.y);
+ } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
+ current_end.y = MAX(drag_end.y, min_end.y);
+ }
+
+ // Uniform resize
+ if (uniform) {
+ if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT) {
+ current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
+ } else if (drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM) {
+ current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
+ } else {
+ if (aspect >= 1.0) {
+ if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
+ current_begin.y = current_end.y - aspect * (current_end.x - current_begin.x);
+ } else {
+ current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
+ }
+ } else {
+ if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
+ current_begin.x = current_end.x - (current_end.y - current_begin.y) / aspect;
+ } else {
+ current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
+ }
}
}
+ }
- // Drag resize handles
- drag = _get_resize_handle_drag_type(click, drag_point_from);
- if (drag != DRAG_NONE) {
- drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->_edit_get_state();
- if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
- if (Object::cast_to<Control>(canvas_item))
- se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
- se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->_edit_get_rect();
- return;
+ // Symmetric resize
+ if (symmetric) {
+ if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
+ current_end.x = 2.0 * center.x - current_begin.x;
+ } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
+ current_begin.x = 2.0 * center.x - current_end.x;
}
-
- // Drag anchor handles
- Control *control = Object::cast_to<Control>(canvas_item);
- if (control && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
- drag = _get_anchor_handle_drag_type(click, drag_point_from);
- if (drag != DRAG_NONE) {
- drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->_edit_get_state();
- se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->_edit_get_rect();
- return;
- }
+ if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
+ current_end.y = 2.0 * center.y - current_begin.y;
+ } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
+ current_begin.y = 2.0 * center.y - current_end.y;
}
}
+ canvas_item->_edit_set_rect(Rect2(current_begin, current_end - current_begin));
+ return true;
}
- // Multiple selected items
- Point2 click = b->get_position();
-
- if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) {
- // Drag the nodes
- _prepare_drag(click);
+ // Confirm resize
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ _commit_canvas_item_state(drag_selection, TTR("Resize CanvasItem"));
+ drag_type = DRAG_NONE;
viewport->update();
- return;
+ return true;
}
- CanvasItem *c = NULL;
- if (Cbone) {
- c = Object::cast_to<CanvasItem>(ObjectDB::get_instance(Cbone->get().bone));
- if (c)
- c = c->get_parent_item();
+ // Cancel a drag
+ if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ _restore_canvas_item_state(drag_selection);
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
}
+ }
+ return false;
+}
- Node *scene = editor->get_edited_scene();
- if (!scene)
- return;
- // Find the item to select
- if (!c) {
- Vector<_SelectResult> selection;
- _find_canvas_items_at_pos(click, scene, transform, Transform2D(), selection, 1);
- if (!selection.empty())
- c = selection[0].item;
+bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventMouseMotion> m = p_event;
+ Ref<InputEventKey> k = p_event;
- CanvasItem *cn = c;
- while (cn) {
- if (cn->has_meta("_edit_group_")) {
- c = cn;
- }
- cn = cn->get_parent_item();
+ if (drag_type == DRAG_NONE) {
+ //Start moving the nodes
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if ((b->get_alt() || tool == TOOL_MOVE) && selection.size() > 0) {
+ drag_type = DRAG_ALL;
+ drag_from = transform.affine_inverse().xform(b->get_position());
+ drag_selection = selection;
+ _save_canvas_item_state(drag_selection);
+ return true;
}
}
+ }
- Node *n = c;
- while ((n && n != scene && n->get_owner() != scene) || (n && !n->is_class("CanvasItem"))) {
- n = n->get_parent();
- };
+ if (drag_type == DRAG_ALL) {
+ // Move the nodes
+ if (m.is_valid()) {
+ _restore_canvas_item_state(drag_selection, true);
- if (n) {
- c = Object::cast_to<CanvasItem>(n);
- } else {
- c = NULL;
- }
+ drag_to = transform.affine_inverse().xform(m->get_position());
+ Point2 previous_pos;
+ if (drag_selection.size() == 1) {
+ Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
+ previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
+ } else {
+ previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
+ }
+ Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES);
+ bool single_axis = m->get_shift();
+ if (single_axis) {
+ if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) {
+ new_pos.y = previous_pos.y;
+ } else {
+ new_pos.x = previous_pos.x;
+ }
+ }
- // Select the item
- additive_selection = b->get_shift();
- if (!c) {
- _select_click_on_empty_area(click, additive_selection, true);
- } else if (!_select_click_on_item(c, click, additive_selection, true)) {
- return;
+ bool force_no_IK = m->get_alt();
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
+ CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
+ _solve_IK(node2d, new_pos);
+ } else {
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+ }
+ }
+ return true;
}
- }
- Ref<InputEventMouseMotion> m = p_event;
- if (m.is_valid()) {
- // Mouse motion event
- _update_cursor();
+ // Confirm the move (only if it was moved)
+ if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && (drag_type == DRAG_ALL)) {
+ if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
+ _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
+ }
- if (box_selecting) {
- // Update box selection
- box_selecting_to = transform.affine_inverse().xform(m->get_position());
+ drag_type = DRAG_NONE;
viewport->update();
- return;
+ return true;
}
- if (drag == DRAG_NONE) {
- bool space_pressed = Input::get_singleton()->is_key_pressed(KEY_SPACE);
- bool simple_panning = EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning");
- int button = m->get_button_mask();
+ // Cancel a drag
+ if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ _restore_canvas_item_state(drag_selection, true);
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
+ }
- // Check if any of the panning triggers are activated
- bool panning_tool = (button & BUTTON_MASK_LEFT) && tool == TOOL_PAN;
- bool panning_middle_button = button & BUTTON_MASK_MIDDLE;
- bool panning_spacebar = (button & BUTTON_MASK_LEFT) && space_pressed;
- bool panning_spacebar_simple = space_pressed && simple_panning;
+ // Move the canvas items with the arrow keys
+ if (k.is_valid() && k->is_pressed() && tool == TOOL_SELECT &&
+ (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
+ if (!k->is_echo()) {
+ // Start moving the canvas items with the keyboard
+ drag_selection = _get_edited_canvas_items();
+ drag_type = DRAG_KEY_MOVE;
+ drag_from = Vector2();
+ drag_to = Vector2();
+ _save_canvas_item_state(drag_selection, true);
+ }
- if (panning_tool || panning_middle_button || panning_spacebar || panning_spacebar_simple) {
- // Pan the viewport
- Point2i relative;
- if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
- relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
- } else {
- relative = m->get_relative();
- }
+ _restore_canvas_item_state(drag_selection, true);
+
+ bool move_local_base = k->get_alt();
+ bool move_local_base_rotated = k->get_control() || k->get_metakey();
+
+ Vector2 dir;
+ if (k->get_scancode() == KEY_UP)
+ dir += Vector2(0, -1);
+ else if (k->get_scancode() == KEY_DOWN)
+ dir += Vector2(0, 1);
+ else if (k->get_scancode() == KEY_LEFT)
+ dir += Vector2(-1, 0);
+ else if (k->get_scancode() == KEY_RIGHT)
+ dir += Vector2(1, 0);
+ if (k->get_shift())
+ dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
+
+ drag_to += dir;
+ if (k->get_shift())
+ drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
+
+ Point2 previous_pos;
+ if (drag_selection.size() == 1) {
+ Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
+ previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
+ } else {
+ previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
+ }
- h_scroll->set_value(h_scroll->get_value() - relative.x / zoom);
- v_scroll->set_value(v_scroll->get_value() - relative.y / zoom);
+ Point2 new_pos;
+ if (drag_selection.size() == 1) {
+ Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]);
+ if (node_2d && move_local_base_rotated) {
+ Transform2D m;
+ m.rotate(node_2d->get_rotation());
+ new_pos += m.xform(drag_to);
+ } else if (move_local_base) {
+ new_pos += drag_to;
+ } else {
+ new_pos = previous_pos + (drag_to - drag_from);
}
-
- return;
+ } else {
+ new_pos = previous_pos + (drag_to - drag_from);
}
- List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
+ for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- bool dragging_bone = drag == DRAG_ALL && selection.size() == 1 && bone_ik_list.size();
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
- if (!dragging_bone) {
- canvas_item->_edit_set_state(se->undo_state); //reset state and reapply
- if (Object::cast_to<Node2D>(canvas_item))
- Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot);
- if (Object::cast_to<Control>(canvas_item))
- Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot);
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
+ _solve_IK(node2d, new_pos);
+ } else {
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
}
+ }
+ return true;
+ }
- Vector2 dfrom = drag_from;
- Vector2 dto = transform.affine_inverse().xform(m->get_position());
- if (canvas_item->has_meta("_edit_lock_"))
- continue;
+ if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT &&
+ (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
+ // Confirm canvas items move by arrow keys
+ if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) &&
+ (!Input::get_singleton()->is_key_pressed(KEY_DOWN)) &&
+ (!Input::get_singleton()->is_key_pressed(KEY_LEFT)) &&
+ (!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) {
+ _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
+ drag_type = DRAG_NONE;
+ }
+ viewport->update();
+ return true;
+ }
- if (drag == DRAG_ROTATE) {
- // Rotate the node
- Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
- {
- Node2D *node = Object::cast_to<Node2D>(canvas_item);
-
- if (node) {
- real_t angle = node->get_rotation();
- node->set_rotation(snap_angle(angle + (dfrom - center).angle_to(dto - center), angle));
- display_rotate_to = dto;
- display_rotate_from = center;
- viewport->update();
- }
- }
+ if (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
+ // Accept the key event in any case
+ return true;
+ }
+ return false;
+}
- {
- Control *node = Object::cast_to<Control>(canvas_item);
+bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> b = p_event;
+ Ref<InputEventMouseMotion> m = p_event;
+ Ref<InputEventKey> k = p_event;
- if (node) {
- real_t angle = node->get_rotation();
- display_rotate_to = dto;
- display_rotate_from = center + node->get_pivot_offset().rotated(angle);
- node->set_rotation(snap_angle(angle + (dfrom - display_rotate_from).angle_to(display_rotate_to - display_rotate_from), angle));
- viewport->update();
- }
+ if (drag_type == DRAG_NONE) {
+ if (b.is_valid() &&
+ ((b->get_button_index() == BUTTON_LEFT && b->get_alt() && tool == TOOL_SELECT) ||
+ (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
+ // Popup the selection menu list
+ Point2 click = transform.xform(b->get_position());
+
+ Node *scene = editor->get_edited_scene();
+
+ _find_canvas_items_at_pos(click, scene, selection_results);
+ for (int i = 0; i < selection_results.size(); i++) {
+ CanvasItem *item = selection_results[i].item;
+ if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) {
+ //invalid result
+ selection_results.remove(i);
+ i--;
}
-
- continue;
}
- bool uniform = m->get_shift();
- bool symmetric = m->get_alt();
+ if (selection_results.size() == 1) {
+ CanvasItem *item = selection_results[0].item;
+ selection_results.clear();
- Vector2 drag_vector =
- canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
- canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
-
- switch (drag) {
- case DRAG_ALL:
- case DRAG_NODE_2D:
- dto -= drag_from - drag_point_from;
- if (uniform) {
- if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {
- dto.y = drag_point_from.y;
- } else {
- dto.x = drag_point_from.x;
- }
- }
- break;
- }
+ _select_click_on_item(item, click, b->get_shift());
- Control *control = Object::cast_to<Control>(canvas_item);
- if (control) {
- // Drag and snap the anchor
- Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse();
+ return true;
+ } else if (!selection_results.empty()) {
+ selection_results.sort();
- Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from);
- anchor = _position_to_anchor(control, anchor);
+ NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
+ StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
- Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_GUIDES | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES));
- anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001));
+ for (int i = 0; i < selection_results.size(); i++) {
+ CanvasItem *item = selection_results[i].item;
- bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
+ Ref<Texture> icon;
+ if (item->has_meta("_editor_icon"))
+ icon = item->get_meta("_editor_icon");
+ else
+ icon = get_icon(has_icon(item->get_class(), "EditorIcons") ? item->get_class() : String("Object"), "EditorIcons");
+ String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path());
- switch (drag) {
- case DRAG_ANCHOR_TOP_LEFT:
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false);
- continue;
- break;
- case DRAG_ANCHOR_TOP_RIGHT:
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false);
- continue;
- break;
- case DRAG_ANCHOR_BOTTOM_RIGHT:
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false);
- break;
- case DRAG_ANCHOR_BOTTOM_LEFT:
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false);
- continue;
- break;
- case DRAG_ANCHOR_ALL:
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false);
- if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false);
- if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false);
- continue;
- break;
+ selection_menu->add_item(item->get_name());
+ selection_menu->set_item_icon(i, icon);
+ selection_menu->set_item_metadata(i, node_path);
+ selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path);
}
- }
- dfrom = drag_point_from;
- dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, _get_single_item());
-
- drag_vector =
- canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
- canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
-
- Rect2 local_rect = canvas_item->_edit_get_rect();
- Vector2 begin = local_rect.position;
- Vector2 end = local_rect.position + local_rect.size;
- Vector2 minsize = canvas_item->_edit_get_minimum_size();
-
- if (uniform) {
- // Keep the height/width ratio of the item
- float aspect = local_rect.size.aspect();
- switch (drag) {
- case DRAG_LEFT:
- drag_vector.y = -drag_vector.x / aspect;
- break;
- case DRAG_RIGHT:
- drag_vector.y = drag_vector.x / aspect;
- break;
- case DRAG_TOP:
- drag_vector.x = -drag_vector.y * aspect;
- break;
- case DRAG_BOTTOM:
- drag_vector.x = drag_vector.y * aspect;
- break;
- case DRAG_BOTTOM_LEFT:
- case DRAG_TOP_RIGHT:
- if (aspect > 1.0) { // width > height, take x as reference
- drag_vector.y = -drag_vector.x / aspect;
- } else { // height > width, take y as reference
- drag_vector.x = -drag_vector.y * aspect;
- }
- break;
- case DRAG_BOTTOM_RIGHT:
- case DRAG_TOP_LEFT:
- if (aspect > 1.0) { // width > height, take x as reference
- drag_vector.y = drag_vector.x / aspect;
- } else { // height > width, take y as reference
- drag_vector.x = drag_vector.y * aspect;
- }
- break;
- }
- } else {
- switch (drag) {
- case DRAG_RIGHT:
- case DRAG_LEFT:
- drag_vector.y = 0;
- break;
- case DRAG_TOP:
- case DRAG_BOTTOM:
- drag_vector.x = 0;
- break;
- }
+ selection_menu_additive_selection = b->get_shift();
+ selection_menu->set_global_position(b->get_global_position());
+ selection_menu->popup();
+ selection_menu->call_deferred("grab_click_focus");
+ selection_menu->set_invalidate_click_until_motion();
+ return true;
}
+ }
- switch (drag) {
- case DRAG_ALL:
- begin += drag_vector;
- end += drag_vector;
- break;
- case DRAG_RIGHT:
- case DRAG_BOTTOM:
- case DRAG_BOTTOM_RIGHT:
- incend(begin.x, end.x, drag_vector.x, minsize.x, symmetric);
- incend(begin.y, end.y, drag_vector.y, minsize.y, symmetric);
- break;
- case DRAG_TOP_LEFT:
- incbeg(begin.x, end.x, drag_vector.x, minsize.x, symmetric);
- incbeg(begin.y, end.y, drag_vector.y, minsize.y, symmetric);
- break;
- case DRAG_TOP:
- case DRAG_TOP_RIGHT:
- incbeg(begin.y, end.y, drag_vector.y, minsize.y, symmetric);
- incend(begin.x, end.x, drag_vector.x, minsize.x, symmetric);
- break;
- case DRAG_LEFT:
- case DRAG_BOTTOM_LEFT:
- incbeg(begin.x, end.x, drag_vector.x, minsize.x, symmetric);
- incend(begin.y, end.y, drag_vector.y, minsize.y, symmetric);
- break;
+ if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
+ // Single item selection
+ Point2 click = transform.affine_inverse().xform(b->get_position());
- case DRAG_PIVOT:
+ Node *scene = editor->get_edited_scene();
+ if (!scene)
+ return true;
- if (Object::cast_to<Node2D>(canvas_item)) {
- Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
- n2d->_edit_set_pivot(se->undo_pivot + drag_vector);
- }
- if (Object::cast_to<Control>(canvas_item)) {
- Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot + drag_vector);
- }
- continue;
- break;
- case DRAG_NODE_2D:
+ // Find the item to select
+ CanvasItem *canvas_item = NULL;
+ Vector<_SelectResult> selection;
+ _find_canvas_items_at_pos(click, scene, selection, 1);
+ if (!selection.empty())
+ canvas_item = selection[0].item;
- ERR_FAIL_COND(!Object::cast_to<Node2D>(canvas_item));
- Object::cast_to<Node2D>(canvas_item)->set_global_position(dto);
- continue;
- break;
+ // Check if the canvas item is in a group, and select the group instead if it is the case
+ CanvasItem *canvas_item_tmp = canvas_item;
+ while (canvas_item_tmp) {
+ if (canvas_item->has_meta("_edit_group_")) {
+ canvas_item = canvas_item_tmp;
+ }
+ canvas_item_tmp = canvas_item_tmp->get_parent_item();
}
- if (!dragging_bone) {
+ // Make sure the selected node is in the current scene
+ Node *node = canvas_item;
+ while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) {
+ node = node->get_parent();
+ };
+ canvas_item = Object::cast_to<CanvasItem>(node);
- local_rect.position = begin;
- local_rect.size = end - begin;
- canvas_item->_edit_set_rect(local_rect);
+ if (!canvas_item) {
+ // Start a box selection
+ if (!b->get_shift()) {
+ // Clear the selection if not additive
+ editor_selection->clear();
+ viewport->update();
+ };
+ drag_from = click;
+ drag_type = DRAG_BOX_SELECTION;
+ box_selecting_to = drag_from;
+ return true;
} else {
- //ok, all that had to be done was done, now solve IK
-
- Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
- Transform2D final_xform = bone_orig_xform;
-
- if (n2d) {
-
- float total_len = 0;
- for (List<BoneIK>::Element *E = bone_ik_list.front(); E; E = E->next()) {
- if (E->prev())
- total_len += E->get().len;
- E->get().pos = E->get().node->get_global_transform().get_origin();
- }
-
- {
-
- final_xform.elements[2] += dto - dfrom; //final_xform.affine_inverse().basis_xform_inv(drag_vector);
- //n2d->set_global_transform(final_xform);
- }
-
- CanvasItem *last = bone_ik_list.back()->get().node;
- if (!last)
- break;
-
- Vector2 root_pos = last->get_global_transform().get_origin();
- Vector2 leaf_pos = final_xform.get_origin();
-
- if ((leaf_pos.distance_to(root_pos)) > total_len) {
- //oops dude you went too far
- //print_line("TOO FAR!");
- Vector2 rel = leaf_pos - root_pos;
- rel = rel.normalized() * total_len;
- leaf_pos = root_pos + rel;
- }
-
- bone_ik_list.front()->get().pos = leaf_pos;
-
- //print_line("BONE IK LIST "+itos(bone_ik_list.size()));
-
- if (bone_ik_list.size() > 2) {
- int solver_iterations = 64;
- float solver_k = 0.3;
-
- for (int i = 0; i < solver_iterations; i++) {
-
- for (List<BoneIK>::Element *E = bone_ik_list.front(); E; E = E->next()) {
-
- if (E == bone_ik_list.back()) {
-
- break;
- }
-
- float len = E->next()->get().len;
-
- if (E->next() == bone_ik_list.back()) {
-
- //print_line("back");
+ bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift());
+ // Start dragging
+ if (still_selected) {
+ // Drag the node(s) if requested
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+
+ drag_type = DRAG_ALL;
+ drag_selection = selection;
+ drag_from = click;
+ _save_canvas_item_state(drag_selection);
+ }
+ // Select the item
+ return true;
+ }
+ }
+ }
- Vector2 rel = E->get().pos - E->next()->get().pos;
- //print_line("PREV "+E->get().pos);
- Vector2 desired = E->next()->get().pos + rel.normalized() * len;
- //print_line("DESIRED "+desired);
- E->get().pos = E->get().pos.linear_interpolate(desired, solver_k);
- //print_line("POST "+E->get().pos);
+ if (drag_type == DRAG_BOX_SELECTION) {
+ if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
+ // Confirms box selection
+ Node *scene = editor->get_edited_scene();
+ if (scene) {
+ List<CanvasItem *> selitems;
- } else if (E == bone_ik_list.front()) {
- //only adjust parent
- //print_line("front");
- Vector2 rel = E->next()->get().pos - E->get().pos;
- //print_line("PREV "+E->next()->get().pos);
- Vector2 desired = E->get().pos + rel.normalized() * len;
- //print_line("DESIRED "+desired);
- E->next()->get().pos = E->next()->get().pos.linear_interpolate(desired, solver_k);
- //print_line("POST "+E->next()->get().pos);
- } else {
+ Point2 bsfrom = drag_from;
+ Point2 bsto = box_selecting_to;
+ if (bsfrom.x > bsto.x)
+ SWAP(bsfrom.x, bsto.x);
+ if (bsfrom.y > bsto.y)
+ SWAP(bsfrom.y, bsto.y);
- Vector2 rel = E->next()->get().pos - E->get().pos;
- Vector2 cen = (E->next()->get().pos + E->get().pos) * 0.5;
- rel = rel.linear_interpolate(rel.normalized() * len, solver_k);
- rel *= 0.5;
- E->next()->get().pos = cen + rel;
- E->get().pos = cen - rel;
- //print_line("mid");
- }
- }
- }
- }
+ _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems);
+ for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
+ editor_selection->add_node(E->get());
}
+ }
- for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) {
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
- Node2D *n = E->get().node;
+ if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
+ // Cancel box selection
+ drag_type = DRAG_NONE;
+ viewport->update();
+ return true;
+ }
- if (!E->prev()) {
- //last goes to what it was
- final_xform.set_origin(n->get_global_position());
- n->set_global_transform(final_xform);
+ if (m.is_valid()) {
+ // Update box selection
+ box_selecting_to = transform.affine_inverse().xform(m->get_position());
+ viewport->update();
+ return true;
+ }
+ }
- } else {
- Vector2 rel = (E->prev()->get().node->get_global_position() - n->get_global_position()).normalized();
- Vector2 rel2 = (E->prev()->get().pos - E->get().pos).normalized();
- float rot = rel.angle_to(rel2);
- if (n->get_global_transform().basis_determinant() < 0) {
- //mirrored, rotate the other way
- rot = -rot;
- }
+ if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
+ // Unselect everything
+ editor_selection->clear();
+ viewport->update();
+ }
+ return false;
+}
- n->rotate(rot);
- }
+void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
+ bool accepted = false;
+ if ((accepted = _gui_input_rulers_and_guides(p_event))) {
+ //printf("Rulers and guides\n");
+ } else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) {
+ //printf("Plugin\n");
+ } else if ((accepted = _gui_input_open_scene_on_double_click(p_event))) {
+ //printf("Open scene on double click\n");
+ } else if ((accepted = _gui_input_anchors(p_event))) {
+ //printf("Anchors\n");
+ } else if ((accepted = _gui_input_pivot(p_event))) {
+ //printf("Set pivot\n");
+ } else if ((accepted = _gui_input_resize(p_event))) {
+ //printf("Resize\n");
+ } else if ((accepted = _gui_input_rotate(p_event))) {
+ //printf("Rotate\n");
+ } else if ((accepted = _gui_input_move(p_event))) {
+ //printf("Move\n");
+ } else if ((accepted = _gui_input_select(p_event))) {
+ //printf("Selection\n");
+ } else if ((accepted = _gui_input_zoom_or_pan(p_event))) {
+ //printf("Zoom or pan\n");
+ }
+
+ if (accepted)
+ accept_event();
+
+ // Change the cursor
+ CursorShape c = CURSOR_ARROW;
+ switch (drag_type) {
+ case DRAG_NONE:
+ if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+ c = CURSOR_DRAG;
+ } else {
+ switch (tool) {
+ case TOOL_MOVE:
+ c = CURSOR_MOVE;
+ break;
+ case TOOL_EDIT_PIVOT:
+ c = CURSOR_CROSS;
+ break;
+ case TOOL_PAN:
+ c = CURSOR_DRAG;
+ break;
+ default:
+ break;
}
-
- break;
}
- }
+ break;
+ case DRAG_LEFT:
+ case DRAG_RIGHT:
+ c = CURSOR_HSIZE;
+ break;
+ case DRAG_TOP:
+ case DRAG_BOTTOM:
+ c = CURSOR_VSIZE;
+ break;
+ case DRAG_TOP_LEFT:
+ case DRAG_BOTTOM_RIGHT:
+ c = CURSOR_FDIAGSIZE;
+ break;
+ case DRAG_TOP_RIGHT:
+ case DRAG_BOTTOM_LEFT:
+ c = CURSOR_BDIAGSIZE;
+ break;
+ case DRAG_ALL:
+ c = CURSOR_MOVE;
+ break;
+ default:
+ break;
+ }
+ viewport->set_default_cursor_shape(c);
+
+ // Grab focus
+ if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
+ viewport->call_deferred("grab_focus");
}
}
@@ -2292,8 +1896,8 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi
void CanvasItemEditor::_draw_focus() {
// Draw the focus around the base viewport
- if (viewport_base->has_focus()) {
- get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size()));
+ if (viewport->has_focus()) {
+ get_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size()));
}
}
@@ -2306,63 +1910,61 @@ void CanvasItemEditor::_draw_guides() {
if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
for (int i = 0; i < vguides.size(); i++) {
- if (drag == DRAG_V_GUIDE && i == edited_guide_index)
+ if (drag_type == DRAG_V_GUIDE && i == dragged_guide_index)
continue;
float x = xform.xform(Point2(vguides[i], 0)).x;
- viewport_base->draw_line(Point2(x, 0), Point2(x, viewport_base->get_size().y), guide_color);
+ viewport->draw_line(Point2(x, 0), Point2(x, viewport->get_size().y), guide_color);
}
}
if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
for (int i = 0; i < hguides.size(); i++) {
- if (drag == DRAG_H_GUIDE && i == edited_guide_index)
+ if (drag_type == DRAG_H_GUIDE && i == dragged_guide_index)
continue;
float y = xform.xform(Point2(0, hguides[i])).y;
- viewport_base->draw_line(Point2(0, y), Point2(viewport_base->get_size().x, y), guide_color);
+ viewport->draw_line(Point2(0, y), Point2(viewport->get_size().x, y), guide_color);
}
}
// Dragged guide
Color text_color = get_color("font_color", "Editor");
text_color.a = 0.5;
- if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE) {
- String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).x);
+ if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
+ String str = vformat("%d px", xform.affine_inverse().xform(dragged_guide_pos).x);
Ref<Font> font = get_font("font", "Label");
Size2 text_size = font->get_string_size(str);
- viewport_base->draw_string(font, Point2(edited_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
- viewport_base->draw_line(Point2(edited_guide_pos.x, 0), Point2(edited_guide_pos.x, viewport_base->get_size().y), guide_color);
+ viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
+ viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color);
}
- if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE) {
- String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).y);
+ if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
+ String str = vformat("%d px", xform.affine_inverse().xform(dragged_guide_pos).y);
Ref<Font> font = get_font("font", "Label");
Size2 text_size = font->get_string_size(str);
- viewport_base->draw_string(font, Point2(RULER_WIDTH + 10, edited_guide_pos.y + text_size.y / 2 + 10), str, text_color);
- viewport_base->draw_line(Point2(0, edited_guide_pos.y), Point2(viewport_base->get_size().x, edited_guide_pos.y), guide_color);
+ viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color);
+ viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color);
}
}
void CanvasItemEditor::_draw_rulers() {
- Color graduation_color = get_color("font_color", "Editor");
- graduation_color.a = 0.5;
Color bg_color = get_color("dark_color_2", "Editor");
+ Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5);
Color font_color = get_color("font_color", "Editor");
font_color.a = 0.8;
Ref<Font> font = get_font("rulers", "EditorFonts");
// The rule transform
- Transform2D ruler_transform;
- if (show_grid || snap_grid) {
- ruler_transform = Transform2D();
- if (snap_relative && get_item_count() > 0) {
- ruler_transform.translate(_find_topleftmost_point());
+ Transform2D ruler_transform = Transform2D();
+ if (show_grid || (snap_active && snap_grid)) {
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (snap_relative && selection.size() > 0) {
+ ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
} else {
ruler_transform.translate(grid_offset);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
}
while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
-
ruler_transform.scale_basis(Point2(2, 2));
}
} else {
@@ -2373,7 +1975,6 @@ void CanvasItemEditor::_draw_rulers() {
for (int i = 0; basic_rule * zoom < 100; i++) {
basic_rule *= (i % 2) ? 2.0 : 5.0;
}
- ruler_transform = Transform2D();
ruler_transform.scale(Size2(basic_rule, basic_rule));
}
@@ -2387,43 +1988,43 @@ void CanvasItemEditor::_draw_rulers() {
minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
// First and last graduations to draw (in the ruler space)
- Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2());
+ Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(RULER_WIDTH, RULER_WIDTH));
Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size());
// Draw top ruler
- viewport_base->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
+ viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
for (int i = Math::ceil(first.x); i < last.x; i++) {
Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0));
if (i % (major_subdivision * minor_subdivision) == 0) {
- viewport_base->draw_line(Point2(position.x + RULER_WIDTH, 0), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color);
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
- viewport_base->draw_string(font, Point2(position.x + RULER_WIDTH + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
+ viewport->draw_string(font, Point2(position.x + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
} else {
if (i % minor_subdivision == 0) {
- viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color);
} else {
- viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.66), Point2(position.x, RULER_WIDTH), graduation_color);
}
}
}
// Draw left ruler
- viewport_base->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
+ viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
for (int i = Math::ceil(first.y); i < last.y; i++) {
Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i));
if (i % (major_subdivision * minor_subdivision) == 0) {
- viewport_base->draw_line(Point2(0, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color);
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
- viewport_base->draw_string(font, Point2(2, position.y + RULER_WIDTH + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
+ viewport->draw_string(font, Point2(2, position.y + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
} else {
if (i % minor_subdivision == 0) {
- viewport_base->draw_line(Point2(RULER_WIDTH * 0.33, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color);
} else {
- viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ viewport->draw_line(Point2(RULER_WIDTH * 0.66, position.y), Point2(RULER_WIDTH, position.y), graduation_color);
}
}
}
- viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
+ viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
}
void CanvasItemEditor::_draw_grid() {
@@ -2434,8 +2035,9 @@ void CanvasItemEditor::_draw_grid() {
Transform2D xform = transform.affine_inverse();
Vector2 real_grid_offset;
- if (snap_relative && get_item_count() > 0) {
- Vector2 topleft = _find_topleftmost_point();
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (snap_relative && selection.size() > 0) {
+ Vector2 topleft = _get_encompassing_rect_from_list(selection).position;
real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier));
real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier));
} else {
@@ -2468,26 +2070,23 @@ void CanvasItemEditor::_draw_grid() {
}
void CanvasItemEditor::_draw_selection() {
- bool pivot_found = false;
Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons");
- bool single = _get_single_item() != NULL;
RID ci = viewport->get_canvas_item();
- Map<Node *, Object *> &selection = editor_selection->get_selection();
- for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
+ List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
+ bool single = selection.size() == 1;
+ for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
Rect2 rect = canvas_item->_edit_get_rect();
- if (show_helpers && drag != DRAG_NONE && drag != DRAG_PIVOT) {
+ // Draw the previous position if we are dragging the node
+ if (show_helpers &&
+ (drag_type == DRAG_ALL || drag_type == DRAG_ROTATE ||
+ drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
+ drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT)) {
const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7);
@@ -2507,8 +2106,8 @@ void CanvasItemEditor::_draw_selection() {
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform);
+ // Draw the selected items surrounding boxes
Vector2 endpoints[4] = {
-
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
@@ -2524,25 +2123,13 @@ void CanvasItemEditor::_draw_selection() {
}
if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
-
- Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
- if (node2d) {
- if (node2d->_edit_use_pivot()) {
- viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor());
- can_move_pivot = true;
- pivot_found = true;
- }
+ // Draw the pivot
+ if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/
+ viewport->draw_texture(pivot_icon, xform.xform(canvas_item->_edit_get_pivot()) + (-pivot_icon->get_size() / 2).floor());
}
Control *control = Object::cast_to<Control>(canvas_item);
if (control) {
- Vector2 pivot_ofs = control->get_pivot_offset();
- if (pivot_ofs != Vector2()) {
- viewport->draw_texture(pivot_icon, xform.xform(pivot_ofs) + (-pivot_icon->get_size() / 2).floor());
- }
- can_move_pivot = true;
- pivot_found = true;
-
if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
// Draw the helpers
Color color_base = Color(0.8, 0.8, 0.8, 0.5);
@@ -2561,10 +2148,9 @@ void CanvasItemEditor::_draw_selection() {
anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i]));
}
- Map<Node *, Object *> &selection = editor_selection->get_selection();
// Get which anchor is dragged
int dragged_anchor = -1;
- switch (drag) {
+ switch (drag_type) {
case DRAG_ANCHOR_ALL:
case DRAG_ANCHOR_TOP_LEFT:
dragged_anchor = 0;
@@ -2578,6 +2164,8 @@ void CanvasItemEditor::_draw_selection() {
case DRAG_ANCHOR_BOTTOM_LEFT:
dragged_anchor = 3;
break;
+ default:
+ break;
}
if (dragged_anchor >= 0) {
@@ -2639,56 +2227,65 @@ void CanvasItemEditor::_draw_selection() {
node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * control->get_parent_area_size().width + control->get_margin(MARGIN_RIGHT);
node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * control->get_parent_area_size().height + control->get_margin(MARGIN_BOTTOM);
- switch (drag) {
+ Point2 start, end;
+ switch (drag_type) {
case DRAG_LEFT:
case DRAG_TOP_LEFT:
case DRAG_BOTTOM_LEFT:
_draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
case DRAG_ALL:
- Point2 start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
- Point2 end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
+ start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
+ end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
_draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
break;
+ default:
+ break;
}
- switch (drag) {
+ switch (drag_type) {
case DRAG_RIGHT:
case DRAG_TOP_RIGHT:
case DRAG_BOTTOM_RIGHT:
_draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
case DRAG_ALL:
- Point2 start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
- Point2 end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
+ start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
+ end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
_draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
break;
+ default:
+ break;
}
- switch (drag) {
+ switch (drag_type) {
case DRAG_TOP:
case DRAG_TOP_LEFT:
case DRAG_TOP_RIGHT:
_draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT);
case DRAG_ALL:
- Point2 start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
- Point2 end = start - Vector2(0, control->get_margin(MARGIN_TOP));
+ start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
+ end = start - Vector2(0, control->get_margin(MARGIN_TOP));
_draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
break;
+ default:
+ break;
}
- switch (drag) {
+ switch (drag_type) {
case DRAG_BOTTOM:
case DRAG_BOTTOM_LEFT:
case DRAG_BOTTOM_RIGHT:
_draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT);
case DRAG_ALL:
- Point2 start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
- Point2 end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
+ start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
+ end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
_draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
break;
+ default:
+ break;
}
- switch (drag) {
+ switch (drag_type) {
//Draw the ghost rect if the node if rotated/scaled
case DRAG_LEFT:
case DRAG_TOP_LEFT:
@@ -2704,14 +2301,15 @@ void CanvasItemEditor::_draw_selection() {
viewport->draw_rect(parent_transform.xform(rect), color_base, false);
}
break;
+ default:
+ break;
}
}
}
if (tool == TOOL_SELECT) {
-
for (int i = 0; i < 4; i++) {
-
+ // Draw the resize handles
int prev = (i + 3) % 4;
int next = (i + 1) % 4;
@@ -2728,9 +2326,9 @@ void CanvasItemEditor::_draw_selection() {
}
}
}
- pivot_button->set_disabled(!pivot_found);
- if (box_selecting) {
+ if (drag_type == DRAG_BOX_SELECTION) {
+ // Draw the dragging box
Point2 bsfrom = transform.xform(drag_from);
Point2 bsto = transform.xform(box_selecting_to);
@@ -2738,8 +2336,50 @@ void CanvasItemEditor::_draw_selection() {
}
Color rotate_color(0.4, 0.7, 1.0, 0.8);
- if (drag == DRAG_ROTATE) {
- VisualServer::get_singleton()->canvas_item_add_line(ci, transform.xform(display_rotate_from), transform.xform(display_rotate_to), rotate_color);
+ if (drag_type == DRAG_ROTATE) {
+ // Draw the line when rotating a node
+ viewport->draw_line(transform.xform(drag_rotation_center), transform.xform(drag_to), rotate_color);
+ }
+}
+
+void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_color) {
+ // Draw a line going through the whole screen from a vector
+ RID ci = viewport->get_canvas_item();
+ Vector<Point2> points;
+ Point2 from = transform.xform(p_from);
+ Point2 to = transform.xform(p_to);
+ Size2 viewport_size = viewport->get_size();
+
+ if (to.x == from.x) {
+ // Vertical line
+ points.push_back(Point2(to.x, 0));
+ points.push_back(Point2(to.x, viewport_size.y));
+ } else if (to.y == from.y) {
+ // Horizontal line
+ points.push_back(Point2(0, to.y));
+ points.push_back(Point2(viewport_size.x, to.y));
+ } else {
+ float y_for_zero_x = (to.y * from.x - from.y * to.x) / (from.x - to.x);
+ float x_for_zero_y = (to.x * from.y - from.x * to.y) / (from.y - to.y);
+ float y_for_viewport_x = ((to.y - from.y) * (viewport_size.x - from.x)) / (to.x - from.x) + from.y;
+ float x_for_viewport_y = ((to.x - from.x) * (viewport_size.y - from.y)) / (to.y - from.y) + from.x; // faux
+
+ //bool start_set = false;
+ if (y_for_zero_x >= 0 && y_for_zero_x <= viewport_size.y) {
+ points.push_back(Point2(0, y_for_zero_x));
+ }
+ if (x_for_zero_y >= 0 && x_for_zero_y <= viewport_size.x) {
+ points.push_back(Point2(x_for_zero_y, 0));
+ }
+ if (y_for_viewport_x >= 0 && y_for_viewport_x <= viewport_size.y) {
+ points.push_back(Point2(viewport_size.x, y_for_viewport_x));
+ }
+ if (x_for_viewport_y >= 0 && x_for_viewport_y <= viewport_size.x) {
+ points.push_back(Point2(x_for_viewport_y, viewport_size.y));
+ }
+ }
+ if (points.size() >= 2) {
+ VisualServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color);
}
}
@@ -2750,9 +2390,8 @@ void CanvasItemEditor::_draw_axis() {
Color y_axis_color(0.4, 1.0, 0.4, 0.6);
Color area_axis_color(0.4, 0.4, 1.0, 0.4);
- Point2 origin = transform.get_origin();
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, origin.y), Point2(viewport->get_size().x, origin.y), x_axis_color);
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(origin.x, 0), Point2(origin.x, viewport->get_size().y), y_axis_color);
+ _draw_straight_line(Point2(), Point2(1, 0), x_axis_color);
+ _draw_straight_line(Point2(), Point2(0, 1), y_axis_color);
Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
@@ -2783,7 +2422,7 @@ void CanvasItemEditor::_draw_bones() {
E->get().from = Vector2();
E->get().to = Vector2();
- Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->get().bone));
+ Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key()));
if (!n2d)
continue;
@@ -2881,7 +2520,6 @@ void CanvasItemEditor::_build_bones_list(Node *p_node) {
ObjectID id = c->get_instance_id();
if (!bone_list.has(id)) {
BoneList bone;
- bone.bone = id;
bone_list[id] = bone;
}
@@ -2890,32 +2528,6 @@ void CanvasItemEditor::_build_bones_list(Node *p_node) {
}
}
-void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) {
- ERR_FAIL_COND(!p_node);
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _get_encompassing_rect(p_node->get_child(i), r_rect, p_xform);
- }
-
- CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
- if (c && c->is_visible_in_tree()) {
- Rect2 rect = c->_edit_get_rect();
- Transform2D xform = p_xform * c->get_transform();
- r_rect.expand_to(xform.xform(rect.position));
- r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
- r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
- r_rect.expand_to(xform.xform(rect.position + rect.size));
- }
-}
-
-void CanvasItemEditor::_draw_viewport_base() {
- if (show_rulers)
- _draw_rulers();
- if (show_guides)
- _draw_guides();
- _draw_focus();
-}
-
void CanvasItemEditor::_draw_viewport() {
// hide/show buttons depending on the selection
@@ -2968,36 +2580,25 @@ void CanvasItemEditor::_draw_viewport() {
}
_draw_bones();
+ if (show_rulers)
+ _draw_rulers();
+ if (show_guides)
+ _draw_guides();
+ _draw_focus();
}
void CanvasItemEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
-
EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- bool all_control = true;
- bool has_control = false;
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (Object::cast_to<Control>(canvas_item))
- has_control = true;
- else
- all_control = false;
+ int nb_control = 0;
+ int nb_having_pivot = 0;
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
+ CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
Rect2 r = canvas_item->_edit_get_rect();
Transform2D xform = canvas_item->get_transform();
@@ -3008,36 +2609,41 @@ void CanvasItemEditor::_notification(int p_what) {
se->prev_xform = xform;
}
- if (Object::cast_to<Control>(canvas_item)) {
+ Control *control = Object::cast_to<Control>(canvas_item);
+ if (control) {
float anchors[4];
Vector2 pivot;
- pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
- anchors[MARGIN_LEFT] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_LEFT);
- anchors[MARGIN_RIGHT] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_RIGHT);
- anchors[MARGIN_TOP] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_TOP);
- anchors[MARGIN_BOTTOM] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_BOTTOM);
+ pivot = control->get_pivot_offset();
+ anchors[MARGIN_LEFT] = control->get_anchor(MARGIN_LEFT);
+ anchors[MARGIN_RIGHT] = control->get_anchor(MARGIN_RIGHT);
+ anchors[MARGIN_TOP] = control->get_anchor(MARGIN_TOP);
+ anchors[MARGIN_BOTTOM] = control->get_anchor(MARGIN_BOTTOM);
if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) {
- viewport->update();
- viewport_base->update();
se->prev_pivot = pivot;
se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT];
se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT];
se->prev_anchors[MARGIN_TOP] = anchors[MARGIN_TOP];
se->prev_anchors[MARGIN_BOTTOM] = anchors[MARGIN_BOTTOM];
+ viewport->update();
}
+ nb_control++;
+ }
+
+ if (canvas_item->_edit_use_pivot()) {
+ nb_having_pivot++;
}
}
+ // Activate / Deactivate the pivot tool
+ pivot_button->set_disabled(nb_having_pivot == 0);
- if (all_control && has_control)
- presets_menu->show();
- else
- presets_menu->hide();
+ // Show / Hide the layout button
+ presets_menu->set_visible(nb_control > 0 && nb_control == selection.size());
for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- Object *b = ObjectDB::get_instance(E->get().bone);
+ Object *b = ObjectDB::get_instance(E->key());
if (!b) {
viewport->update();
@@ -3150,63 +2756,60 @@ void CanvasItemEditor::_notification(int p_what) {
void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
- drag = DRAG_NONE;
+ drag_type = DRAG_NONE;
// Clear the selection
editor_selection->clear(); //_clear_canvas_items();
editor_selection->add_node(p_canvas_item);
- //_add_canvas_item(p_canvas_item);
viewport->update();
- viewport_base->update();
}
void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
- if (show_rulers)
- viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH));
- else
- viewport_scrollable->set_begin(Point2());
+ Point2 zoom_hb_begin = Point2(5, 5);
+ zoom_hb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2();
+ zoom_hb->set_begin(zoom_hb_begin);
Size2 size = viewport->get_size();
Size2 hmin = h_scroll->get_minimum_size();
Size2 vmin = v_scroll->get_minimum_size();
- v_scroll->set_begin(Point2(size.width - vmin.width, 0));
+ v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
v_scroll->set_end(Point2(size.width, size.height));
- h_scroll->set_begin(Point2(0, size.height - hmin.height));
+ h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
- Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
-
bone_last_frame++;
if (editor->get_edited_scene()) {
_build_bones_list(editor->get_edited_scene());
- _get_encompassing_rect(editor->get_edited_scene(), canvas_item_rect, Transform2D());
}
List<Map<ObjectID, BoneList>::Element *> bone_to_erase;
-
for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
-
if (E->get().last_pass != bone_last_frame) {
bone_to_erase.push_back(E);
}
}
-
while (bone_to_erase.size()) {
bone_list.erase(bone_to_erase.front()->get());
bone_to_erase.pop_front();
}
- //expand area so it's easier to do animations and stuff at 0,0
+ // Calculate scrollable area
+ Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
+ if (editor->get_edited_scene()) {
+ Rect2 content_rect = _get_scene_encompassing_rect();
+ canvas_item_rect.expand_to(content_rect.position);
+ canvas_item_rect.expand_to(content_rect.position + content_rect.size);
+ }
canvas_item_rect.size += screen_rect * 2;
canvas_item_rect.position -= screen_rect;
@@ -3273,48 +2876,42 @@ void CanvasItemEditor::_update_scroll(float) {
editor->get_scene_root()->set_global_canvas_transform(transform);
viewport->update();
- viewport_base->update();
}
void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) {
List<Node *> selection = editor_selection->get_selected_node_list();
undo_redo->create_action(TTR("Change Anchors and Margins"));
+
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *c = Object::cast_to<Control>(E->get());
-
- undo_redo->add_do_method(c, "set_anchors_preset", p_preset);
- switch (p_preset) {
- case PRESET_TOP_LEFT:
- case PRESET_TOP_RIGHT:
- case PRESET_BOTTOM_LEFT:
- case PRESET_BOTTOM_RIGHT:
- case PRESET_CENTER_LEFT:
- case PRESET_CENTER_TOP:
- case PRESET_CENTER_RIGHT:
- case PRESET_CENTER_BOTTOM:
- case PRESET_CENTER:
- undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
- break;
- case PRESET_LEFT_WIDE:
- case PRESET_TOP_WIDE:
- case PRESET_RIGHT_WIDE:
- case PRESET_BOTTOM_WIDE:
- case PRESET_VCENTER_WIDE:
- case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
- undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
- break;
+ Control *control = Object::cast_to<Control>(E->get());
+ if (control) {
+ undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
+ break;
+ case PRESET_LEFT_WIDE:
+ case PRESET_TOP_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
+ break;
+ }
+ undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
}
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM));
}
undo_redo->commit_action();
@@ -3326,13 +2923,11 @@ void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
undo_redo->create_action(TTR("Change Anchors"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *c = Object::cast_to<Control>(E->get());
-
- undo_redo->add_do_method(c, "set_anchors_preset", p_preset);
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT));
- undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM));
+ Control *control = Object::cast_to<Control>(E->get());
+ if (control) {
+ undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
+ undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
+ }
}
undo_redo->commit_action();
@@ -3351,25 +2946,34 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
_update_scroll(0);
viewport->update();
- viewport_base->update();
}
-void CanvasItemEditor::_zoom_minus() {
+void CanvasItemEditor::_button_zoom_minus() {
_zoom_on_position(zoom / 2.0, viewport_scrollable->get_size() / 2.0);
}
-void CanvasItemEditor::_zoom_reset() {
+void CanvasItemEditor::_button_zoom_reset() {
_zoom_on_position(1.0, viewport_scrollable->get_size() / 2.0);
}
-void CanvasItemEditor::_zoom_plus() {
+void CanvasItemEditor::_button_zoom_plus() {
_zoom_on_position(zoom * 2.0, viewport_scrollable->get_size() / 2.0);
}
-void CanvasItemEditor::_toggle_snap(bool p_status) {
+void CanvasItemEditor::_button_toggle_snap(bool p_status) {
snap_active = p_status;
viewport->update();
- viewport_base->update();
+}
+
+void CanvasItemEditor::_button_tool_select(int p_index) {
+
+ ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, rotate_button, pivot_button, pan_button };
+ for (int i = 0; i < TOOL_MAX; i++) {
+ tb[i]->set_pressed(i == p_index);
+ }
+
+ viewport->update();
+ tool = (Tool)p_index;
}
void CanvasItemEditor::_popup_callback(int p_op) {
@@ -3382,7 +2986,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
view_menu->get_popup()->set_item_checked(idx, show_grid);
viewport->update();
- viewport_base->update();
} break;
case SNAP_USE_NODE_PARENT: {
snap_node_parent = !snap_node_parent;
@@ -3399,6 +3002,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
} break;
+ case SNAP_USE_NODE_CENTER: {
+ snap_node_center = !snap_node_center;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_center);
+ } break;
case SNAP_USE_OTHER_NODES: {
snap_other_nodes = !snap_other_nodes;
int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
@@ -3424,7 +3032,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
viewport->update();
- viewport_base->update();
} break;
case SNAP_USE_PIXEL: {
snap_pixel = !snap_pixel;
@@ -3452,26 +3059,19 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
view_menu->get_popup()->set_item_checked(idx, show_rulers);
viewport->update();
- viewport_base->update();
} break;
case SHOW_GUIDES: {
show_guides = !show_guides;
int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
view_menu->get_popup()->set_item_checked(idx, show_guides);
viewport->update();
- viewport_base->update();
} break;
-
case LOCK_SELECTED: {
-
List<Node *> selection = editor_selection->get_selected_node_list();
-
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
if (!canvas_item || !canvas_item->is_inside_tree())
continue;
-
if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
continue;
@@ -3481,35 +3081,25 @@ void CanvasItemEditor::_popup_callback(int p_op) {
viewport->update();
} break;
case UNLOCK_SELECTED: {
-
List<Node *> selection = editor_selection->get_selected_node_list();
-
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
if (!canvas_item || !canvas_item->is_inside_tree())
continue;
-
if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
continue;
canvas_item->set_meta("_edit_lock_", Variant());
emit_signal("item_lock_status_changed");
}
-
viewport->update();
-
} break;
case GROUP_SELECTED: {
-
List<Node *> selection = editor_selection->get_selected_node_list();
-
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
if (!canvas_item || !canvas_item->is_inside_tree())
continue;
-
if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
continue;
@@ -3519,26 +3109,19 @@ void CanvasItemEditor::_popup_callback(int p_op) {
viewport->update();
} break;
case UNGROUP_SELECTED: {
-
List<Node *> selection = editor_selection->get_selected_node_list();
-
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
if (!canvas_item || !canvas_item->is_inside_tree())
continue;
-
if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
continue;
canvas_item->set_meta("_edit_group_", Variant());
emit_signal("item_group_status_changed");
}
-
viewport->update();
-
} break;
-
case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: {
_set_anchors_and_margins_preset(PRESET_TOP_LEFT);
} break;
@@ -3723,28 +3306,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
key_scale = key_scale_button->is_pressed();
} break;
- /*
- case ANIM_INSERT_POS_ROT
- case ANIM_INSERT_POS_SCALE:
- case ANIM_INSERT_ROT_SCALE:
- case ANIM_INSERT_POS_ROT_SCALE: {
- static const bool key_toggles[7][3]={
- {true,false,false},
- {false,true,false},
- {false,false,true},
- {true,true,false},
- {true,false,true},
- {false,true,true},
- {true,true,true}
- };
- key_pos=key_toggles[p_op-ANIM_INSERT_POS][0];
- key_rot=key_toggles[p_op-ANIM_INSERT_POS][1];
- key_scale=key_toggles[p_op-ANIM_INSERT_POS][2];
- for(int i=ANIM_INSERT_POS;i<=ANIM_INSERT_POS_ROT_SCALE;i++) {
- int idx = animation_menu->get_popup()->get_item_index(i);
- animation_menu->get_popup()->set_item_checked(idx,i==p_op);
- }
- } break;*/
case ANIM_COPY_POSE: {
pose_clipboard.clear();
@@ -3823,9 +3384,9 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
ctrl->set_position(Point2());
/*
- if (key_scale)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
- */
+ if (key_scale)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
+ */
}
}
@@ -3974,20 +3535,18 @@ void CanvasItemEditor::_focus_selection(int p_op) {
void CanvasItemEditor::_bind_methods() {
- ClassDB::bind_method("_zoom_minus", &CanvasItemEditor::_zoom_minus);
- ClassDB::bind_method("_zoom_reset", &CanvasItemEditor::_zoom_reset);
- ClassDB::bind_method("_zoom_plus", &CanvasItemEditor::_zoom_plus);
- ClassDB::bind_method("_toggle_snap", &CanvasItemEditor::_toggle_snap);
+ ClassDB::bind_method("_button_zoom_minus", &CanvasItemEditor::_button_zoom_minus);
+ ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset);
+ ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
+ ClassDB::bind_method("_button_toggle_snap", &CanvasItemEditor::_button_toggle_snap);
ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
- ClassDB::bind_method("_tool_select", &CanvasItemEditor::_tool_select);
+ ClassDB::bind_method("_button_tool_select", &CanvasItemEditor::_button_tool_select);
ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed);
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
- ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base);
ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
- ClassDB::bind_method("_gui_input_viewport_base", &CanvasItemEditor::_gui_input_viewport_base);
ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
@@ -3997,11 +3556,172 @@ void CanvasItemEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_group_status_changed"));
}
+Dictionary CanvasItemEditor::get_state() const {
+
+ Dictionary state;
+ state["zoom"] = zoom;
+ state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value());
+ state["grid_offset"] = grid_offset;
+ state["grid_step"] = grid_step;
+ state["snap_rotation_offset"] = snap_rotation_offset;
+ state["snap_rotation_step"] = snap_rotation_step;
+ state["snap_active"] = snap_active;
+ state["snap_node_parent"] = snap_node_parent;
+ state["snap_node_anchors"] = snap_node_anchors;
+ state["snap_node_sides"] = snap_node_sides;
+ state["snap_node_center"] = snap_node_center;
+ state["snap_other_nodes"] = snap_other_nodes;
+ state["snap_grid"] = snap_grid;
+ state["snap_guides"] = snap_guides;
+ state["show_grid"] = show_grid;
+ state["show_rulers"] = show_rulers;
+ state["show_guides"] = show_guides;
+ state["show_helpers"] = show_helpers;
+ state["snap_rotation"] = snap_rotation;
+ state["snap_relative"] = snap_relative;
+ state["snap_pixel"] = snap_pixel;
+ state["skeleton_show_bones"] = skeleton_show_bones;
+ return state;
+}
+
+void CanvasItemEditor::set_state(const Dictionary &p_state) {
+
+ Dictionary state = p_state;
+ if (state.has("zoom")) {
+ zoom = p_state["zoom"];
+ }
+
+ if (state.has("ofs")) {
+ _update_scrollbars(); // i wonder how safe is calling this here..
+ Point2 ofs = p_state["ofs"];
+ h_scroll->set_value(ofs.x);
+ v_scroll->set_value(ofs.y);
+ }
+
+ if (state.has("grid_offset")) {
+ grid_offset = state["grid_offset"];
+ }
+
+ if (state.has("grid_step")) {
+ grid_step = state["grid_step"];
+ }
+
+ if (state.has("snap_rotation_step")) {
+ snap_rotation_step = state["snap_rotation_step"];
+ }
+
+ if (state.has("snap_rotation_offset")) {
+ snap_rotation_offset = state["snap_rotation_offset"];
+ }
+
+ if (state.has("snap_active")) {
+ snap_active = state["snap_active"];
+ snap_button->set_pressed(snap_active);
+ }
+
+ if (state.has("snap_node_parent")) {
+ snap_node_parent = state["snap_node_parent"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
+ }
+
+ if (state.has("snap_node_anchors")) {
+ snap_node_anchors = state["snap_node_anchors"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
+ }
+
+ if (state.has("snap_node_sides")) {
+ snap_node_sides = state["snap_node_sides"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
+ }
+
+ if (state.has("snap_node_center")) {
+ snap_node_center = state["snap_node_center"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_center);
+ }
+
+ if (state.has("snap_other_nodes")) {
+ snap_other_nodes = state["snap_other_nodes"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
+ smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
+ }
+
+ if (state.has("snap_guides")) {
+ snap_guides = state["snap_guides"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_guides);
+ }
+
+ if (state.has("snap_grid")) {
+ snap_grid = state["snap_grid"];
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
+ }
+
+ if (state.has("show_grid")) {
+ show_grid = state["show_grid"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
+ view_menu->get_popup()->set_item_checked(idx, show_grid);
+ }
+
+ if (state.has("show_rulers")) {
+ show_rulers = state["show_rulers"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
+ view_menu->get_popup()->set_item_checked(idx, show_rulers);
+ }
+
+ if (state.has("show_guides")) {
+ show_guides = state["show_guides"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
+ view_menu->get_popup()->set_item_checked(idx, show_guides);
+ }
+
+ if (state.has("show_helpers")) {
+ show_helpers = state["show_helpers"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
+ view_menu->get_popup()->set_item_checked(idx, show_helpers);
+ }
+
+ if (state.has("snap_rotation")) {
+ snap_rotation = state["snap_rotation"];
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
+ }
+
+ if (state.has("snap_relative")) {
+ snap_relative = state["snap_relative"];
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
+ }
+
+ if (state.has("snap_pixel")) {
+ snap_pixel = state["snap_pixel"];
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
+ }
+
+ if (state.has("skeleton_show_bones")) {
+ skeleton_show_bones = state["skeleton_show_bones"];
+ int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
+ skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
+ }
+
+ viewport->update();
+}
+
void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
hb->add_child(p_control);
}
+void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) {
+
+ hb->remove_child(p_control);
+}
+
HSplitContainer *CanvasItemEditor::get_palette_split() {
return palette_split;
@@ -4037,21 +3757,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
bottom_split->add_child(palette_split);
palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
- viewport_base = memnew(Control);
- palette_split->add_child(viewport_base);
- viewport_base->set_clip_contents(true);
- viewport_base->connect("draw", this, "_draw_viewport_base");
- viewport_base->connect("gui_input", this, "_gui_input_viewport_base");
- viewport_base->set_focus_mode(FOCUS_ALL);
- viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
- viewport_base->set_h_size_flags(SIZE_EXPAND_FILL);
-
viewport_scrollable = memnew(Control);
- viewport_base->add_child(viewport_scrollable);
+ palette_split->add_child(viewport_scrollable);
viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS);
- viewport_scrollable->set_draw_behind_parent(true);
- viewport_scrollable->set_anchors_and_margins_preset(Control::PRESET_WIDE);
- viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH));
+ viewport_scrollable->set_clip_contents(true);
+ viewport_scrollable->set_v_size_flags(SIZE_EXPAND_FILL);
+ viewport_scrollable->set_h_size_flags(SIZE_EXPAND_FILL);
ViewportContainer *scene_tree = memnew(ViewportContainer);
viewport_scrollable->add_child(scene_tree);
@@ -4064,6 +3775,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
viewport->set_mouse_filter(MOUSE_FILTER_PASS);
viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
viewport->set_clip_contents(true);
+ viewport->set_focus_mode(FOCUS_ALL);
viewport->connect("draw", this, "_draw_viewport");
viewport->connect("gui_input", this, "_gui_input_viewport");
@@ -4077,33 +3789,32 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED);
v_scroll->hide();
- HBoxContainer *zoom_hb = memnew(HBoxContainer);
+ zoom_hb = memnew(HBoxContainer);
viewport->add_child(zoom_hb);
zoom_hb->set_begin(Point2(5, 5));
zoom_minus = memnew(ToolButton);
zoom_hb->add_child(zoom_minus);
- zoom_minus->connect("pressed", this, "_zoom_minus");
+ zoom_minus->connect("pressed", this, "_button_zoom_minus");
zoom_minus->set_focus_mode(FOCUS_NONE);
zoom_reset = memnew(ToolButton);
zoom_hb->add_child(zoom_reset);
- zoom_reset->connect("pressed", this, "_zoom_reset");
+ zoom_reset->connect("pressed", this, "_button_zoom_reset");
zoom_reset->set_focus_mode(FOCUS_NONE);
zoom_plus = memnew(ToolButton);
zoom_hb->add_child(zoom_plus);
- zoom_plus->connect("pressed", this, "_zoom_plus");
+ zoom_plus->connect("pressed", this, "_button_zoom_plus");
zoom_plus->set_focus_mode(FOCUS_NONE);
updating_scroll = false;
- handle_len = 10;
first_update = true;
select_button = memnew(ToolButton);
hb->add_child(select_button);
select_button->set_toggle_mode(true);
- select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_SELECT));
+ select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECT));
select_button->set_pressed(true);
select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q));
select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection"));
@@ -4111,14 +3822,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
move_button = memnew(ToolButton);
hb->add_child(move_button);
move_button->set_toggle_mode(true);
- move_button->connect("pressed", this, "_tool_select", make_binds(TOOL_MOVE));
+ move_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_MOVE));
move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W));
move_button->set_tooltip(TTR("Move Mode"));
rotate_button = memnew(ToolButton);
hb->add_child(rotate_button);
rotate_button->set_toggle_mode(true);
- rotate_button->connect("pressed", this, "_tool_select", make_binds(TOOL_ROTATE));
+ rotate_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_ROTATE));
rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E));
rotate_button->set_tooltip(TTR("Rotate Mode"));
@@ -4127,19 +3838,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
list_select_button = memnew(ToolButton);
hb->add_child(list_select_button);
list_select_button->set_toggle_mode(true);
- list_select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_LIST_SELECT));
+ list_select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_LIST_SELECT));
list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
pivot_button = memnew(ToolButton);
hb->add_child(pivot_button);
pivot_button->set_toggle_mode(true);
- pivot_button->connect("pressed", this, "_tool_select", make_binds(TOOL_EDIT_PIVOT));
+ pivot_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_EDIT_PIVOT));
pivot_button->set_tooltip(TTR("Click to change object's rotation pivot."));
pan_button = memnew(ToolButton);
hb->add_child(pan_button);
pan_button->set_toggle_mode(true);
- pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN));
+ pan_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PAN));
pan_button->set_tooltip(TTR("Pan Mode"));
hb->add_child(memnew(VSeparator));
@@ -4147,7 +3858,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_button = memnew(ToolButton);
hb->add_child(snap_button);
snap_button->set_toggle_mode(true);
- snap_button->connect("toggled", this, "_toggle_snap");
+ snap_button->connect("toggled", this, "_button_toggle_snap");
snap_button->set_tooltip(TTR("Toggles snapping"));
snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_S));
@@ -4174,6 +3885,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to parent")), SNAP_USE_NODE_PARENT);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_center", TTR("Snap to node center")), SNAP_USE_NODE_CENTER);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to guides")), SNAP_USE_GUIDES);
@@ -4225,9 +3937,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = view_menu->get_popup();
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show helpers"), KEY_H), SHOW_HELPERS);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show rulers"), KEY_R), SHOW_RULERS);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show guides"), KEY_Y), SHOW_GUIDES);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers"), KEY_R), SHOW_RULERS);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
@@ -4305,9 +4017,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
selection_menu->connect("id_pressed", this, "_selection_result_pressed");
selection_menu->connect("popup_hide", this, "_selection_menu_hide");
- drag_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/drag_pivot", TTR("Drag pivot from mouse position"), KEY_MASK_SHIFT | KEY_V);
- set_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/set_pivot", TTR("Set pivot at mouse position"), KEY_V);
-
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
@@ -4315,9 +4024,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
key_rot = true;
key_scale = false;
- edited_guide_pos = Point2();
- edited_guide_index = -1;
-
show_grid = false;
show_helpers = false;
show_rulers = true;
@@ -4332,6 +4038,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_node_parent = true;
snap_node_anchors = true;
snap_node_sides = true;
+ snap_node_center = true;
snap_other_nodes = true;
snap_grid = true;
snap_guides = true;
@@ -4339,17 +4046,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_pixel = false;
skeleton_show_bones = true;
skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
- box_selecting = false;
- //zoom=0.5;
singleton = this;
set_process_unhandled_key_input(true);
- can_move_pivot = false;
- drag = DRAG_NONE;
+
+ drag_type = DRAG_NONE;
+ drag_from = Vector2();
+ drag_to = Vector2();
+ dragged_guide_pos = Point2();
+ dragged_guide_index = -1;
+
bone_last_frame = 0;
- additive_selection = false;
- // Update the menus checkboxes
+ // Update the menus' checkboxes
call_deferred("set_state", get_state());
}
@@ -4372,7 +4081,7 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) {
canvas_item_editor->show();
canvas_item_editor->set_physics_process(true);
VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
- canvas_item_editor->viewport_base->grab_focus();
+ canvas_item_editor->viewport->grab_focus();
} else {
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index ace87f9fe2..adf203cf3d 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -50,9 +50,6 @@ class CanvasItemEditorSelectedItem : public Object {
GDCLASS(CanvasItemEditorSelectedItem, Object);
public:
- Variant undo_state;
- Vector2 undo_pivot;
-
Transform2D prev_xform;
float prev_rot;
Rect2 prev_rect;
@@ -62,6 +59,11 @@ public:
Transform2D pre_drag_xform;
Rect2 pre_drag_rect;
+ List<float> pre_drag_bones_length;
+ List<Dictionary> pre_drag_bones_undo_state;
+
+ Dictionary undo_state;
+
CanvasItemEditorSelectedItem() { prev_rot = 0; }
};
@@ -86,6 +88,7 @@ class CanvasItemEditor : public VBoxContainer {
SNAP_USE_NODE_PARENT,
SNAP_USE_NODE_ANCHORS,
SNAP_USE_NODE_SIDES,
+ SNAP_USE_NODE_CENTER,
SNAP_USE_OTHER_NODES,
SNAP_USE_GRID,
SNAP_USE_GUIDES,
@@ -169,6 +172,7 @@ class CanvasItemEditor : public VBoxContainer {
enum DragType {
DRAG_NONE,
+ DRAG_BOX_SELECTION,
DRAG_LEFT,
DRAG_TOP_LEFT,
DRAG_TOP,
@@ -185,29 +189,20 @@ class CanvasItemEditor : public VBoxContainer {
DRAG_ALL,
DRAG_ROTATE,
DRAG_PIVOT,
- DRAG_NODE_2D,
DRAG_V_GUIDE,
DRAG_H_GUIDE,
DRAG_DOUBLE_GUIDE,
- };
-
- enum KeyMoveMODE {
- MOVE_VIEW_BASE,
- MOVE_LOCAL_BASE,
- MOVE_LOCAL_WITH_ROT
+ DRAG_KEY_MOVE
};
EditorSelection *editor_selection;
- bool additive_selection;
+ bool selection_menu_additive_selection;
Tool tool;
bool first_update;
Control *viewport;
- Control *viewport_base;
Control *viewport_scrollable;
- bool can_move_pivot;
-
HScrollBar *h_scroll;
VScrollBar *v_scroll;
HBoxContainer *hb;
@@ -233,6 +228,7 @@ class CanvasItemEditor : public VBoxContainer {
bool snap_node_parent;
bool snap_node_anchors;
bool snap_node_sides;
+ bool snap_node_center;
bool snap_other_nodes;
bool snap_grid;
bool snap_guides;
@@ -240,14 +236,10 @@ class CanvasItemEditor : public VBoxContainer {
bool snap_relative;
bool snap_pixel;
bool skeleton_show_bones;
- bool box_selecting;
- Point2 box_selecting_to;
bool key_pos;
bool key_rot;
bool key_scale;
- void _tool_select(int p_index);
-
MenuOption last_option;
struct _SelectResult {
@@ -267,33 +259,17 @@ class CanvasItemEditor : public VBoxContainer {
Transform2D xform;
Vector2 from;
Vector2 to;
- ObjectID bone;
uint64_t last_pass;
};
-
uint64_t bone_last_frame;
Map<ObjectID, BoneList> bone_list;
- Transform2D bone_orig_xform;
-
- struct BoneIK {
-
- Variant orig_state;
- Vector2 pos;
- float len;
- Node2D *node;
- };
-
- List<BoneIK> bone_ik_list;
-
struct PoseClipboard {
-
Vector2 pos;
Vector2 scale;
float rot;
ObjectID id;
};
-
List<PoseClipboard> pose_clipboard;
ToolButton *select_button;
@@ -333,16 +309,17 @@ class CanvasItemEditor : public VBoxContainer {
Control *top_ruler;
Control *left_ruler;
- //PopupMenu *popup;
- DragType drag;
+ DragType drag_type;
Point2 drag_from;
- Point2 drag_point_from;
+ Point2 drag_to;
+ Point2 drag_rotation_center;
+ List<CanvasItem *> drag_selection;
+ int dragged_guide_index;
+ Point2 dragged_guide_pos;
+
bool updating_value_dialog;
- Point2 display_rotate_from;
- Point2 display_rotate_to;
- int edited_guide_index;
- Point2 edited_guide_pos;
+ Point2 box_selecting_to;
Ref<StyleBoxTexture> select_sb;
Ref<Texture> select_handle;
@@ -353,28 +330,19 @@ class CanvasItemEditor : public VBoxContainer {
Ref<ShortCut> multiply_grid_step_shortcut;
Ref<ShortCut> divide_grid_step_shortcut;
- int handle_len;
- bool _is_part_of_subscene(CanvasItem *p_item);
- void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit = 0);
- void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, List<CanvasItem *> *r_items);
-
- void _select_click_on_empty_area(Point2 p_click_pos, bool p_append, bool p_box_selection);
- bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag);
+ void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
+ void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
+ bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append);
ConfirmationDialog *snap_dialog;
CanvasItem *ref_item;
- void _edit_set_pivot(const Vector2 &mouse_pos);
void _add_canvas_item(CanvasItem *p_canvas_item);
- void _remove_canvas_item(CanvasItem *p_canvas_item);
- void _clear_canvas_items();
- void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode);
- void _list_select(const Ref<InputEventMouseButton> &b);
- DragType _get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
- void _prepare_drag(const Point2 &p_click_pos);
- DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
+ void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false);
+ void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false);
+ void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false);
Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor);
Vector2 _position_to_anchor(const Control *p_control, Vector2 position);
@@ -383,27 +351,21 @@ class CanvasItemEditor : public VBoxContainer {
bool updating_scroll;
void _update_scroll(float);
void _update_scrollbars();
- void _update_cursor();
- void incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric);
- void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric);
-
void _append_canvas_item(CanvasItem *p_item);
void _snap_changed();
void _selection_result_pressed(int);
void _selection_menu_hide();
UndoRedo *undo_redo;
-
- Point2 _find_topleftmost_point();
-
void _build_bones_list(Node *p_node);
- void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform);
+ List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
+ Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
+ void _expand_encompassing_rect_using_children(Rect2 &p_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
+ Rect2 _get_scene_encompassing_rect();
Object *_get_editor_data(Object *p_what);
- CanvasItem *_get_single_item();
- int get_item_count();
void _keying_changed();
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
@@ -411,6 +373,7 @@ class CanvasItemEditor : public VBoxContainer {
void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side);
void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side);
void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side);
+ void _draw_straight_line(Point2 p_from, Point2 p_to, Color p_color);
void _draw_rulers();
void _draw_guides();
@@ -422,13 +385,23 @@ class CanvasItemEditor : public VBoxContainer {
void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform);
void _draw_viewport();
- void _draw_viewport_base();
+
+ bool _gui_input_anchors(const Ref<InputEvent> &p_event);
+ bool _gui_input_move(const Ref<InputEvent> &p_event);
+ bool _gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event);
+ bool _gui_input_pivot(const Ref<InputEvent> &p_event);
+ bool _gui_input_resize(const Ref<InputEvent> &p_event);
+ bool _gui_input_rotate(const Ref<InputEvent> &p_event);
+ bool _gui_input_select(const Ref<InputEvent> &p_event);
+ bool _gui_input_zoom_or_pan(const Ref<InputEvent> &p_event);
+ bool _gui_input_rulers_and_guides(const Ref<InputEvent> &p_event);
void _gui_input_viewport(const Ref<InputEvent> &p_event);
- void _gui_input_viewport_base(const Ref<InputEvent> &p_event);
void _focus_selection(int p_op);
+ void _solve_IK(Node2D *leaf_node, Point2 target_position);
+
void _snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius = 10.0);
void _snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0);
void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap = NULL);
@@ -437,12 +410,13 @@ class CanvasItemEditor : public VBoxContainer {
void _set_margins_preset(Control::LayoutPreset p_preset);
void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset);
+ HBoxContainer *zoom_hb;
void _zoom_on_position(float p_zoom, Point2 p_position = Point2());
- void _zoom_minus();
- void _zoom_reset();
- void _zoom_plus();
-
- void _toggle_snap(bool p_status);
+ void _button_zoom_minus();
+ void _button_zoom_reset();
+ void _button_zoom_plus();
+ void _button_toggle_snap(bool p_status);
+ void _button_tool_select(int p_index);
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
@@ -494,9 +468,10 @@ public:
SNAP_NODE_PARENT = 1 << 3,
SNAP_NODE_ANCHORS = 1 << 4,
SNAP_NODE_SIDES = 1 << 5,
- SNAP_OTHER_NODES = 1 << 6,
+ SNAP_NODE_CENTER = 1 << 6,
+ SNAP_OTHER_NODES = 1 << 7,
- SNAP_DEFAULT = 0x07,
+ SNAP_DEFAULT = SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL,
};
Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0);
@@ -509,6 +484,7 @@ public:
void set_state(const Dictionary &p_state);
void add_control_to_menu_panel(Control *p_control);
+ void remove_control_from_menu_panel(Control *p_control);
HSplitContainer *get_palette_split();
VSplitContainer *get_bottom_split();
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 215964235e..47d730cdf1 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -30,6 +30,7 @@
#include "editor_preview_plugins.h"
+#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "io/file_access_memory.h"
@@ -39,6 +40,38 @@
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
+static void post_process_preview(Ref<Image> p_image) {
+
+ if (p_image->get_format() != Image::FORMAT_RGBA8)
+ p_image->convert(Image::FORMAT_RGBA8);
+
+ p_image->lock();
+
+ const int w = p_image->get_width();
+ const int h = p_image->get_height();
+
+ const int r = MIN(w, h) / 32;
+ const int r2 = r * r;
+ Color transparent = Color(0, 0, 0, 0);
+
+ for (int i = 0; i < r; i++) {
+ for (int j = 0; j < r; j++) {
+ int dx = i - r;
+ int dy = j - r;
+ if (dx * dx + dy * dy > r2) {
+ p_image->set_pixel(i, j, transparent);
+ p_image->set_pixel(w - 1 - i, j, transparent);
+ p_image->set_pixel(w - 1 - i, h - 1 - j, transparent);
+ p_image->set_pixel(i, h - 1 - j, transparent);
+ } else {
+ break;
+ }
+ }
+ }
+
+ p_image->unlock();
+}
+
bool EditorTexturePreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Texture");
@@ -90,6 +123,7 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) {
}
img->resize(width, height);
+ post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
@@ -162,6 +196,7 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) {
}
img->resize(width, height);
+ post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
@@ -203,6 +238,7 @@ Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
+ post_process_preview(img);
ptex->create_from_image(img, 0);
return ptex;
@@ -258,6 +294,7 @@ Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) {
thumbnail_size *= EDSCALE;
img->convert(Image::FORMAT_RGBA8);
img->resize(thumbnail_size, thumbnail_size);
+ post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
ptex->create_from_image(img, 0);
return ptex;
@@ -426,19 +463,36 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
img->create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8);
Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
- bg_color.a = 1.0;
Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
+ if (EditorSettings::get_singleton()->get("text_editor/theme/color_theme") == "Adaptive") {
+ Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme();
+
+ bg_color = tm->get_color("text_editor/highlighting/background_color", "Editor");
+ keyword_color = tm->get_color("text_editor/highlighting/keyword_color", "Editor");
+ text_color = tm->get_color("text_editor/highlighting/text_color", "Editor");
+ symbol_color = tm->get_color("text_editor/highlighting/symbol_color", "Editor");
+ }
+
img->lock();
+ if (bg_color.a == 0)
+ bg_color = Color(0, 0, 0, 0);
+ bg_color.a = MAX(bg_color.a, 0.2); // some background
+
for (int i = 0; i < thumbnail_size; i++) {
for (int j = 0; j < thumbnail_size; j++) {
img->set_pixel(i, j, bg_color);
}
}
+ const int x0 = thumbnail_size / 8;
+ const int y0 = thumbnail_size / 8;
+ const int available_height = thumbnail_size - 2 * y0;
+ col = x0;
+
bool prev_is_text = false;
bool in_keyword = false;
for (int i = 0; i < code.length(); i++) {
@@ -471,8 +525,8 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
Color ul = color;
ul.a *= 0.5;
- img->set_pixel(col, line * 2, bg_color.blend(ul));
- img->set_pixel(col, line * 2 + 1, color);
+ img->set_pixel(col, y0 + line * 2, bg_color.blend(ul));
+ img->set_pixel(col, y0 + line * 2 + 1, color);
prev_is_text = _is_text_char(c);
}
@@ -482,9 +536,9 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
in_keyword = false;
if (c == '\n') {
- col = 0;
+ col = x0;
line++;
- if (line >= thumbnail_size / 2)
+ if (line >= available_height / 2)
break;
} else if (c == '\t') {
col += 3;
@@ -495,6 +549,8 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
img->unlock();
+ post_process_preview(img);
+
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
ptex->create_from_image(img, 0);
@@ -762,6 +818,7 @@ Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
}
imgdata = PoolVector<uint8_t>::Write();
+ post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
ptex->create_from_image(Image(w,h,0,Image::FORMAT_RGB8,img),0);
@@ -831,6 +888,7 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) {
thumbnail_size *= EDSCALE;
img->convert(Image::FORMAT_RGBA8);
img->resize(thumbnail_size, thumbnail_size);
+ post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
ptex->create_from_image(img, 0);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index a47cb40240..c6e8ec1a2b 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -229,17 +229,34 @@ void ResourcePreloaderEditor::_update_library() {
ERR_CONTINUE(r.is_null());
ti->set_tooltip(0, r->get_path());
- String type = r->get_class();
- ti->set_text(1, type);
+ ti->set_text(1, r->get_path());
+ ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
+ ti->set_tooltip(1, TTR("Instance:") + " " + r->get_path() + "\n" + TTR("Type:") + " " + r->get_class());
+ ti->set_editable(1, false);
ti->set_selectable(1, false);
+ String type = r->get_class();
+ ti->set_text(2, type);
+ ti->set_selectable(2, false);
if (has_icon(type, "EditorIcons"))
- ti->set_icon(1, get_icon(type, "EditorIcons"));
+ ti->set_icon(2, get_icon(type, "EditorIcons"));
}
//player->add_resource("default",resource);
}
+void ResourcePreloaderEditor::_cell_button_pressed(Object *p_item, int p_column, int p_id) {
+
+ TreeItem *item = Object::cast_to<TreeItem>(p_item);
+ ERR_FAIL_COND(!item);
+
+ String rpath = item->get_text(p_column);
+
+ if (p_id == BUTTON_SUBSCENE) {
+ EditorInterface::get_singleton()->open_scene_from_path(rpath);
+ }
+}
+
void ResourcePreloaderEditor::edit(ResourcePreloader *p_preloader) {
preloader = p_preloader;
@@ -354,6 +371,7 @@ void ResourcePreloaderEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_delete_confirm_pressed"), &ResourcePreloaderEditor::_delete_confirm_pressed);
ClassDB::bind_method(D_METHOD("_files_load_request"), &ResourcePreloaderEditor::_files_load_request);
ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library);
+ ClassDB::bind_method(D_METHOD("_cell_button_pressed"), &ResourcePreloaderEditor::_cell_button_pressed);
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw);
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw);
@@ -385,11 +403,14 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
add_child(file);
tree = memnew(Tree);
- tree->set_columns(2);
+ tree->connect("button_pressed", this, "_cell_button_pressed");
+ tree->set_columns(3);
tree->set_column_min_width(0, 3);
tree->set_column_min_width(1, 1);
+ tree->set_column_min_width(2, 1);
tree->set_column_expand(0, true);
tree->set_column_expand(1, true);
+ tree->set_column_expand(2, true);
tree->set_v_size_flags(SIZE_EXPAND_FILL);
tree->set_drag_forwarding(this);
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index 6e04c70741..e737157785 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -42,6 +42,10 @@ class ResourcePreloaderEditor : public PanelContainer {
GDCLASS(ResourcePreloaderEditor, PanelContainer);
+ enum {
+ BUTTON_SUBSCENE = 0,
+ };
+
Button *load;
Button *_delete;
Button *paste;
@@ -61,6 +65,7 @@ class ResourcePreloaderEditor : public PanelContainer {
void _delete_pressed();
void _delete_confirm_pressed();
void _update_library();
+ void _cell_button_pressed(Object *p_item, int p_column, int p_id);
void _item_edited();
UndoRedo *undo_redo;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index d18422c0c0..a2641738f3 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -148,8 +148,6 @@ public:
}
};
-#define SORT_SCRIPT_LIST
-
void ScriptEditorQuickOpen::popup(const Vector<String> &p_functions, bool p_dontclear) {
popup_centered_ratio(0.6);
@@ -429,36 +427,32 @@ void ScriptEditor::_add_recent_script(String p_path) {
return;
}
- // remove if already stored
- int already_recent = previous_scripts.find(p_path);
- if (already_recent >= 0) {
- previous_scripts.remove(already_recent);
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array());
+ if (rc.find(p_path) != -1) {
+ rc.erase(p_path);
+ }
+ rc.push_front(p_path);
+ if (rc.size() > 10) {
+ rc.resize(10);
}
- // add to list
- previous_scripts.insert(0, p_path);
-
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", rc);
_update_recent_scripts();
}
void ScriptEditor::_update_recent_scripts() {
- // make sure we don't exceed max size
- const int max_history = EDITOR_DEF("text_editor/files/maximum_recent_files", 20);
- if (previous_scripts.size() > max_history) {
- previous_scripts.resize(max_history);
- }
-
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array());
recent_scripts->clear();
recent_scripts->add_shortcut(ED_SHORTCUT("script_editor/open_recent", TTR("Open Recent"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T));
recent_scripts->add_separator();
- const int max_shown = 8;
- for (int i = 0; i < previous_scripts.size() && i <= max_shown; i++) {
- String path = previous_scripts.get(i);
- // just show script name and last dir
- recent_scripts->add_item(path.get_slice("/", path.get_slice_count("/") - 2) + "/" + path.get_file());
+ String path;
+ for (int i = 0; i < rc.size(); i++) {
+
+ path = rc[i];
+ recent_scripts->add_item(path.replace("res://", ""));
}
recent_scripts->add_separator();
@@ -471,7 +465,7 @@ void ScriptEditor::_open_recent_script(int p_idx) {
// clear button
if (p_idx == recent_scripts->get_item_count() - 1) {
- previous_scripts.clear();
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", Array());
call_deferred("_update_recent_scripts");
return;
}
@@ -481,22 +475,34 @@ void ScriptEditor::_open_recent_script(int p_idx) {
p_idx -= 2;
}
- if (p_idx < previous_scripts.size() && p_idx >= 0) {
+ Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array());
+ ERR_FAIL_INDEX(p_idx, rc.size());
- String path = previous_scripts.get(p_idx);
- // if its not on disk its a help file or deleted
- if (FileAccess::exists(path)) {
- Ref<Script> script = ResourceLoader::load(path);
- if (script.is_valid()) {
- edit(script, true);
- }
- // if it's a path then its most likely a delted file not help
- } else if (!path.is_resource_file()) {
- _help_class_open(path);
+ String path = rc[p_idx];
+ // if its not on disk its a help file or deleted
+ if (FileAccess::exists(path)) {
+ Ref<Script> script = ResourceLoader::load(path);
+ if (script.is_valid()) {
+ edit(script, true);
+ return;
}
- previous_scripts.remove(p_idx);
- _update_recent_scripts();
+
+ // if it's a path then its most likely a deleted file not help
+ } else if (!path.is_resource_file()) {
+ _help_class_open(path);
+ return;
}
+
+ rc.remove(p_idx);
+ EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", rc);
+ _update_recent_scripts();
+ _show_error_dialog(path);
+}
+
+void ScriptEditor::_show_error_dialog(String p_path) {
+
+ error_dialog->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_path));
+ error_dialog->popup_centered_minsize();
}
void ScriptEditor::_close_tab(int p_idx, bool p_save) {
@@ -508,14 +514,10 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) {
Node *tselected = tab_container->get_child(selected);
ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
if (current) {
- _add_recent_script(current->get_edited_script()->get_path());
if (p_save) {
apply_scripts();
}
notify_script_close(current->get_edited_script());
- } else {
- EditorHelp *help = Object::cast_to<EditorHelp>(tab_container->get_child(selected));
- _add_recent_script(help->get_class());
}
// roll back to previous tab
@@ -1328,11 +1330,12 @@ void ScriptEditor::_members_overview_selected(int p_idx) {
if (!se) {
return;
}
- // Go to the member's line and reset the cursor column. We can't just change scroll_position
- // directly, since code might be folded.
+ // Go to the member's line and reset the cursor column. We can't change scroll_position
+ // directly until we have gone to the line first, since code might be folded.
se->goto_line(members_overview->get_item_metadata(p_idx));
Dictionary state = se->get_edit_state();
state["column"] = 0;
+ state["scroll_position"] = members_overview->get_item_metadata(p_idx);
se->set_edit_state(state);
}
@@ -1573,6 +1576,9 @@ void ScriptEditor::_update_script_names() {
case SORT_BY_PATH: {
sd.sort_key = path;
} break;
+ case SORT_BY_NONE: {
+ sd.sort_key = "";
+ } break;
}
switch (display_as) {
@@ -1690,28 +1696,42 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool
String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path");
String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags");
- Dictionary keys;
- keys["project"] = ProjectSettings::get_singleton()->get_resource_path();
- keys["file"] = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
- keys["line"] = p_line >= 0 ? p_line : 0;
- keys["col"] = p_col;
-
- flags = flags.format(keys).strip_edges().replace("\\\\", "\\");
-
List<String> args;
if (flags.size()) {
- int from = 0, to = 0;
+ String project_path = ProjectSettings::get_singleton()->get_resource_path();
+ String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
+
+ flags = flags.replacen("{line}", itos(p_line > 0 ? p_line : 0));
+ flags = flags.replacen("{col}", itos(p_col));
+ flags = flags.strip_edges().replace("\\\\", "\\");
+
+ int from = 0;
+ int num_chars = 0;
bool inside_quotes = false;
+
for (int i = 0; i < flags.size(); i++) {
+
if (flags[i] == '"' && (!i || flags[i - 1] != '\\')) {
+
+ if (!inside_quotes) {
+ from++;
+ }
inside_quotes = !inside_quotes;
+
} else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) {
- args.push_back(flags.substr(from, to));
+
+ String arg = flags.substr(from, num_chars);
+
+ // do path replacement here, else there will be issues with spaces and quotes
+ arg = arg.replacen("{project}", project_path);
+ arg = arg.replacen("{file}", script_path);
+ args.push_back(arg);
+
from = i + 1;
- to = 0;
+ num_chars = 0;
} else {
- to++;
+ num_chars++;
}
}
}
@@ -1787,6 +1807,7 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool
se->goto_line(p_line - 1);
notify_script_changed(p_script);
+ _add_recent_script(p_script->get_path());
return true;
}
@@ -2304,6 +2325,7 @@ void ScriptEditor::_help_class_open(const String &p_class) {
_go_to_tab(tab_container->get_tab_count() - 1);
eh->go_to_class(p_class, 0);
eh->connect("go_to_help", this, "_help_class_goto");
+ _add_recent_script(p_class);
_update_script_names();
_save_layout();
}
@@ -2332,6 +2354,7 @@ void ScriptEditor::_help_class_goto(const String &p_desc) {
_go_to_tab(tab_container->get_tab_count() - 1);
eh->go_to_help(p_desc);
eh->connect("go_to_help", this, "_help_class_goto");
+ _add_recent_script(eh->get_class());
_update_script_names();
_save_layout();
}
@@ -2586,11 +2609,13 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
members_overview = memnew(ItemList);
list_split->add_child(members_overview);
+ members_overview->set_allow_reselect(true);
members_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing
members_overview->set_v_size_flags(SIZE_EXPAND_FILL);
help_overview = memnew(ItemList);
list_split->add_child(help_overview);
+ help_overview->set_allow_reselect(true);
help_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing
help_overview->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -2738,6 +2763,10 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
add_child(file_dialog);
file_dialog->connect("file_selected", this, "_file_dialog_action");
+ error_dialog = memnew(AcceptDialog);
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("I see.."));
+
debugger = memnew(ScriptEditorDebugger(editor));
debugger->connect("goto_script_line", this, "_goto_script_line");
debugger->connect("show_debugger", this, "_show_debugger");
@@ -2900,7 +2929,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size", 15);
EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.3));
EDITOR_DEF("text_editor/open_scripts/group_help_pages", true);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path"));
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path,None"));
EDITOR_DEF("text_editor/open_scripts/sort_scripts_by", 0);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/list_script_names_as", PROPERTY_HINT_ENUM, "Name,Parent Directory And Name,Full Path"));
EDITOR_DEF("text_editor/open_scripts/list_script_names_as", 0);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index e60e4cf8c0..a5531c96b5 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -165,6 +165,7 @@ class ScriptEditor : public PanelContainer {
enum ScriptSortBy {
SORT_BY_NAME,
SORT_BY_PATH,
+ SORT_BY_NONE
};
enum ScriptListName {
@@ -198,6 +199,7 @@ class ScriptEditor : public PanelContainer {
VSplitContainer *list_split;
TabContainer *tab_container;
EditorFileDialog *file_dialog;
+ AcceptDialog *error_dialog;
ConfirmationDialog *erase_tab_confirm;
ScriptCreateDialog *script_create_dialog;
ScriptEditorDebugger *debugger;
@@ -227,8 +229,6 @@ class ScriptEditor : public PanelContainer {
Vector<ScriptHistory> history;
int history_pos;
- Vector<String> previous_scripts;
-
EditorHelpIndex *help_index;
void _tab_changed(int p_which);
@@ -250,6 +250,8 @@ class ScriptEditor : public PanelContainer {
void _update_recent_scripts();
void _open_recent_script(int p_idx);
+ void _show_error_dialog(String p_path);
+
void _close_tab(int p_idx, bool p_save = true);
void _close_current_tab();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index a3728a1d46..aeba0ff930 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -519,6 +519,7 @@ void ScriptTextEditor::tag_saved_version() {
void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
TextEdit *tx = code_editor->get_text_edit();
+ tx->deselect();
tx->unfold_line(p_line);
tx->call_deferred("cursor_set_line", p_line);
}
@@ -934,13 +935,27 @@ void ScriptTextEditor::_edit_option(int p_op) {
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
-
tx->begin_complex_operation();
- int line = tx->cursor_get_line();
- tx->set_line(tx->cursor_get_line(), "");
- tx->backspace_at_cursor();
- tx->unfold_line(line);
- tx->cursor_set_line(line);
+ if (tx->is_selection_active()) {
+ int to_line = tx->get_selection_to_line();
+ int from_line = tx->get_selection_from_line();
+ int count = Math::abs(to_line - from_line) + 1;
+ while (count) {
+ tx->set_line(tx->cursor_get_line(), "");
+ tx->backspace_at_cursor();
+ count--;
+ if (count)
+ tx->unfold_line(from_line);
+ }
+ tx->cursor_set_line(from_line - 1);
+ tx->deselect();
+ } else {
+ int line = tx->cursor_get_line();
+ tx->set_line(tx->cursor_get_line(), "");
+ tx->backspace_at_cursor();
+ tx->unfold_line(line);
+ tx->cursor_set_line(line);
+ }
tx->end_complex_operation();
} break;
case EDIT_CLONE_DOWN: {
@@ -1283,12 +1298,9 @@ Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_fro
bool ScriptTextEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
Dictionary d = p_data;
- if (d.has("type") &&
- (
-
- String(d["type"]) == "resource" ||
- String(d["type"]) == "files" ||
- String(d["type"]) == "nodes")) {
+ if (d.has("type") && (String(d["type"]) == "resource" ||
+ String(d["type"]) == "files" ||
+ String(d["type"]) == "nodes")) {
return true;
}
@@ -1329,6 +1341,10 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
Dictionary d = p_data;
+ TextEdit *te = code_editor->get_text_edit();
+ int row, col;
+ te->_get_mouse_pos(p_point, row, col);
+
if (d.has("type") && String(d["type"]) == "resource") {
Ref<Resource> res = d["resource"];
@@ -1341,7 +1357,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
return;
}
- code_editor->get_text_edit()->insert_text_at_cursor(res->get_path());
+ te->cursor_set_line(row);
+ te->cursor_set_column(col);
+ te->insert_text_at_cursor(res->get_path());
}
if (d.has("type") && String(d["type"]) == "files") {
@@ -1356,7 +1374,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
}
- code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
+ te->cursor_set_line(row);
+ te->cursor_set_column(col);
+ te->insert_text_at_cursor(text_to_drop);
}
if (d.has("type") && String(d["type"]) == "nodes") {
@@ -1385,7 +1405,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
text_to_drop += "\"" + path.c_escape() + "\"";
}
- code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
+ te->cursor_set_line(row);
+ te->cursor_set_column(col);
+ te->insert_text_at_cursor(text_to_drop);
}
}
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 5e8eb06556..63762651d7 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -318,6 +318,9 @@ void SpatialEditorViewport::_select(Spatial *p_node, bool p_append, bool p_singl
editor_selection->clear();
editor_selection->add_node(p_node);
+ if (Engine::get_singleton()->is_editor_hint())
+ editor->call("edit_node", p_node);
+
} else {
if (editor_selection->is_selected(p_node) && p_single) {
@@ -3827,9 +3830,6 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) {
si->sbox_instance = VisualServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario());
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF);
- if (Engine::get_singleton()->is_editor_hint())
- editor->call("edit_node", sp);
-
return si;
}
@@ -4778,6 +4778,11 @@ void SpatialEditor::add_control_to_menu_panel(Control *p_control) {
hbc_menu->add_child(p_control);
}
+void SpatialEditor::remove_control_from_menu_panel(Control *p_control) {
+
+ hbc_menu->remove_child(p_control);
+}
+
void SpatialEditor::set_can_preview(Camera *p_preview) {
for (int i = 0; i < 4; i++) {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index e12f7affb7..55866cac99 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -605,6 +605,7 @@ public:
UndoRedo *get_undo_redo() { return undo_redo; }
void add_control_to_menu_panel(Control *p_control);
+ void remove_control_from_menu_panel(Control *p_control);
VSplitContainer *get_shader_split();
HSplitContainer *get_palette_split();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 7a4eee0344..d8d0a6f013 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -398,8 +398,6 @@ void SpriteFramesEditor::_animation_add() {
animations->grab_focus();
}
void SpriteFramesEditor::_animation_remove() {
-
- //fuck everything
if (updating)
return;
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 36a578037e..e891850870 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -75,6 +75,9 @@ void TextureEditor::_notification(int p_what) {
// In the case of CurveTextures we know they are 1 in height, so fill the preview to see the gradient
ofs_y = 0;
tex_height = size.height;
+ } else if (Object::cast_to<GradientTexture>(*texture)) {
+ ofs_y = size.height / 4.0;
+ tex_height = size.height / 2.0;
}
draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index dd5127181d..2ff8536b4c 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -1023,6 +1023,9 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
}
} else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) {
+ if (!tools[TOOL_SELECT]->is_disabled())
+ tools[TOOL_SELECT]->set_disabled(true);
+
if (mb.is_valid()) {
if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
Vector2 pos = mb->get_position();
@@ -1089,6 +1092,8 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
} else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT && current_shape.size() > 2) {
if (creating_shape) {
close_shape(shape_anchor);
+ if (tools[TOOL_SELECT]->is_disabled())
+ tools[TOOL_SELECT]->set_disabled(false);
}
}
} else if (mm.is_valid()) {
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index da283b16dc..9c3b09608b 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -304,8 +304,9 @@ private:
ProjectSettings *current = memnew(ProjectSettings);
- if (current->setup(dir, "")) {
- set_message(TTR("Couldn't get project.godot in project path."), MESSAGE_ERROR);
+ int err = current->setup(dir, "");
+ if (err != OK) {
+ set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR);
} else {
ProjectSettings::CustomMap edited_settings;
edited_settings["application/config/name"] = project_name->get_text();
@@ -530,8 +531,9 @@ public:
ProjectSettings *current = memnew(ProjectSettings);
- if (current->setup(project_path->get_text(), "")) {
- set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR);
+ int err = current->setup(project_path->get_text(), "");
+ if (err != OK) {
+ set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR);
status_rect->show();
msg->show();
get_ok()->set_disabled(true);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 704ec40e4c..9625bc19c0 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -750,7 +750,16 @@ void ProjectSettingsEditor::_item_add() {
String catname = category->get_text().strip_edges();
String propname = property->get_text().strip_edges();
- String name = catname != "" ? catname + "/" + propname : propname;
+
+ if (propname.empty()) {
+ return;
+ }
+
+ if (catname.empty()) {
+ catname = "global";
+ }
+
+ String name = catname + "/" + propname;
undo_redo->create_action(TTR("Add Global Property"));
@@ -1586,7 +1595,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
props_base->add_child(hbc);
- search_button = memnew(ToolButton);
+ search_button = memnew(Button);
search_button->set_toggle_mode(true);
search_button->set_pressed(false);
search_button->set_text(TTR("Search"));
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index d6c2c0f5a8..452cf5b060 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -67,7 +67,7 @@ class ProjectSettingsEditor : public AcceptDialog {
SectionedPropertyEditor *globals_editor;
HBoxContainer *search_bar;
- ToolButton *search_button;
+ Button *search_button;
LineEdit *search_box;
ToolButton *clear_button;
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 87906c5a93..043add046e 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -2695,7 +2695,7 @@ TreeItem *PropertyEditor::get_parent_node(String p_path, HashMap<String, TreeIte
item->set_editable(1, false);
item->set_selectable(1, subsection_selectable);
- if (use_folding) { //
+ if (use_folding) {
if (!obj->editor_is_section_unfolded(p_path)) {
updating_folding = true;
item->set_collapsed(true);
@@ -3015,7 +3015,7 @@ void PropertyEditor::update_tree() {
item->set_tooltip(1, obj->get(p.name) ? "True" : "False");
item->set_checked(1, obj->get(p.name));
if (show_type_icons)
- item->set_icon(0, get_icon("Bool", "EditorIcons"));
+ item->set_icon(0, get_icon("bool", "EditorIcons"));
item->set_editable(1, !read_only);
} break;
@@ -3135,12 +3135,12 @@ void PropertyEditor::update_tree() {
if (p.type == Variant::REAL) {
if (show_type_icons)
- item->set_icon(0, get_icon("Real", "EditorIcons"));
+ item->set_icon(0, get_icon("float", "EditorIcons"));
item->set_range(1, obj->get(p.name));
} else {
if (show_type_icons)
- item->set_icon(0, get_icon("Integer", "EditorIcons"));
+ item->set_icon(0, get_icon("int", "EditorIcons"));
item->set_range(1, obj->get(p.name));
}
@@ -3246,7 +3246,7 @@ void PropertyEditor::update_tree() {
item->set_text(1, type_name + "[]");
if (show_type_icons)
- item->set_icon(0, get_icon("ArrayData", "EditorIcons"));
+ item->set_icon(0, get_icon("PoolByteArray", "EditorIcons"));
} break;
case Variant::DICTIONARY: {
@@ -3258,7 +3258,7 @@ void PropertyEditor::update_tree() {
item->add_button(1, get_icon("EditResource", "EditorIcons"));
if (show_type_icons)
- item->set_icon(0, get_icon("DictionaryData", "EditorIcons"));
+ item->set_icon(0, get_icon("Dictionary", "EditorIcons"));
} break;
@@ -3273,7 +3273,7 @@ void PropertyEditor::update_tree() {
else
item->set_text(1, "IntArray[]");
if (show_type_icons)
- item->set_icon(0, get_icon("ArrayInt", "EditorIcons"));
+ item->set_icon(0, get_icon("PoolIntArray", "EditorIcons"));
} break;
case Variant::POOL_REAL_ARRAY: {
@@ -3287,7 +3287,7 @@ void PropertyEditor::update_tree() {
else
item->set_text(1, "FloatArray[]");
if (show_type_icons)
- item->set_icon(0, get_icon("ArrayReal", "EditorIcons"));
+ item->set_icon(0, get_icon("PoolRealArray", "EditorIcons"));
} break;
case Variant::POOL_STRING_ARRAY: {
@@ -3301,7 +3301,7 @@ void PropertyEditor::update_tree() {
else
item->set_text(1, "String[]");
if (show_type_icons)
- item->set_icon(0, get_icon("ArrayString", "EditorIcons"));
+ item->set_icon(0, get_icon("PoolStringArray", "EditorIcons"));
} break;
case Variant::POOL_BYTE_ARRAY: {
@@ -3315,7 +3315,7 @@ void PropertyEditor::update_tree() {
else
item->set_text(1, "Byte[]");
if (show_type_icons)
- item->set_icon(0, get_icon("ArrayData", "EditorIcons"));
+ item->set_icon(0, get_icon("PoolByteArray", "EditorIcons"));
} break;
case Variant::POOL_VECTOR2_ARRAY: {
@@ -3343,7 +3343,7 @@ void PropertyEditor::update_tree() {
else
item->set_text(1, "Vector3[]");
if (show_type_icons)
- item->set_icon(0, get_icon("Vector", "EditorIcons"));
+ item->set_icon(0, get_icon("Vector3", "EditorIcons"));
} break;
case Variant::POOL_COLOR_ARRAY: {
@@ -3384,7 +3384,7 @@ void PropertyEditor::update_tree() {
item->set_editable(1, true);
item->set_text(1, obj->get(p.name));
if (show_type_icons)
- item->set_icon(0, get_icon("Vector", "EditorIcons"));
+ item->set_icon(0, get_icon("Vector3", "EditorIcons"));
} break;
case Variant::TRANSFORM2D:
@@ -3393,6 +3393,7 @@ void PropertyEditor::update_tree() {
item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM);
item->set_editable(1, true);
item->set_text(1, obj->get(p.name));
+
} break;
case Variant::TRANSFORM: {
@@ -3400,7 +3401,7 @@ void PropertyEditor::update_tree() {
item->set_editable(1, true);
item->set_text(1, obj->get(p.name));
if (show_type_icons)
- item->set_icon(0, get_icon("Matrix", "EditorIcons"));
+ item->set_icon(0, get_icon("Transform", "EditorIcons"));
} break;
case Variant::PLANE: {
@@ -3419,6 +3420,7 @@ void PropertyEditor::update_tree() {
item->set_text(1, "AABB");
if (show_type_icons)
item->set_icon(0, get_icon("AABB", "EditorIcons"));
+
} break;
case Variant::QUAT: {
@@ -3446,6 +3448,8 @@ void PropertyEditor::update_tree() {
item->set_editable(1, !read_only);
item->set_text(1, obj->get(p.name));
item->add_button(1, get_icon("CopyNodePath", "EditorIcons"));
+ if (show_type_icons)
+ item->set_icon(0, get_icon("NodePath", "EditorIcons"));
} break;
case Variant::OBJECT: {
@@ -4332,7 +4336,7 @@ PropertyEditor::PropertyEditor() {
use_filter = false;
subsection_selectable = false;
property_selectable = false;
- show_type_icons = false; // maybe one day will return.
+ show_type_icons = EDITOR_DEF("interface/editor/show_type_icons", false);
}
PropertyEditor::~PropertyEditor() {
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 41ee5ab286..8506c75a68 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -67,6 +67,9 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
if (get_viewport()->get_modal_stack_top())
return; //ignore because of modal window
+ if (get_focus_owner() && get_focus_owner()->is_text_field())
+ return;
+
if (!p_event->is_pressed() || p_event->is_echo())
return;
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index fd21b83605..0a3e2da5e9 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -69,24 +69,10 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
emit_signal("open_script", script);
} else if (p_id == BUTTON_VISIBILITY) {
-
- if (n->is_class("Spatial")) {
-
- bool v = bool(n->call("is_visible"));
- undo_redo->create_action(TTR("Toggle Spatial Visible"));
- undo_redo->add_do_method(n, "set_visible", !v);
- undo_redo->add_undo_method(n, "set_visible", v);
- undo_redo->commit_action();
-
- } else if (n->is_class("CanvasItem")) {
-
- bool v = bool(n->call("is_visible"));
- undo_redo->create_action(TTR("Toggle CanvasItem Visible"));
- undo_redo->add_do_method(n, v ? "hide" : "show");
- undo_redo->add_undo_method(n, v ? "show" : "hide");
- undo_redo->commit_action();
- }
-
+ undo_redo->create_action(TTR("Toggle Visible"));
+ undo_redo->add_do_method(this, "toggle_visible", n);
+ undo_redo->add_undo_method(this, "toggle_visible", n);
+ undo_redo->commit_action();
} else if (p_id == BUTTON_LOCK) {
if (n->is_class("CanvasItem") || n->is_class("Spatial")) {
@@ -131,7 +117,34 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
NodeDock::singleton->show_groups();
}
}
+void SceneTreeEditor::_toggle_visible(Node *p_node) {
+ if (p_node->is_class("Spatial")) {
+ bool v = bool(p_node->call("is_visible"));
+ p_node->call("set_visible", !v);
+ } else if (p_node->is_class("CanvasItem")) {
+ bool v = bool(p_node->call("is_visible"));
+ if (v) {
+ p_node->call("hide");
+ } else {
+ p_node->call("show");
+ }
+ }
+}
+void SceneTreeEditor::toggle_visible(Node *p_node) {
+ _toggle_visible(p_node);
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ if (selection.size() > 1) {
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node *nv = E->get();
+ ERR_FAIL_COND(!nv);
+ if (nv == p_node) {
+ continue;
+ }
+ _toggle_visible(nv);
+ }
+ }
+}
bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
if (!p_node)
@@ -949,6 +962,8 @@ void SceneTreeEditor::_bind_methods() {
ClassDB::bind_method("_cell_collapsed", &SceneTreeEditor::_cell_collapsed);
ClassDB::bind_method("_rmb_select", &SceneTreeEditor::_rmb_select);
ClassDB::bind_method("_warning_changed", &SceneTreeEditor::_warning_changed);
+ ClassDB::bind_method("_toggle_visible", &SceneTreeEditor::_toggle_visible);
+ ClassDB::bind_method("toggle_visible", &SceneTreeEditor::toggle_visible);
ClassDB::bind_method("_node_script_changed", &SceneTreeEditor::_node_script_changed);
ClassDB::bind_method("_node_visibility_changed", &SceneTreeEditor::_node_visibility_changed);
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 45194bb81d..b63eb2a1f0 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -70,6 +70,8 @@ class SceneTreeEditor : public Control {
void _compute_hash(Node *p_node, uint64_t &hash);
+ void toggle_visible(Node *p_node);
+
bool _add_nodes(Node *p_node, TreeItem *p_parent);
void _test_update_tree();
void _update_tree();
@@ -103,6 +105,7 @@ class SceneTreeEditor : public Control {
static void _bind_methods();
void _cell_button_pressed(Object *p_item, int p_column, int p_id);
+ void _toggle_visible(Node *p_node);
void _cell_multi_selected(Object *p_object, int p_cell, bool p_selected);
void _update_selection(TreeItem *item);
void _node_script_changed(Node *p_node);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index cee356b930..e56a7f2a55 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -51,7 +51,9 @@ void ScriptCreateDialog::_notification(int p_what) {
void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path) {
class_name->set_text("");
+ class_name->deselect();
parent_name->set_text(p_base_name);
+ parent_name->deselect();
if (p_base_path != "") {
initial_bp = p_base_path.get_basename();
file_path->set_text(initial_bp + "." + ScriptServer::get_language(language_menu->get_selected())->get_extension());
@@ -59,8 +61,9 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_
initial_bp = "";
file_path->set_text("");
}
+ file_path->deselect();
+
_lang_changed(current_language);
- _parent_name_changed(parent_name->get_text());
_class_name_changed("");
_path_changed(file_path->get_text());
}
@@ -290,6 +293,7 @@ void ScriptCreateDialog::_lang_changed(int l) {
_template_changed(template_menu->get_selected());
EditorSettings::get_singleton()->set_project_metadata("script_setup", "last_selected_language", language_menu->get_item_text(language_menu->get_selected()));
+ _parent_name_changed(parent_name->get_text());
_update_dialog();
}
@@ -303,11 +307,19 @@ void ScriptCreateDialog::_built_in_pressed() {
_update_dialog();
}
-void ScriptCreateDialog::_browse_path(bool browse_parent) {
+void ScriptCreateDialog::_browse_path(bool browse_parent, bool p_save) {
is_browsing_parent = browse_parent;
- file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ if (p_save) {
+ file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_browse->set_title(TTR("Open Script/Choose Location"));
+ file_browse->get_ok()->set_text(TTR("Open"));
+ } else {
+ file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_browse->set_title(TTR("Open Script"));
+ }
+
file_browse->set_disable_overwrite_warning(true);
file_browse->clear_filters();
List<String> extensions;
@@ -380,8 +392,6 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
is_new_script_created = false;
is_path_valid = true;
_msg_path_valid(true, TTR("File exists, will be reused"));
- } else {
- path_error_label->set_text("");
}
memdelete(f);
_update_dialog();
@@ -533,10 +543,8 @@ void ScriptCreateDialog::_update_dialog() {
internal->set_disabled(!supports_built_in);
if (is_built_in) {
_msg_path_valid(true, TTR("Built-in script (into scene file)"));
- } else {
- if (script_ok) {
- _msg_path_valid(true, TTR("Create new script file"));
- }
+ } else if (is_path_valid) {
+ _msg_path_valid(true, TTR("Create new script file"));
}
} else {
// Script Loaded
@@ -544,7 +552,7 @@ void ScriptCreateDialog::_update_dialog() {
parent_name->set_editable(false);
parent_browse_button->set_disabled(true);
internal->set_disabled(true);
- if (script_ok) {
+ if (is_path_valid) {
_msg_path_valid(true, TTR("Load existing script file"));
}
}
@@ -678,7 +686,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
hb->add_child(parent_name);
parent_browse_button = memnew(Button);
parent_browse_button->set_flat(true);
- parent_browse_button->connect("pressed", this, "_browse_path", varray(true));
+ parent_browse_button->connect("pressed", this, "_browse_path", varray(true, false));
hb->add_child(parent_browse_button);
l = memnew(Label);
l->set_text(TTR("Inherits"));
@@ -730,7 +738,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
hb->add_child(file_path);
path_button = memnew(Button);
path_button->set_flat(true);
- path_button->connect("pressed", this, "_browse_path", varray(false));
+ path_button->connect("pressed", this, "_browse_path", varray(false, true));
hb->add_child(path_button);
l = memnew(Label);
l->set_text(TTR("Path"));
@@ -742,6 +750,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
file_browse = memnew(EditorFileDialog);
file_browse->connect("file_selected", this, "_file_selected");
+ file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE);
add_child(file_browse);
get_ok()->set_text(TTR("Create"));
alert = memnew(AcceptDialog);
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index b5afe2e38e..99e5bc9e6a 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -81,7 +81,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _class_name_changed(const String &p_name);
void _parent_name_changed(const String &p_parent);
void _template_changed(int p_template = 0);
- void _browse_path(bool browse_parent);
+ void _browse_path(bool browse_parent, bool p_save);
void _file_selected(const String &p_file);
virtual void ok_pressed();
void _create_new();
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index d0527a13ea..86ab84909e 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -193,6 +193,12 @@ public:
}
};
+void ScriptEditorDebugger::debug_copy() {
+ String msg = reason->get_text();
+ if (msg == "") return;
+ OS::get_singleton()->set_clipboard(msg);
+}
+
void ScriptEditorDebugger::debug_next() {
ERR_FAIL_COND(!breaked);
@@ -338,6 +344,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
step->set_disabled(!can_continue);
next->set_disabled(!can_continue);
_set_reason_text(error, MESSAGE_ERROR);
+ copy->set_disabled(false);
breaked = true;
dobreak->set_disabled(true);
docontinue->set_disabled(false);
@@ -354,6 +361,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
} else if (p_msg == "debug_exit") {
breaked = false;
+ copy->set_disabled(true);
step->set_disabled(true);
next->set_disabled(true);
reason->set_text("");
@@ -940,6 +948,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
inspector->edit(variables);
+ copy->set_icon(get_icon("Duplicate", "EditorIcons"));
+
step->set_icon(get_icon("DebugStep", "EditorIcons"));
next->set_icon(get_icon("DebugNext", "EditorIcons"));
back->set_icon(get_icon("Back", "EditorIcons"));
@@ -1741,6 +1751,9 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected);
+
+ ClassDB::bind_method(D_METHOD("debug_copy"), &ScriptEditorDebugger::debug_copy);
+
ClassDB::bind_method(D_METHOD("debug_next"), &ScriptEditorDebugger::debug_next);
ClassDB::bind_method(D_METHOD("debug_step"), &ScriptEditorDebugger::debug_step);
ClassDB::bind_method(D_METHOD("debug_break"), &ScriptEditorDebugger::debug_break);
@@ -1816,6 +1829,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
hbc->add_child(memnew(VSeparator));
+ copy = memnew(ToolButton);
+ hbc->add_child(copy);
+ copy->set_tooltip(TTR("Copy Error"));
+ copy->connect("pressed", this, "debug_copy");
+
+ hbc->add_child(memnew(VSeparator));
+
step = memnew(ToolButton);
hbc->add_child(step);
step->set_tooltip(TTR("Step Into"));
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index e86add940a..669d8737fe 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -104,6 +104,7 @@ class ScriptEditorDebugger : public Control {
Label *reason;
+ Button *copy;
Button *step;
Button *next;
Button *back;
@@ -197,6 +198,8 @@ public:
void unpause();
void stop();
+ void debug_copy();
+
void debug_next();
void debug_step();
void debug_break();
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 72c0f050d2..8c90d86b9e 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -308,15 +308,6 @@ void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size
m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), cubem.surface_get_arrays(0));
m->surface_set_material(0, p_material);
add_mesh(m);
-
- Instance ins;
- ins.mesh = m;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
}
void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) {
@@ -1130,7 +1121,7 @@ void CameraSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p
if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) {
Transform gt = camera->get_global_transform();
float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt);
- camera->set("fov", a);
+ camera->set("fov", a * 2.0);
} else {
Vector3 ra, rb;
@@ -1187,7 +1178,8 @@ void CameraSpatialGizmo::redraw() {
case Camera::PROJECTION_PERSPECTIVE: {
- float fov = camera->get_fov();
+ // The real FOV is halved for accurate representation
+ float fov = camera->get_fov() / 2.0;
Vector3 side = Vector3(Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)));
Vector3 nside = side;
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
index cb483ed653..eedab7fdef 100644
--- a/editor/spatial_editor_gizmos.h
+++ b/editor/spatial_editor_gizmos.h
@@ -105,7 +105,7 @@ protected:
void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const AABB &p_bounds = AABB());
void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1);
void add_handles(const Vector<Vector3> &p_handles, bool p_billboard = false, bool p_secondary = false);
- void add_solid_box(Ref<Material> &p_material, Vector3 size);
+ void add_solid_box(Ref<Material> &p_material, Vector3 p_size);
void set_spatial_node(Spatial *p_node);
const Spatial *get_spatial_node() const { return spatial_node; }
@@ -376,13 +376,13 @@ public:
class JointGizmosDrawer {
public:
- static Basis look_body(const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body(const Transform &p_joint_transform, const Transform &p_body_transform);
static Basis look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform);
- static Basis look_body_toward_x(const Transform &joint_transform, const Transform &body_transform);
- static Basis look_body_toward_y(const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body_toward_x(const Transform &p_joint_transform, const Transform &p_body_transform);
+ static Basis look_body_toward_y(const Transform &p_joint_transform, const Transform &p_body_transform);
/// Special function just used for physics joints, it that returns a basis constrained toward Joint Z axis
/// with axis X and Y that are looking toward the body and oriented toward up
- static Basis look_body_toward_z(const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body_toward_z(const Transform &p_joint_transform, const Transform &p_body_transform);
// Draw circle around p_axis
static void draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse = false);