aboutsummaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_editor.cpp11
-rw-r--r--editor/code_editor.cpp6
-rw-r--r--editor/create_dialog.cpp1
-rw-r--r--editor/editor_export.cpp18
-rw-r--r--editor/editor_export.h4
-rw-r--r--editor/editor_file_dialog.cpp1
-rw-r--r--editor/editor_fonts.cpp3
-rw-r--r--editor/editor_log.cpp6
-rw-r--r--editor/editor_node.cpp10
-rw-r--r--editor/editor_profiler.cpp11
-rw-r--r--editor/editor_settings.cpp8
-rw-r--r--editor/editor_themes.cpp169
-rw-r--r--editor/filesystem_dock.cpp2
-rw-r--r--editor/icons/icon_a_r_v_r_camera.svg3
-rw-r--r--editor/icons/icon_area.svg2
-rw-r--r--editor/icons/icon_error.svg2
-rw-r--r--editor/icons/icon_error_sign.svg5
-rw-r--r--editor/icons/icon_file_broken.svg2
-rw-r--r--editor/icons/icon_file_broken_big_thumb.svg2
-rw-r--r--editor/icons/icon_file_dead.svg2
-rw-r--r--editor/icons/icon_file_dead_big_thumb.svg2
-rw-r--r--editor/icons/icon_file_dead_medium_thumb.svg2
-rw-r--r--editor/icons/icon_gui_close_customizable.svg5
-rw-r--r--editor/icons/icon_gui_graph_node_port.svg5
-rw-r--r--editor/icons/icon_gui_resizer.svg3
-rw-r--r--editor/icons/icon_import_check.svg2
-rw-r--r--editor/icons/icon_import_fail.svg2
-rw-r--r--editor/icons/icon_key_invalid.svg2
-rw-r--r--editor/icons/icon_key_move_disabled.svg4
-rw-r--r--editor/icons/icon_key_move_enabled.svg4
-rw-r--r--editor/icons/icon_key_rotate_disabled.svg4
-rw-r--r--editor/icons/icon_key_rotate_enabled.svg4
-rw-r--r--editor/icons/icon_key_scale_disabled.svg4
-rw-r--r--editor/icons/icon_key_scale_enabled.svg4
-rw-r--r--editor/icons/icon_node_warning.svg2
-rw-r--r--editor/icons/icon_sample_library.svg5
-rw-r--r--editor/icons/icon_slider_joint.svg7
-rw-r--r--editor/icons/icon_snap.svg101
-rw-r--r--editor/icons/icon_snap_grid.svg92
-rw-r--r--editor/icons/icon_warning.svg2
-rw-r--r--editor/import/resource_importer_scene.cpp14
-rw-r--r--editor/import/resource_importer_scene.h6
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp1398
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h117
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp61
-rw-r--r--editor/scene_tree_dock.cpp1
-rw-r--r--editor/script_editor_debugger.cpp1
49 files changed, 1478 insertions, 648 deletions
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index 47360ff7f..96e5627be 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -2898,10 +2898,6 @@ void AnimationKeyEditor::_notification(int p_what) {
zoomicon->set_custom_minimum_size(Size2(24 * EDSCALE, 0));
zoomicon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK);
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK);
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK);
-
menu_track->set_icon(get_icon("Tools", "EditorIcons"));
menu_track->get_popup()->add_item(TTR("Scale Selection"), TRACK_MENU_SCALE);
menu_track->get_popup()->add_item(TTR("Scale From Cursor"), TRACK_MENU_SCALE_PIVOT);
@@ -3817,6 +3813,9 @@ AnimationKeyEditor::AnimationKeyEditor() {
hb->add_child(menu_add_track);
menu_add_track->get_popup()->connect("id_pressed", this, "_menu_add_track");
menu_add_track->set_tooltip(TTR("Add new tracks."));
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK);
move_up_button = memnew(ToolButton);
hb->add_child(move_up_button);
@@ -3934,7 +3933,7 @@ AnimationKeyEditor::AnimationKeyEditor() {
key_editor_tab = memnew(TabContainer);
key_editor_tab->set_tab_align(TabContainer::ALIGN_LEFT);
hb->add_child(key_editor_tab);
- key_editor_tab->set_custom_minimum_size(Size2(200, 0));
+ key_editor_tab->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
key_editor = memnew(PropertyEditor);
key_editor->set_area_as_parent_rect();
@@ -4052,8 +4051,6 @@ AnimationKeyEditor::AnimationKeyEditor() {
cleanup_dialog->connect("confirmed", this, "_menu_track", varray(TRACK_MENU_CLEAN_UP_CONFIRM));
- add_constant_override("separation", get_constant("separation", "VBoxContainer"));
-
track_editor->set_clip_contents(true);
}
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 8c153d274..5dd8b8a80 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1023,8 +1023,10 @@ void CodeTextEditor::_line_col_changed() {
void CodeTextEditor::_text_changed() {
- code_complete_timer->start();
- idle->start();
+ if (text_editor->is_insert_text_operation()) {
+ code_complete_timer->start();
+ idle->start();
+ }
}
void CodeTextEditor::_code_complete_timer_timeout() {
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 9797a2e9f..33734957e 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -637,6 +637,7 @@ CreateDialog::CreateDialog() {
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
search_hb->add_child(search_box);
favorite = memnew(Button);
+ favorite->set_flat(true);
favorite->set_toggle_mode(true);
search_hb->add_child(favorite);
favorite->connect("pressed", this, "_favorite_toggled");
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index d08a595fd..ad9bc4a66 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -1246,9 +1246,13 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
}
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->copy(template_path, p_path);
+ Error err = da->copy(template_path, p_path, get_chmod_flags());
memdelete(da);
+ if (err != OK) {
+ return err;
+ }
+
String pck_path = p_path.get_basename() + ".pck";
return save_pack(p_preset, pck_path);
@@ -1302,5 +1306,17 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
}
}
+int EditorExportPlatformPC::get_chmod_flags() const {
+
+ return chmod_flags;
+}
+
+void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
+
+ chmod_flags = p_flags;
+}
+
EditorExportPlatformPC::EditorExportPlatformPC() {
+
+ chmod_flags = -1;
}
diff --git a/editor/editor_export.h b/editor/editor_export.h
index b6ea4fd88..50379b968 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -319,6 +319,7 @@ class EditorExportPlatformPC : public EditorExportPlatform {
Set<String> extra_features;
bool use64;
+ int chmod_flags;
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
@@ -347,6 +348,9 @@ public:
void add_platform_feature(const String &p_feature);
virtual void get_platform_features(List<String> *r_features);
+ int get_chmod_flags() const;
+ void set_chmod_flags(int p_flags);
+
EditorExportPlatformPC();
};
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 288b923e8..8d1315312 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -1299,6 +1299,7 @@ EditorFileDialog::EditorFileDialog() {
pathhb->add_child(refresh);
favorite = memnew(ToolButton);
+ favorite->set_flat(true);
favorite->set_toggle_mode(true);
favorite->connect("toggled", this, "_favorite_toggled");
pathhb->add_child(favorite);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index b0334685c..6e5726a16 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -137,6 +137,9 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font("doc", "EditorFonts", df_doc);
p_theme->set_font("doc_title", "EditorFonts", df_title);
+ MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE);
+ p_theme->set_font("rulers", "EditorFonts", df_rulers);
+
Ref<DynamicFont> df_code;
df_code.instance();
df_code->set_size(int(EditorSettings::get_singleton()->get("interface/source_font_size")) * EDSCALE);
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 035819f50..481f2aaec 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -85,7 +85,11 @@ void EditorLog::clear() {
void EditorLog::add_message(const String &p_msg, bool p_error) {
+ Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts");
+ log->push_font(doc_code_font);
+
log->add_newline();
+
if (p_error) {
log->push_color(get_color("error_color", "Editor"));
Ref<Texture> icon = get_icon("Error", "EditorIcons");
@@ -100,6 +104,8 @@ void EditorLog::add_message(const String &p_msg, bool p_error) {
if (p_error)
log->pop();
+
+ log->pop(); // pop font;
}
/*
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index d7cce71b9..1a89d6ef6 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -4061,6 +4061,13 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
ERR_FAIL_INDEX(p_idx, bottom_panel_items.size());
if (p_enable) {
+ // this is the debug panel wich uses tabs, so the top section should be smaller
+ if (ScriptEditor::get_singleton()->get_debugger() == bottom_panel_items[p_idx].control) {
+ Ref<StyleBoxFlat> style_panel_invisible_top = gui_base->get_stylebox("debugger_panel", "EditorStyles");
+ bottom_panel->add_style_override("panel", style_panel_invisible_top);
+ } else {
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
+ }
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->set_pressed(i == p_idx);
@@ -4069,11 +4076,14 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
center_split->set_collapsed(false);
} else {
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
+
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->set_pressed(false);
bottom_panel_items[i].control->set_visible(false);
}
+
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
center_split->set_collapsed(true);
}
diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp
index 6b972262b..247775fa1 100644
--- a/editor/editor_profiler.cpp
+++ b/editor/editor_profiler.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "editor_profiler.h"
+#include "editor_scale.h"
#include "editor_settings.h"
#include "os/os.h"
@@ -656,14 +657,14 @@ EditorProfiler::EditorProfiler() {
hb->add_child(cursor_metric_edit);
cursor_metric_edit->connect("value_changed", this, "_cursor_metric_changed");
- hb->add_constant_override("separation", 8);
+ hb->add_constant_override("separation", 8 * EDSCALE);
h_split = memnew(HSplitContainer);
add_child(h_split);
h_split->set_v_size_flags(SIZE_EXPAND_FILL);
variables = memnew(Tree);
- variables->set_custom_minimum_size(Size2(300, 0));
+ variables->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
variables->set_hide_folding(true);
h_split->add_child(variables);
variables->set_hide_root(true);
@@ -674,10 +675,10 @@ EditorProfiler::EditorProfiler() {
variables->set_column_min_width(0, 60);
variables->set_column_title(1, "Time");
variables->set_column_expand(1, false);
- variables->set_column_min_width(1, 60);
+ variables->set_column_min_width(1, 60 * EDSCALE);
variables->set_column_title(2, "Calls");
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60);
+ variables->set_column_min_width(2, 60 * EDSCALE);
variables->connect("item_edited", this, "_item_edited");
graph = memnew(TextureRect);
@@ -691,8 +692,6 @@ EditorProfiler::EditorProfiler() {
h_split->add_child(graph);
graph->set_h_size_flags(SIZE_EXPAND_FILL);
- add_constant_override("separation", 3);
-
int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024);
frame_metrics.resize(metric_size);
last_metric = -1;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index d4ee6b2d1..eb72fdf64 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -460,7 +460,7 @@ void EditorSettings::setup_network() {
List<IP_Address> local_ip;
IP::get_singleton()->get_local_addresses(&local_ip);
- String lip;
+ String lip = "127.0.0.1";
String hint;
String current = has("network/debug/remote_host") ? get("network/debug/remote_host") : "";
int port = has("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007;
@@ -469,8 +469,9 @@ void EditorSettings::setup_network() {
String ip = E->get();
- if (lip == "")
- lip = ip;
+ // link-local IPv6 addresses don't work, skipping them
+ if (ip.begins_with("fe80:0:0:0:")) // fe80::/64
+ continue;
if (ip == current)
lip = current; //so it saves
if (hint != "")
@@ -581,6 +582,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/theme/contrast"] = PropertyInfo(Variant::REAL, "interface/theme/contrast", PROPERTY_HINT_RANGE, "0.01, 1, 0.01");
set("interface/theme/highlight_tabs", false);
set("interface/theme/border_size", 1);
+ set("interface/theme/use_graph_node_headers", false);
hints["interface/theme/border_size"] = PropertyInfo(Variant::INT, "interface/theme/border_size", PROPERTY_HINT_RANGE, "0,2,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
set("interface/theme/custom_theme", "");
hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 0cba02459..4aa1ccaa8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -112,41 +112,49 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr
#ifdef SVG_ENABLED
Dictionary dark_icon_color_dictionary;
- //convert color: FROM TO
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color
+ if (!dark_theme) {
+ //convert color: FROM TO
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // error
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // success
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#ffad07"); // warning
+ // rainbow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink
- // rainbow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink
+ // audio gradient
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green
- // audio gradient
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // remove (red)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // add (green)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red)
+ }
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red)
+ // these ones should be converted even if we are using a dark theme
+ const Color error_color = p_theme->get_color("error_color", "Editor");
+ const Color success_color = p_theme->get_color("success_color", "Editor");
+ const Color warning_color = p_theme->get_color("warning_color", "Editor");
+ dark_icon_color_dictionary[Color::html("#ff5d5d")] = error_color;
+ dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color;
+ dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color;
List<String> exceptions;
exceptions.push_back("EditorPivot");
@@ -157,17 +165,20 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr
exceptions.push_back("ProceduralSky");
exceptions.push_back("EditorControlAnchor");
exceptions.push_back("DefaultProjectIcon");
+ exceptions.push_back("GuiCloseCustomizable");
+ exceptions.push_back("GuiGraphNodePort");
+ exceptions.push_back("GuiResizer");
clock_t begin_time = clock();
- ImageLoaderSVG::set_convert_colors(dark_theme ? NULL : &dark_icon_color_dictionary);
+ ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary);
// generate icons
if (!only_thumbs)
for (int i = 0; i < editor_icons_count; i++) {
List<String>::Element *is_exception = exceptions.find(editor_icons_names[i]);
if (is_exception) exceptions.erase(is_exception);
- Ref<ImageTexture> icon = editor_generate_icon(i, !dark_theme && !is_exception);
+ Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception);
p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon);
}
@@ -220,6 +231,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
bool highlight_tabs = EDITOR_DEF("interface/theme/highlight_tabs", false);
int border_size = EDITOR_DEF("interface/theme/border_size", 1);
+ bool use_gn_headers = EDITOR_DEF("interface/theme/use_graph_node_headers", false);
+
Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
switch (preset) {
@@ -322,6 +335,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const int border_width = CLAMP(border_size, 0, 3) * EDSCALE;
const int default_margin_size = 4;
+ const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 3);
// styleboxes
// this is the most commonly used stylebox, variations should be made as duplicate of this
@@ -333,11 +347,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Button and widgets
Ref<StyleBoxFlat> style_widget = style_default->duplicate();
- // style_widget->set_bg_color(dark_color_1.linear_interpolate(base_color, 0.4));
style_widget->set_bg_color(dark_color_1);
style_widget->set_default_margin(MARGIN_LEFT, 6 * EDSCALE);
style_widget->set_default_margin(MARGIN_RIGHT, 6 * EDSCALE);
- // style_widget->set_border_color_all(contrast_color_1);
style_widget->set_border_color_all(dark_color_2);
Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate();
@@ -368,18 +380,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size);
// Tabs
+ const int tab_default_margin_side = 10 * EDSCALE;
Ref<StyleBoxFlat> style_tab_selected = style_default->duplicate();
style_tab_selected->set_border_width_all(border_width);
style_tab_selected->set_border_width(MARGIN_BOTTOM, 0);
style_tab_selected->set_border_color_all(dark_color_3);
style_tab_selected->set_expand_margin_size(MARGIN_BOTTOM, border_width);
- style_tab_selected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE);
- style_tab_selected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE);
+ style_tab_selected->set_default_margin(MARGIN_LEFT, tab_default_margin_side);
+ style_tab_selected->set_default_margin(MARGIN_RIGHT, tab_default_margin_side);
style_tab_selected->set_bg_color(tab_color);
- Ref<StyleBoxEmpty> style_tab_unselected = style_empty->duplicate();
- style_tab_unselected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE);
- style_tab_unselected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE);
+ Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate();
+ style_tab_unselected->set_bg_color(Color(0.0, 0.0, 0.0, 0.0));
+ style_tab_unselected->set_border_color_all(Color(0.0, 0.0, 0.0, 0.0));
// Editor background
theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size));
@@ -603,13 +616,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
style_content_panel->set_border_color_all(dark_color_3);
style_content_panel->set_border_width_all(border_width);
+ // compensate the border
+ style_content_panel->set_default_margin(MARGIN_TOP, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_RIGHT, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_BOTTOM, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_LEFT, margin_size_extra * EDSCALE);
// this is the stylebox used in 3d and 2d viewports (no borders)
Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
- style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width);
- style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size);
- style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width);
- style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width);
+ style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width * 2);
+ style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
+ style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width * 2);
+ style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width * 2);
theme->set_stylebox("panel", "TabContainer", style_content_panel);
theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
@@ -617,15 +635,29 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, border_width));
theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, border_width, 0, true));
- // Debugger
- Ref<StyleBoxFlat> style_panel_debugger = style_default->duplicate();
- theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
+ // HACK Debuger panel
+ Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate();
+ const int v_offset = theme->get_font("font", "Tabs")->get_height() + style_tab_selected->get_minimum_size().height + default_margin_size * EDSCALE;
+ style_panel_debugger->set_expand_margin_size(MARGIN_TOP, -v_offset);
+ theme->set_stylebox("debugger_panel", "EditorStyles", style_panel_debugger);
+ // Debugger
+ Ref<StyleBoxFlat> style_debugger_contents = style_content_panel->duplicate();
+ style_debugger_contents->set_default_margin(MARGIN_LEFT, 0);
+ style_debugger_contents->set_default_margin(MARGIN_BOTTOM, 0);
+ style_debugger_contents->set_default_margin(MARGIN_RIGHT, 0);
+ style_debugger_contents->set_border_width_all(0);
+ style_debugger_contents->set_expand_margin_size(MARGIN_TOP, -v_offset);
+ theme->set_constant("extra_margin", "DebuggerPanel", default_margin_size * EDSCALE + border_width);
+ theme->set_stylebox("DebuggerPanel", "EditorStyles", style_debugger_contents);
Ref<StyleBoxFlat> style_tab_fg_debugger = style_tab_selected->duplicate();
- style_tab_fg_debugger->set_border_width_all(0);
-
+ style_tab_fg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width);
+ style_tab_fg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE);
theme->set_stylebox("DebuggerTabFG", "EditorStyles", style_tab_fg_debugger);
- theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_unselected);
+ Ref<StyleBoxFlat> style_tab_bg_debugger = style_tab_unselected->duplicate();
+ style_tab_bg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width);
+ style_tab_bg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE);
+ theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_bg_debugger);
// LineEdit
theme->set_stylebox("normal", "LineEdit", style_widget);
@@ -651,6 +683,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE);
theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE);
+ // Containers
+ theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("margin_left", "MarginContainer", 0);
+ theme->set_constant("margin_top", "MarginContainer", 0);
+ theme->set_constant("margin_right", "MarginContainer", 0);
+ theme->set_constant("margin_bottom", "MarginContainer", 0);
+ theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE);
+ theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE);
+
// WindowDialog
Ref<StyleBoxFlat> style_window = style_popup->duplicate();
style_window->set_border_color_all(tab_color);
@@ -762,28 +805,40 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// GraphNode
- Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5);
+ const int gn_margin_side = 28;
+ Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5);
graphsb->set_border_width_all(border_width);
- graphsb->set_border_color_all(Color(1, 1, 1, 0.6));
- graphsb->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5);
+ graphsb->set_border_color_all(Color(1, 1, 1, 0.9));
+ Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.4), gn_margin_side, 24, gn_margin_side, 5);
graphsbselected->set_border_width_all(border_width);
graphsbselected->set_border_color_all(Color(accent_color.r, accent_color.g, accent_color.b, 0.9));
graphsbselected->set_shadow_size(8 * EDSCALE);
graphsbselected->set_shadow_color(shadow_color);
- graphsbselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5);
+ Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5);
graphsbcomment->set_border_width_all(border_width);
- graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.6));
- graphsbcomment->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5);
+ graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.9));
+ Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), gn_margin_side, 24, gn_margin_side, 5);
graphsbcommentselected->set_border_width_all(border_width);
graphsbcommentselected->set_border_color_all(Color(1, 1, 1, 0.9));
- graphsbcommentselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
+
+ if (use_gn_headers) {
+ graphsb->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbcomment->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbcommentselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ }
+
theme->set_stylebox("frame", "GraphNode", graphsb);
theme->set_stylebox("selectedframe", "GraphNode", graphsbselected);
theme->set_stylebox("comment", "GraphNode", graphsbcomment);
theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected);
+ theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE);
+ theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE);
+ theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE);
+ theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE);
+ theme->set_icon("close", "GraphNode", theme->get_icon("GuiCloseCustomizable", "EditorIcons"));
+ theme->set_icon("resizer", "GraphNode", theme->get_icon("GuiResizer", "EditorIcons"));
+ theme->set_icon("port", "GraphNode", theme->get_icon("GuiGraphNodePort", "EditorIcons"));
// FileDialog
theme->set_color("files_disabled", "FileDialog", font_color_disabled);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index f0ace864e..526a8fe81 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1812,8 +1812,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
display_mode = DISPLAY_THUMBNAILS;
path = "res://";
-
- add_constant_override("separation", 4);
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/icons/icon_a_r_v_r_camera.svg b/editor/icons/icon_a_r_v_r_camera.svg
new file mode 100644
index 000000000..a02b4d983
--- /dev/null
+++ b/editor/icons/icon_a_r_v_r_camera.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m2 1c-0.55401 0-1 0.446-1 1v7c0 0.554 0.44599 1 1 1h4l1-2c0.24699-0.494 0.44772-1 1-1s0.75301 0.506 1 1l1 2h4c0.55401 0 1-0.446 1-1v-7c0-0.554-0.44599-1-1-1h-12zm2 3a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm-8 7v4h2c0.502 4e-4 0.9265-0.37144 0.99219-0.86914 0.0059-0.047 0.0085325-0.094025 0.0078125-0.14062v-2.9902h-1v3h-1v-3h-1zm5 0v4h1v-1h1v1h1v-1c-7.73e-4 -0.1811-0.05073-0.35867-0.14453-0.51367 0.08369-0.1462 0.14453-0.30573 0.14453-0.48633v-1c0-0.5523-0.4485-1.0293-1-1h-2zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_area.svg b/editor/icons/icon_area.svg
index 22348d50c..ac673d10f 100644
--- a/editor/icons/icon_area.svg
+++ b/editor/icons/icon_area.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c" fill-opacity=".99608"/>
+<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_error.svg b/editor/icons/icon_error.svg
index 771a418cf..846bd88cb 100644
--- a/editor/icons/icon_error.svg
+++ b/editor/icons/icon_error.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff8484"/>
+<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff5d5d"/>
</g>
</svg>
diff --git a/editor/icons/icon_error_sign.svg b/editor/icons/icon_error_sign.svg
index a2d714c31..bde0494a9 100644
--- a/editor/icons/icon_error_sign.svg
+++ b/editor/icons/icon_error_sign.svg
@@ -1,7 +1,6 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1020.4)">
-<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff8484" fill-rule="evenodd"/>
-<rect x="14" y="1028.4" width="4" height="9" fill="#fff"/>
-<rect x="14" y="1040.4" width="4" height="4" fill="#fff"/>
+<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff5d5d" fill-rule="evenodd"/>
+<path transform="translate(0 1020.4)" d="m14 8l1 10h2l1-10h-4zm2 12a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#fff"/>
</g>
</svg>
diff --git a/editor/icons/icon_file_broken.svg b/editor/icons/icon_file_broken.svg
index f352eeb00..7b05ab625 100644
--- a/editor/icons/icon_file_broken.svg
+++ b/editor/icons/icon_file_broken.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff5d5d"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_broken_big_thumb.svg b/editor/icons/icon_file_broken_big_thumb.svg
index 167bb1bb5..5e8fa607c 100644
--- a/editor/icons/icon_file_broken_big_thumb.svg
+++ b/editor/icons/icon_file_broken_big_thumb.svg
@@ -1,7 +1,7 @@
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -988.36)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead.svg b/editor/icons/icon_file_dead.svg
index e0aee6fd9..ec13e7087 100644
--- a/editor/icons/icon_file_dead.svg
+++ b/editor/icons/icon_file_dead.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff5d5d"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead_big_thumb.svg b/editor/icons/icon_file_dead_big_thumb.svg
index c8aab912f..2ac8d1e9d 100644
--- a/editor/icons/icon_file_dead_big_thumb.svg
+++ b/editor/icons/icon_file_dead_big_thumb.svg
@@ -1,7 +1,7 @@
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -988.36)">
<g transform="translate(0 -1.6949e-5)">
-<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead_medium_thumb.svg b/editor/icons/icon_file_dead_medium_thumb.svg
index 60a456a60..010019ae0 100644
--- a/editor/icons/icon_file_dead_medium_thumb.svg
+++ b/editor/icons/icon_file_dead_medium_thumb.svg
@@ -1,7 +1,7 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1020.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_gui_close_customizable.svg b/editor/icons/icon_gui_close_customizable.svg
new file mode 100644
index 000000000..ac023b703
--- /dev/null
+++ b/editor/icons/icon_gui_close_customizable.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3.7578 2.3438l-1.4141 1.4141 4.2422 4.2422-4.2422 4.2422 1.4141 1.4141 4.2422-4.2422 4.2422 4.2422 1.4141-1.4141-4.2422-4.2422 4.2422-4.2422-1.4141-1.4141-4.2422 4.2422-4.2422-4.2422z" fill="#fff" fill-opacity=".89804"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_gui_graph_node_port.svg b/editor/icons/icon_gui_graph_node_port.svg
new file mode 100644
index 000000000..112021884
--- /dev/null
+++ b/editor/icons/icon_gui_graph_node_port.svg
@@ -0,0 +1,5 @@
+<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1042.4)">
+<circle cx="5" cy="1047.4" r="5" fill="#fff" fill-rule="evenodd"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_gui_resizer.svg b/editor/icons/icon_gui_resizer.svg
new file mode 100644
index 000000000..d9af04721
--- /dev/null
+++ b/editor/icons/icon_gui_resizer.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m11 3c-0.55228 0-1 0.44772-1 1v6h-6c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h7c0.55226-5.5e-5 0.99994-0.44774 1-1v-7c0-0.55228-0.44772-1-1-1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fff" fill-opacity=".58824" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+</svg>
diff --git a/editor/icons/icon_import_check.svg b/editor/icons/icon_import_check.svg
index e3ad9ec37..c9f51bb6e 100644
--- a/editor/icons/icon_import_check.svg
+++ b/editor/icons/icon_import_check.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#84ffb1" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#45ff8b" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</svg>
diff --git a/editor/icons/icon_import_fail.svg b/editor/icons/icon_import_fail.svg
index e08812604..f4aa212c2 100644
--- a/editor/icons/icon_import_fail.svg
+++ b/editor/icons/icon_import_fail.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff8484" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff5d5d" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_key_invalid.svg b/editor/icons/icon_key_invalid.svg
index f1df51f7c..742859bac 100644
--- a/editor/icons/icon_key_invalid.svg
+++ b/editor/icons/icon_key_invalid.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff8484"/>
+<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff5d5d"/>
</g>
</svg>
diff --git a/editor/icons/icon_key_move_disabled.svg b/editor/icons/icon_key_move_disabled.svg
new file mode 100644
index 000000000..05c158dc3
--- /dev/null
+++ b/editor/icons/icon_key_move_disabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m7.984 1.002c-0.259 4e-3 -0.507 0.108-0.691 0.291l-2 2 1.414 1.414 1.293-1.293 1.293 1.293 1.414-1.414-2-2c-0.191-0.191-0.452-0.296-0.722-0.291h-1e-3zm-4.691 4.291l-2 2c-0.39 0.391-0.39 1.024 0 1.414l2 2 1.414-1.414-1.293-1.293 1.293-1.293-1.414-1.414zm9.414 0l-1.414 1.414 1.293 1.293-1.293 1.293 1.414 1.414 2-2c0.39-0.39 0.39-1.023 0-1.414l-2-2zm-6 6l-1.414 1.414 2 2c0.391 0.391 1.024 0.391 1.414 0l2-2-1.414-1.414-1.293 1.293-1.293-1.293z" fill="#e0e0e0" fill-opacity=".5" fill-rule="evenodd"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/>
+</svg>
diff --git a/editor/icons/icon_key_move_enabled.svg b/editor/icons/icon_key_move_enabled.svg
new file mode 100644
index 000000000..2d455f2d8
--- /dev/null
+++ b/editor/icons/icon_key_move_enabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m7.984 1.002c-0.259 4e-3 -0.507 0.108-0.691 0.291l-2 2 1.414 1.414 1.293-1.293 1.293 1.293 1.414-1.414-2-2c-0.191-0.191-0.452-0.296-0.722-0.291h-1e-3zm-4.691 4.291l-2 2c-0.39 0.391-0.39 1.024 0 1.414l2 2 1.414-1.414-1.293-1.293 1.293-1.293-1.414-1.414zm9.414 0l-1.414 1.414 1.293 1.293-1.293 1.293 1.414 1.414 2-2c0.39-0.39 0.39-1.023 0-1.414l-2-2zm-6 6l-1.414 1.414 2 2c0.391 0.391 1.024 0.391 1.414 0l2-2-1.414-1.414-1.293 1.293-1.293-1.293z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/>
+</svg>
diff --git a/editor/icons/icon_key_rotate_disabled.svg b/editor/icons/icon_key_rotate_disabled.svg
new file mode 100644
index 000000000..6394bfd82
--- /dev/null
+++ b/editor/icons/icon_key_rotate_disabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8.088 1.001c-0.102-1e-3 -0.203 0-0.305 2e-3 -0.233 8e-3 -0.466 0.027-0.697 0.057-2.973 0.392-5.366 2.633-5.951 5.574-0.46 2.319 0.281 4.712 1.97 6.365h-1.105v2h4c0.308 1e-3 0.599-0.141 0.788-0.384 0.19-0.243 0.257-0.559 0.183-0.858l-1-4-1.942 0.487 0.281 1.121c-0.84-0.92-1.308-2.12-1.31-3.366 0-2.761 2.239-5 5-5 1.326 0 2.598 0.527 3.536 1.465 0.937 0.938 1.464 2.209 1.464 3.535-1e-3 1.326-0.529 2.597-1.467 3.534l1.416 1.416c2.12-2.121 2.654-5.356 1.328-8.045-1.165-2.362-3.556-3.869-6.189-3.903z" fill="#e0e0e0" fill-opacity=".5"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/>
+</svg>
diff --git a/editor/icons/icon_key_rotate_enabled.svg b/editor/icons/icon_key_rotate_enabled.svg
new file mode 100644
index 000000000..1dcb12c8a
--- /dev/null
+++ b/editor/icons/icon_key_rotate_enabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8.088 1.001c-0.102-1e-3 -0.203 0-0.305 2e-3 -0.233 8e-3 -0.466 0.027-0.697 0.057-2.973 0.392-5.366 2.633-5.951 5.574-0.46 2.319 0.281 4.712 1.97 6.365h-1.105v2h4c0.308 1e-3 0.599-0.141 0.788-0.384 0.19-0.243 0.257-0.559 0.183-0.858l-1-4-1.942 0.487 0.281 1.121c-0.84-0.92-1.308-2.12-1.31-3.366 0-2.761 2.239-5 5-5 1.326 0 2.598 0.527 3.536 1.465 0.937 0.938 1.464 2.209 1.464 3.535-1e-3 1.326-0.529 2.597-1.467 3.534l1.416 1.416c2.12-2.121 2.654-5.356 1.328-8.045-1.165-2.362-3.556-3.869-6.189-3.903z" fill="#e0e0e0" fill-opacity=".99608"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/>
+</svg>
diff --git a/editor/icons/icon_key_scale_disabled.svg b/editor/icons/icon_key_scale_disabled.svg
new file mode 100644
index 000000000..9601e4925
--- /dev/null
+++ b/editor/icons/icon_key_scale_disabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m9 1c-0.552 0-1 0.448-1 1s0.448 1 1 1h2.586l-1.293 1.293 1.414 1.414 1.293-1.293v2.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-5c0-0.552-0.448-1-1-1h-5zm-7 7c-0.552 0-1 0.448-1 1v5c0 0.552 0.448 1 1 1h5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2.586l1.293-1.293-1.414-1.414-1.293 1.293v-2.586c0-0.552-0.448-1-1-1z" fill="#e0e0e0" fill-opacity=".5" fill-rule="evenodd"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/>
+</svg>
diff --git a/editor/icons/icon_key_scale_enabled.svg b/editor/icons/icon_key_scale_enabled.svg
new file mode 100644
index 000000000..f00f3db35
--- /dev/null
+++ b/editor/icons/icon_key_scale_enabled.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m9 1c-0.552 0-1 0.448-1 1s0.448 1 1 1h2.586l-1.293 1.293 1.414 1.414 1.293-1.293v2.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-5c0-0.552-0.448-1-1-1h-5zm-7 7c-0.552 0-1 0.448-1 1v5c0 0.552 0.448 1 1 1h5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2.586l1.293-1.293-1.414-1.414-1.293 1.293v-2.586c0-0.552-0.448-1-1-1z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/>
+<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/>
+</svg>
diff --git a/editor/icons/icon_node_warning.svg b/editor/icons/icon_node_warning.svg
index 5c03bad34..66663f7d6 100644
--- a/editor/icons/icon_node_warning.svg
+++ b/editor/icons/icon_node_warning.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffd684" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffdd65" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_sample_library.svg b/editor/icons/icon_sample_library.svg
index b5ec2bb43..403ea5ff4 100644
--- a/editor/icons/icon_sample_library.svg
+++ b/editor/icons/icon_sample_library.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#ff8484">
-<path transform="translate(0 1036.4)" d="m9 8v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4z"/>
-<path d="m7.0215 1037.4a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7226-0.52344-1.0468a1.0001 1.0001 0 0 0 -0.89453 -0.5528h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.3223l0.58984-4.7226 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.5527h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4472a1.0001 1.0001 0 0 0 -0.88672 -0.5508z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m7.0215 1.002a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7227-0.52344-1.0469a1.0001 1.0001 0 0 0 -0.89453 -0.55273h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.32227l0.58984-4.7227 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.55273h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4473a1.0001 1.0001 0 0 0 -0.88672 -0.55078zm1.9785 6.998v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#ff8484"/>
</g>
</svg>
diff --git a/editor/icons/icon_slider_joint.svg b/editor/icons/icon_slider_joint.svg
index 479323bf9..d1469058d 100644
--- a/editor/icons/icon_slider_joint.svg
+++ b/editor/icons/icon_slider_joint.svg
@@ -1,10 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m3 1051.4h5l-1-4z" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m6 1048.4 9-9v3l-8 8z" fill="#fb9b9b"/>
-<path d="m10 1040.4-9 9v-3l8-8z" fill="#fb9b9b"/>
-<path d="m13 1037.4h-5l1 4z" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m10 1038.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/>
-<path d="m11 1050.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m5 1c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h3l-7 7v3l12-12zm10 2-12 12h8c0.55228 0 1-0.44772 1-1s-0.44772-1-1-1h-3l7-7z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_snap.svg b/editor/icons/icon_snap.svg
index b1f36cfe4..0195f7cfc 100644
--- a/editor/icons/icon_snap.svg
+++ b/editor/icons/icon_snap.svg
@@ -1,10 +1,93 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" fill="#f3f3f3"/>
-<path d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" fill="#ff8484"/>
-<rect x="7" y="1047.4" width="2" height="2" fill="#ff8484"/>
-<rect x="13" y="1047.4" width="2" height="2" fill="#ff8484"/>
-<rect x="7" y="1049.4" width="2" height="2" fill="#fff"/>
-<rect x="13" y="1049.4" width="2" height="2" fill="#fff"/>
-</g>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg848"
+ sodipodi:docname="icon_snap.svg"
+ inkscape:version="0.92.2 5c3e80d, 2017-08-06">
+ <metadata
+ id="metadata854">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs852" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2558"
+ inkscape:window-height="1422"
+ id="namedview850"
+ showgrid="true"
+ inkscape:pagecheckerboard="true"
+ inkscape:zoom="26.317631"
+ inkscape:cx="-14.078109"
+ inkscape:cy="-1.3201296"
+ inkscape:window-x="1366"
+ inkscape:window-y="16"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg848">
+ <inkscape:grid
+ type="xygrid"
+ id="grid862" />
+ </sodipodi:namedview>
+ <path
+ style="fill:#ff8484;stroke-width:1.48039925"
+ inkscape:connector-curvature="0"
+ id="path836"
+ d="m 3.9501321,14.20668 a 5.9215969,5.9215969 0 0 0 8.0890509,-2.167455 l -2.5641252,-1.4804 A 2.9607985,2.9607985 0 0 1 5.4305313,11.642553 2.9607985,2.9607985 0 0 1 4.3468039,7.5980268 L 1.7826772,6.1176278 A 5.9215969,5.9215969 0 0 0 3.9501321,14.20668 Z" />
+ <rect
+ style="fill:#ff8484;stroke-width:1.48039925"
+ id="rect838"
+ height="2.9607985"
+ width="2.9607985"
+ y="-4.4066463"
+ x="-16.44585"
+ transform="rotate(-150)" />
+ <rect
+ style="fill:#ff8484;stroke-width:1.48039925"
+ id="rect840"
+ height="2.9607985"
+ width="2.9607985"
+ y="-4.4066463"
+ x="-7.5634551"
+ transform="rotate(-150)" />
+ <rect
+ style="fill:#ffffff;stroke-width:1.48039925"
+ id="rect842"
+ height="2.9607985"
+ width="2.9607985"
+ y="-1.4458472"
+ x="-16.44585"
+ transform="rotate(-150)" />
+ <rect
+ style="fill:#ffffff;stroke-width:1.48039925"
+ id="rect844"
+ height="2.9607985"
+ width="2.9607985"
+ y="-1.4458472"
+ x="-7.5634551"
+ transform="rotate(-150)" />
</svg>
diff --git a/editor/icons/icon_snap_grid.svg b/editor/icons/icon_snap_grid.svg
new file mode 100644
index 000000000..b47949632
--- /dev/null
+++ b/editor/icons/icon_snap_grid.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg913"
+ sodipodi:docname="icon_snap_grid.svg"
+ inkscape:version="0.92.2 5c3e80d, 2017-08-06">
+ <metadata
+ id="metadata919">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs917" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2558"
+ inkscape:window-height="1422"
+ id="namedview915"
+ showgrid="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:zoom="52.635261"
+ inkscape:cx="6.4374987"
+ inkscape:cy="5.7074131"
+ inkscape:window-x="1366"
+ inkscape:window-y="16"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg913" />
+ <g
+ transform="translate(0 -1036.4)"
+ id="g911">
+ <path
+ d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z"
+ fill="#f3f3f3"
+ id="path899" />
+ <path
+ d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z"
+ fill="#ff8484"
+ id="path901" />
+ <rect
+ x="7"
+ y="1047.4"
+ width="2"
+ height="2"
+ fill="#ff8484"
+ id="rect903" />
+ <rect
+ x="13"
+ y="1047.4"
+ width="2"
+ height="2"
+ fill="#ff8484"
+ id="rect905" />
+ <rect
+ x="7"
+ y="1049.4"
+ width="2"
+ height="2"
+ fill="#fff"
+ id="rect907" />
+ <rect
+ x="13"
+ y="1049.4"
+ width="2"
+ height="2"
+ fill="#fff"
+ id="rect909" />
+ </g>
+</svg>
diff --git a/editor/icons/icon_warning.svg b/editor/icons/icon_warning.svg
index 455e7b187..8f6bf2184 100644
--- a/editor/icons/icon_warning.svg
+++ b/editor/icons/icon_warning.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<rect y="1044.4" width="8" height="8" ry="4" fill="#ffd684"/>
+<rect y="1044.4" width="8" height="8" ry="4" fill="#ffdd65"/>
</g>
</svg>
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index cc519c1c4..b448ab892 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -120,13 +120,13 @@ String ResourceImporterScene::get_preset_name(int p_idx) const {
switch (p_idx) {
case PRESET_SINGLE_SCENE: return TTR("Import as Single Scene");
- case PRESET_SEPERATE_ANIMATIONS: return TTR("Import with Seperate Animations");
+ case PRESET_SEPARATE_ANIMATIONS: return TTR("Import with Separate Animations");
case PRESET_SEPARATE_MATERIALS: return TTR("Import with Separate Materials");
case PRESET_SEPARATE_MESHES: return TTR("Import with Separate Objects");
case PRESET_SEPARATE_MESHES_AND_MATERIALS: return TTR("Import with Separate Objects+Materials");
- case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Animations");
- case PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Materials+Animations");
- case PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Materials+Animations");
+ case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Separate Objects+Animations");
+ case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Materials+Animations");
+ case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Objects+Materials+Animations");
case PRESET_MULTIPLE_SCENES: return TTR("Import as Multiple Scenes");
case PRESET_MULTIPLE_SCENES_AND_MATERIALS: return TTR("Import as Multiple Scenes+Materials");
}
@@ -954,10 +954,10 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
script_ext_hint += "*." + E->get();
}
- bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
- bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS;
- bool animations_out = p_preset == PRESET_SEPERATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0));
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 652977b98..c3a66aa8b 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -85,14 +85,14 @@ class ResourceImporterScene : public ResourceImporter {
enum Presets {
PRESET_SEPARATE_MATERIALS,
PRESET_SEPARATE_MESHES,
- PRESET_SEPERATE_ANIMATIONS,
+ PRESET_SEPARATE_ANIMATIONS,
PRESET_SINGLE_SCENE,
PRESET_SEPARATE_MESHES_AND_MATERIALS,
PRESET_SEPARATE_MESHES_AND_ANIMATIONS,
- PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS,
- PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS,
+ PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS,
+ PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS,
PRESET_MULTIPLE_SCENES,
PRESET_MULTIPLE_SCENES_AND_MATERIALS,
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index d7762a66d..c8db1763a 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -103,13 +103,11 @@ void AnimationPlayerEditor::_notification(int p_what) {
get_tree()->connect("node_removed", this, "_node_removed");
add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel"));
- add_constant_override("separation", get_constant("separation", "VBoxContainer"));
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel"));
- add_constant_override("separation", get_constant("separation", "VBoxContainer"));
} break;
case NOTIFICATION_THEME_CHANGED: {
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index b28da54c6..27dad7756 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -53,6 +53,8 @@
#define MIN_ZOOM 0.01
#define MAX_ZOOM 100
+#define RULER_WIDTH 15 * EDSCALE
+
class SnapDialog : public ConfirmationDialog {
GDCLASS(SnapDialog, ConfirmationDialog);
@@ -109,13 +111,13 @@ public:
label->set_h_size_flags(SIZE_EXPAND_FILL);
grid_step_x = memnew(SpinBox);
- grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_min(0.01);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
grid_step_x->set_suffix("px");
child_container->add_child(grid_step_x);
grid_step_y = memnew(SpinBox);
- grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_min(0.01);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
grid_step_y->set_suffix("px");
child_container->add_child(grid_step_y);
@@ -149,7 +151,7 @@ public:
child_container->add_child(rotation_step);
}
- void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
+ void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
grid_offset_x->set_value(p_grid_offset.x);
grid_offset_y->set_value(p_grid_offset.y);
grid_step_x->set_value(p_grid_step.x);
@@ -158,11 +160,9 @@ public:
rotation_step->set_value(p_rotation_step * (180 / Math_PI));
}
- void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
- p_grid_offset.x = grid_offset_x->get_value();
- p_grid_offset.y = grid_offset_y->get_value();
- p_grid_step.x = grid_step_x->get_value();
- p_grid_step.y = grid_step_y->get_value();
+ void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+ p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value());
+ p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value());
p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
}
@@ -222,6 +222,135 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
undo_redo->commit_action();
}
+void CanvasItemEditor::_snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) {
+ float radius = p_radius / zoom;
+ float dist;
+
+ Transform2D rot_trans = Transform2D(rotation, Point2());
+ p_value = rot_trans.inverse().xform(p_value);
+ p_target_snap = rot_trans.inverse().xform(p_target_snap);
+ r_current_snap = rot_trans.inverse().xform(r_current_snap);
+
+ dist = Math::abs(p_value.x - p_target_snap.x);
+ if (p_radius < 0 || dist < radius && (!r_snapped[0] || dist < Math::abs(r_current_snap.x - p_value.x))) {
+ r_current_snap.x = p_target_snap.x;
+ r_snapped[0] = true;
+ }
+
+ dist = Math::abs(p_value.y - p_target_snap.y);
+ if (p_radius < 0 || dist < radius && (!r_snapped[1] || dist < Math::abs(r_current_snap.y - p_value.y))) {
+ r_current_snap.y = p_target_snap.y;
+ r_snapped[1] = true;
+ }
+
+ r_current_snap = rot_trans.xform(r_current_snap);
+}
+
+void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) {
+ const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
+ if (canvas_item && p_current != p_to_snap) {
+ Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
+ Transform2D to_snap_transform = p_to_snap->get_global_transform_with_canvas();
+ if (ci_transform.get_rotation() == to_snap_transform.get_rotation()) {
+ Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position());
+ Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size());
+
+ _snap_if_closer(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
+ _snap_if_closer(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
+ }
+ }
+ for (int i = 0; i < p_current->get_child_count(); i++) {
+ _snap_other_nodes(p_value, r_current_snap, r_snapped, p_current->get_child(i), p_to_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
+ Vector2 output = p_target;
+ real_t rotation = 0.0;
+
+ if (p_canvas_item) {
+ Point2 begin;
+ Point2 end;
+ rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation();
+
+ if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
+ // Parent sides and center
+ 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)));
+ end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
+ can_snap = true;
+ } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
+ begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position());
+ end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position() + parent_ci->get_item_rect().get_size());
+ can_snap = true;
+ }
+
+ if (can_snap) {
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, (begin + end) / 2.0, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+ }
+
+ // Self anchors (for sides)
+ 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))));
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+ }
+
+ // Self sides (for anchors)
+ 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->get_item_rect().get_position());
+ end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position() + p_canvas_item->get_item_rect().get_size());
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+
+ // Other nodes sides
+ if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
+ _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item);
+ }
+ }
+
+ if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) {
+ // Grid
+ Point2 offset = grid_offset;
+ if (snap_relative) {
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ 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();
+ }
+ }
+ Point2 grid_output;
+ grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
+ grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
+ _snap_if_closer(p_target, grid_output, output, snapped, 0.0, -1.0);
+ }
+
+ if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
+ // Pixel
+ output = output.snapped(Size2(1, 1));
+ }
+
+ return output;
+}
+
+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;
+}
+
void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventKey> k = p_ev;
@@ -232,22 +361,34 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
if (k->get_control())
return;
- if (k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V && drag == DRAG_NONE && can_move_pivot) {
-
- if (k->get_shift()) {
+ 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 (!Input::get_singleton()->is_mouse_button_pressed(0)) {
+ } 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_pos();
+ 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());
- List<Node *> &selection = editor_selection->get_selected_node_list();
- Vector2 mouse_pos = viewport->get_local_mouse_pos();
- 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);
-
- _edit_set_pivot(mouse_pos);
+ _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)) {
+ // 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();
}
}
}
@@ -272,38 +413,25 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
return memnew(CanvasItemEditorSelectedItem);
}
-inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
- float offset = p_snap_relative ? p_start : p_offset;
- return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
-}
-
-Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
- if (snap_grid) {
- p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
- p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
- }
- if (snap_pixel)
- p_target = p_target.snapped(Size2(1, 1));
-
- return p_target;
-}
-
-float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
- return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
-}
-
Dictionary CanvasItemEditor::get_state() const {
Dictionary state;
state["zoom"] = zoom;
state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value());
//state["ofs"]=-transform.get_origin();
- state["snap_offset"] = snap_offset;
- state["snap_step"] = snap_step;
+ 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_show_grid"] = snap_show_grid;
+ state["show_grid"] = show_grid;
+ state["show_rulers"] = show_rulers;
+ state["show_helpers"] = show_helpers;
state["snap_rotation"] = snap_rotation;
state["snap_relative"] = snap_relative;
state["snap_pixel"] = snap_pixel;
@@ -324,12 +452,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
v_scroll->set_value(ofs.y);
}
- if (state.has("snap_step")) {
- snap_step = state["snap_step"];
+ if (state.has("grid_offset")) {
+ grid_offset = state["grid_offset"];
}
- if (state.has("snap_offset")) {
- snap_offset = state["snap_offset"];
+ if (state.has("grid_step")) {
+ grid_step = state["grid_step"];
}
if (state.has("snap_rotation_step")) {
@@ -340,40 +468,81 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
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_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_grid")) {
snap_grid = state["snap_grid"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked(idx, 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("snap_show_grid")) {
- snap_show_grid = state["snap_show_grid"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
- edit_menu->get_popup()->set_item_checked(idx, snap_show_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_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 = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
- edit_menu->get_popup()->set_item_checked(idx, 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 = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
- edit_menu->get_popup()->set_item_checked(idx, 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 = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx, 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_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->set_item_checked(idx, 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();
@@ -495,6 +664,7 @@ void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_ap
if (!p_append) {
editor_selection->clear();
viewport->update();
+ viewport_base->update();
};
if (p_box_selection) {
@@ -534,6 +704,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po
}
viewport->update();
+ viewport_base->update();
return still_selected;
}
@@ -566,7 +737,7 @@ void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE
Vector2 drag = p_dir;
if (p_snap)
- drag *= snap_step;
+ 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());
@@ -649,7 +820,7 @@ int CanvasItemEditor::get_item_count() {
return ic;
}
-CanvasItem *CanvasItemEditor::get_single_item() {
+CanvasItem *CanvasItemEditor::_get_single_item() {
Map<Node *, Object *> &selection = editor_selection->get_selection();
@@ -674,7 +845,7 @@ CanvasItem *CanvasItemEditor::get_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();
+ CanvasItem *canvas_item = _get_single_item();
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
@@ -738,35 +909,7 @@ CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const
return DRAG_NONE;
}
-float CanvasItemEditor::_anchor_snap(float p_anchor, bool *p_snapped, float p_opposite_anchor) {
- bool snapped = false;
- float dist, dist_min = 0.0;
- float radius = 0.05 / zoom;
- float basic_anchors[3] = { 0.0, 0.5, 1.0 };
- for (int i = 0; i < 3; i++) {
- dist = fabs(p_anchor - basic_anchors[i]);
- if (dist < radius) {
- if (!snapped || dist <= dist_min) {
- p_anchor = basic_anchors[i];
- dist_min = dist;
- snapped = true;
- }
- }
- }
- dist = fabs(p_anchor - p_opposite_anchor);
- if (p_opposite_anchor >= 0 && dist < radius) {
- if (!snapped || dist <= dist_min) {
- p_anchor = p_opposite_anchor;
- dist_min = dist;
- snapped = true;
- }
- }
- if (p_snapped)
- *p_snapped = snapped;
- return p_anchor;
-}
-
-Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor) {
+Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) {
ERR_FAIL_COND_V(!p_control, Vector2());
Transform2D parent_transform = p_control->get_transform().affine_inverse();
@@ -775,7 +918,7 @@ Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor
return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y));
}
-Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 position) {
+Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) {
ERR_FAIL_COND_V(!p_control, Vector2());
Size2 parent_size = p_control->get_parent_area_size();
@@ -784,7 +927,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 positi
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();
+ CanvasItem *canvas_item = _get_single_item();
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
Control *control = Object::cast_to<Control>(canvas_item);
@@ -920,28 +1063,12 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) {
}
void CanvasItemEditor::_snap_changed() {
- ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
+ grid_step_multiplier = 0;
+ viewport_base->update();
viewport->update();
}
-void CanvasItemEditor::_dialog_value_changed(double) {
-
- if (updating_value_dialog)
- return;
-
- switch (last_option) {
-
- case ZOOM_SET: {
-
- zoom = dialog_val->get_value() / 100.0;
- _update_scroll(0);
- viewport->update();
-
- } break;
- default: {}
- }
-}
-
void CanvasItemEditor::_selection_result_pressed(int p_result) {
if (selection_results.size() <= p_result)
@@ -962,7 +1089,7 @@ void CanvasItemEditor::_selection_menu_hide() {
void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
Node *scene = editor->get_edited_scene();
if (!scene)
@@ -1070,7 +1197,7 @@ void CanvasItemEditor::_update_cursor() {
viewport->set_default_cursor_shape(c);
}
-void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
+void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) {
{
EditorNode *en = editor;
@@ -1103,7 +1230,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
float prev_zoom = zoom;
zoom = zoom * (1 - (0.05 * b->get_factor()));
{
- Point2 ofs = b->get_position();
+ Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
ofs = ofs / prev_zoom - ofs / zoom;
h_scroll->set_value(h_scroll->get_value() + ofs.x);
v_scroll->set_value(v_scroll->get_value() + ofs.y);
@@ -1127,7 +1254,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
float prev_zoom = zoom;
zoom = zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95);
{
- Point2 ofs = b->get_position();
+ Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
ofs = ofs / prev_zoom - ofs / zoom;
h_scroll->set_value(h_scroll->get_value() + ofs.x);
v_scroll->set_value(v_scroll->get_value() + ofs.y);
@@ -1216,9 +1343,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
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();
+ Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
mouse_pos = transform.affine_inverse().xform(mouse_pos);
- mouse_pos = snap_point(mouse_pos);
+ mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item());
_edit_set_pivot(mouse_pos);
}
return;
@@ -1339,8 +1466,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
E->get().to
};
- Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s);
- float d = p.distance_to(b->get_position());
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s);
+ float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
if (d < bone_width && d < closest_dist) {
Cbone = E;
closest_dist = d;
@@ -1397,12 +1524,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
// Single selected item
- CanvasItem *canvas_item = get_single_item();
+ CanvasItem *canvas_item = _get_single_item();
if (canvas_item) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
ERR_FAIL_COND(!se);
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
// Rotation
if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
@@ -1440,7 +1567,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
// Drag anchor handles
- if (Object::cast_to<Control>(canvas_item)) {
+ 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);
@@ -1453,7 +1581,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
// Multiple selected items
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) {
// Drag the nodes
@@ -1513,12 +1641,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
// Mouse motion event
_update_cursor();
- if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- viewport->call_deferred("grab_focus");
+ if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+ viewport_base->call_deferred("grab_focus");
if (box_selecting) {
// Update box selection
- box_selecting_to = transform.affine_inverse().xform(m->get_position());
+ box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
viewport->update();
return;
}
@@ -1564,7 +1692,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
Vector2 dfrom = drag_from;
- Vector2 dto = transform.affine_inverse().xform(m->get_position());
+ Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
if (canvas_item->has_meta("_edit_lock_"))
continue;
@@ -1598,60 +1726,74 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
continue;
}
+ bool uniform = m->get_shift();
+ bool symmetric = m->get_alt();
+
+ 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;
+ }
+
Control *control = Object::cast_to<Control>(canvas_item);
if (control) {
// Drag and snap the anchor
- Vector2 anchor = _position_to_anchor(control, canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto - drag_from + drag_point_from));
+ Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse();
+
+ Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from);
+ anchor = _position_to_anchor(control, anchor);
+
+ Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | 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));
+
+ bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
switch (drag) {
case DRAG_ANCHOR_TOP_LEFT:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false);
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_TOP_RIGHT:
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false);
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_BOTTOM_RIGHT:
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false);
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false);
- continue;
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
break;
case DRAG_ANCHOR_BOTTOM_LEFT:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false);
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_ALL:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x));
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x));
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y));
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y));
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
continue;
break;
}
}
- bool uniform = m->get_shift();
- bool symmetric = m->get_alt();
-
- if (drag == DRAG_ALL || drag == DRAG_NODE_2D)
- dto -= drag_from - drag_point_from;
-
- if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) {
- 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;
- }
- }
-
dfrom = drag_point_from;
- dto = snap_point(dto, drag_point_from);
+ dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item());
- Vector2 drag_vector =
+ drag_vector =
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
@@ -1901,56 +2043,148 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
}
+void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
+ Color color = Color(0.8, 0.8, 0.8, 0.5);
+ Ref<Font> font = get_font("font", "Label");
+ Size2 text_size = font->get_string_size(p_string);
+ switch (p_side) {
+ case MARGIN_LEFT:
+ p_position += Vector2(-text_size.x - 5, text_size.y / 2);
+ break;
+ case MARGIN_TOP:
+ p_position += Vector2(-text_size.x / 2, -5);
+ break;
+ case MARGIN_RIGHT:
+ p_position += Vector2(5, text_size.y / 2);
+ break;
+ case MARGIN_BOTTOM:
+ p_position += Vector2(-text_size.x / 2, text_size.y + 5);
+ break;
+ }
+ viewport->draw_string(font, p_position, p_string, color);
+}
+
+void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
+ String str = vformat("%d px", p_value);
+ if (p_value != 0) {
+ _draw_text_at_position(p_position, str, p_side);
+ }
+}
+
void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
+ String str = vformat("%.1f %%", p_value * 100.0);
if (p_value != 0) {
- Color color = Color(0.8, 0.8, 0.8, 0.5);
- Ref<Font> font = get_font("font", "Label");
- String str = vformat("%.1f %%", p_value * 100.0);
- Size2 text_size = font->get_string_size(str);
- switch (p_side) {
- case MARGIN_LEFT:
- p_position += Vector2(-text_size.x - 5, text_size.y / 2);
- break;
- case MARGIN_TOP:
- p_position += Vector2(-text_size.x / 2, -5);
- break;
- case MARGIN_RIGHT:
- p_position += Vector2(5, text_size.y / 2);
- break;
- case MARGIN_BOTTOM:
- p_position += Vector2(-text_size.x / 2, text_size.y + 5);
- break;
- }
- viewport->draw_string(font, p_position, str, color);
+ _draw_text_at_position(p_position, str, p_side);
}
}
-void CanvasItemEditor::_viewport_draw() {
+void CanvasItemEditor::_draw_rulers() {
+ Color graduation_color = Color(0.5, 0.5, 0.5, 1);
+ Color bg_color = get_color("dark_color_2", "Editor");
+ Color font_color = Color(0.8, 0.8, 0.8, 1);
+ Ref<Font> font = get_font("rulers", "EditorFonts");
- // TODO fetch the viewport?
+ // 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());
+ 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) {
- Ref<Texture> pivot = get_icon("EditorPivot", "EditorIcons");
- _update_scrollbars();
- RID ci = viewport->get_canvas_item();
+ ruler_transform.scale_basis(Point2(2, 2));
+ }
+ } else {
+ float basic_rule = 100;
+ for (int i = 0; basic_rule * zoom > 100; i++) {
+ basic_rule /= (i % 2) ? 5.0 : 2.0;
+ }
+ 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));
+ }
+
+ // Subdivisions
+ int major_subdivision = 2;
+ Transform2D major_subdivide = Transform2D();
+ major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
+
+ int minor_subdivision = 5;
+ Transform2D minor_subdivide = Transform2D();
+ 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 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size());
- if (snap_show_grid) {
+ // Draw top ruler
+ viewport_base->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);
+ 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);
+ } 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);
+ } else {
+ viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, 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);
+ 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);
+ 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);
+ } 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);
+ } else {
+ viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ }
+ }
+ }
+ viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
+}
+
+void CanvasItemEditor::_draw_focus() {
+ if (viewport_base->has_focus()) {
+ get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size()));
+ }
+}
+
+void CanvasItemEditor::_draw_grid() {
+ if (show_grid) {
//Draw the grid
Size2 s = viewport->get_size();
int last_cell = 0;
Transform2D xform = transform.affine_inverse();
- Vector2 grid_offset;
- if (snap_relative && snap_grid && get_item_count() > 0) {
+ Vector2 real_grid_offset;
+ if (snap_relative && get_item_count() > 0) {
Vector2 topleft = _find_topleftmost_point();
- grid_offset.x = fmod(topleft.x, snap_step.x);
- grid_offset.y = fmod(topleft.y, snap_step.y);
+ real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier));
+ real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier));
} else {
- grid_offset = snap_offset;
+ real_grid_offset = grid_offset;
}
- if (snap_step.x != 0) {
+ if (grid_step.x != 0) {
for (int i = 0; i < s.width; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - grid_offset.x) / snap_step.x));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier))));
if (i == 0)
last_cell = cell;
if (last_cell != cell)
@@ -1959,9 +2193,9 @@ void CanvasItemEditor::_viewport_draw() {
}
}
- if (snap_step.y != 0) {
+ if (grid_step.y != 0) {
for (int i = 0; i < s.height; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - grid_offset.y) / snap_step.y));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier))));
if (i == 0)
last_cell = cell;
if (last_cell != cell)
@@ -1970,21 +2204,15 @@ void CanvasItemEditor::_viewport_draw() {
}
}
}
+}
- if (viewport->has_focus()) {
- Size2 size = viewport->get_size();
- get_stylebox("Focus", "EditorStyles")->draw(ci, Rect2(Point2(), size));
- }
-
- Ref<Texture> lock = get_icon("Lock", "EditorIcons");
- Ref<Texture> group = get_icon("Group", "EditorIcons");
-
- bool single = get_single_item() != NULL;
-
- Map<Node *, Object *> &selection = editor_selection->get_selection();
-
+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()) {
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
@@ -2036,10 +2264,10 @@ void CanvasItemEditor::_viewport_draw() {
if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
- if (Object::cast_to<Node2D>(canvas_item)) {
-
- if (Object::cast_to<Node2D>(canvas_item)->edit_has_pivot()) {
- viewport->draw_texture(pivot, xform.get_origin() + (-pivot->get_size() / 2).floor());
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d) {
+ if (node2d->edit_has_pivot()) {
+ viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor());
can_move_pivot = true;
pivot_found = true;
}
@@ -2049,12 +2277,15 @@ void CanvasItemEditor::_viewport_draw() {
if (control) {
Vector2 pivot_ofs = control->get_pivot_offset();
if (pivot_ofs != Vector2()) {
- viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor());
+ 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) {
+ 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);
+
float anchors_values[4];
anchors_values[0] = control->get_anchor(MARGIN_LEFT);
anchors_values[1] = control->get_anchor(MARGIN_TOP);
@@ -2069,6 +2300,7 @@ void CanvasItemEditor::_viewport_draw() {
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) {
@@ -2091,7 +2323,6 @@ void CanvasItemEditor::_viewport_draw() {
// Draw the 4 lines when dragged
bool snapped;
Color color_snapped = Color(0.64, 0.93, 0.67, 0.5);
- Color color_base = Color(0.8, 0.8, 0.8, 0.5);
Vector2 corners_pos[4];
for (int i = 0; i < 4; i++) {
@@ -2104,7 +2335,7 @@ void CanvasItemEditor::_viewport_draw() {
float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i];
line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val);
line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val);
- _anchor_snap(anchors_values[i], &snapped);
+ snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1);
}
@@ -2136,6 +2367,83 @@ void CanvasItemEditor::_viewport_draw() {
for (int i = 0; i < 4; i++) {
anchor_handle->draw_rect(ci, anchor_rects[i]);
}
+
+ // Draw the margin values and the node width/height when dragging control side
+ float ratio = 0.33;
+ Transform2D parent_transform = xform * control->get_transform().affine_inverse();
+ float node_pos_in_parent[4];
+
+ node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * control->get_parent_area_size().width + control->get_margin(MARGIN_LEFT);
+ node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * control->get_parent_area_size().height + control->get_margin(MARGIN_TOP);
+ 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) {
+ 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);
+ _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;
+ }
+ switch (drag) {
+ 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);
+ _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;
+ }
+ switch (drag) {
+ 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));
+ _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;
+ }
+ switch (drag) {
+ 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));
+ _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;
+ }
+
+ switch (drag) {
+ //Draw the ghost rect if the node if rotated/scaled
+ case DRAG_LEFT:
+ case DRAG_TOP_LEFT:
+ case DRAG_TOP:
+ case DRAG_TOP_RIGHT:
+ case DRAG_RIGHT:
+ case DRAG_BOTTOM_RIGHT:
+ case DRAG_BOTTOM:
+ case DRAG_BOTTOM_LEFT:
+ case DRAG_ALL:
+ if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) {
+ Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size());
+ viewport->draw_rect(parent_transform.xform(rect), color_base, false);
+ }
+ break;
+ }
}
}
@@ -2158,33 +2466,32 @@ void CanvasItemEditor::_viewport_draw() {
}
}
}
-
- //DRAW_EMPTY_RECT( Rect2( current_window->get_scroll()-Point2(1,1), get_size()+Size2(2,2)), Color(0.8,0.8,1.0,0.8) );
- //E->get().last_rect = rect;
}
-
pivot_button->set_disabled(!pivot_found);
- VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
-
- Color x_axis_color(1.0, 0.4, 0.4, 0.6);
- Color y_axis_color(0.4, 1.0, 0.4, 0.6);
- Color area_axis_color(0.4, 0.4, 1.0, 0.4);
- Color rotate_color(0.4, 0.7, 1.0, 0.8);
-
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(h_scroll->get_min(), 0) + transform.get_origin(), Point2(h_scroll->get_max(), 0) + transform.get_origin(), x_axis_color);
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, v_scroll->get_min()) + transform.get_origin(), Point2(0, v_scroll->get_max()) + transform.get_origin(), y_axis_color);
if (box_selecting) {
-
Point2 bsfrom = transform.xform(drag_from);
Point2 bsto = transform.xform(box_selecting_to);
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(bsfrom, bsto - bsfrom), Color(0.7, 0.7, 1.0, 0.3));
}
+ 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);
}
+}
+
+void CanvasItemEditor::_draw_axis() {
+ RID ci = viewport->get_canvas_item();
+
+ Color x_axis_color(1.0, 0.4, 0.4, 0.6);
+ 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);
Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
@@ -2196,34 +2503,12 @@ void CanvasItemEditor::_viewport_draw() {
};
for (int i = 0; i < 4; i++) {
-
VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color);
}
+}
- for (List<LockList>::Element *E = lock_list.front(); E; E = E->next()) {
-
- Vector2 ofs = transform.xform(E->get().pos);
- if (E->get().lock) {
-
- lock->draw(ci, ofs);
- ofs.x += lock->get_width();
- }
- if (E->get().group) {
-
- group->draw(ci, ofs);
- }
- }
-
- {
-
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty()) {
-
- over_plugin_list->forward_draw_over_canvas(transform, viewport);
- }
- }
+void CanvasItemEditor::_draw_bones() {
+ RID ci = viewport->get_canvas_item();
if (skeleton_show_bones) {
int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
@@ -2291,6 +2576,125 @@ void CanvasItemEditor::_viewport_draw() {
}
}
+void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) {
+ RID viewport_ci = viewport->get_canvas_item();
+
+ Transform2D transform_ci = p_xform;
+ CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
+ if (ci)
+ transform_ci = transform_ci * ci->get_transform();
+
+ for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
+ _draw_locks_and_groups(p_node->get_child(i), transform_ci);
+ }
+
+ if (ci) {
+ Ref<Texture> lock = get_icon("Lock", "EditorIcons");
+ if (p_node->has_meta("_edit_lock_")) {
+ lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0)));
+ }
+
+ Ref<Texture> group = get_icon("Group", "EditorIcons");
+ if (ci->has_meta("_edit_group_")) {
+ Vector2 ofs = transform_ci.xform(Point2(0, 0));
+ if (ci->has_meta("_edit_lock_"))
+ ofs = Point2(ofs.x + lock->get_size().x, ofs.y);
+ group->draw(viewport_ci, ofs);
+ }
+ }
+}
+
+void CanvasItemEditor::_build_bones_list(Node *p_node) {
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _build_bones_list(p_node->get_child(i));
+ }
+
+ CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ if (c && c->is_visible_in_tree()) {
+ if (c->has_meta("_edit_bone_")) {
+
+ ObjectID id = c->get_instance_id();
+ if (!bone_list.has(id)) {
+ BoneList bone;
+ bone.bone = id;
+ bone_list[id] = bone;
+ }
+
+ bone_list[id].last_pass = bone_last_frame;
+ }
+ }
+}
+
+void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) {
+ 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->get_item_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();
+ _draw_focus();
+}
+
+void CanvasItemEditor::_draw_viewport() {
+
+ // hide/show buttons depending on the selection
+ bool all_locked = true;
+ bool all_group = true;
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ if (selection.empty()) {
+ all_locked = false;
+ all_group = false;
+ } else {
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_lock_")) {
+ all_locked = false;
+ break;
+ }
+ }
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_group_")) {
+ all_group = false;
+ break;
+ }
+ }
+ }
+
+ lock_button->set_visible(!all_locked);
+ lock_button->set_disabled(selection.empty());
+ unlock_button->set_visible(all_locked);
+ group_button->set_visible(!all_group);
+ group_button->set_disabled(selection.empty());
+ ungroup_button->set_visible(all_group);
+
+ _update_scrollbars();
+
+ _draw_grid();
+ _draw_selection();
+ _draw_axis();
+ _draw_locks_and_groups(editor->get_edited_scene(), transform);
+
+ RID ci = viewport->get_canvas_item();
+ VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
+
+ EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
+ if (!over_plugin_list->empty()) {
+ over_plugin_list->forward_draw_over_canvas(transform, viewport);
+ }
+ _draw_focus();
+}
+
void CanvasItemEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_FIXED_PROCESS) {
@@ -2341,6 +2745,7 @@ void CanvasItemEditor::_notification(int p_what) {
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];
@@ -2389,6 +2794,9 @@ void CanvasItemEditor::_notification(int p_what) {
list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
+ snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
select_handle = get_icon("EditorHandle", "EditorIcons");
@@ -2399,6 +2807,10 @@ void CanvasItemEditor::_notification(int p_what) {
ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
+ zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
+ zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
+ zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
+
anchor_menu->set_icon(get_icon("Anchor", "EditorIcons"));
PopupMenu *p = anchor_menu->get_popup();
@@ -2433,6 +2845,9 @@ void CanvasItemEditor::_notification(int p_what) {
list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
+ snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
select_handle = get_icon("EditorHandle", "EditorIcons");
@@ -2474,66 +2889,23 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
drag = 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();
-}
-
-void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) {
-
- if (!p_node)
- return;
-
- CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
-
- for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
-
- //CanvasItem *r=NULL;
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_span(p_node->get_child(i), r_rect, p_xform * c->get_transform());
- else
- _find_canvas_items_span(p_node->get_child(i), r_rect, Transform2D());
- }
-
- if (c && c->is_visible_in_tree()) {
-
- Rect2 rect = c->get_item_rect();
- Transform2D xform = p_xform * c->get_transform();
-
- LockList lock;
- lock.lock = c->has_meta("_edit_lock_");
- lock.group = c->has_meta("_edit_group_");
-
- if (lock.group || lock.lock) {
- lock.pos = xform.xform(rect.position);
- lock_list.push_back(lock);
- }
-
- if (c->has_meta("_edit_bone_")) {
-
- ObjectID id = c->get_instance_id();
- if (!bone_list.has(id)) {
- BoneList bone;
- bone.bone = id;
- bone_list[id] = bone;
- }
-
- bone_list[id].last_pass = bone_last_frame;
- }
-
- 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_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());
+
Size2 size = viewport->get_size();
Size2 hmin = h_scroll->get_minimum_size();
Size2 vmin = v_scroll->get_minimum_size();
@@ -2550,11 +2922,12 @@ void CanvasItemEditor::_update_scrollbars() {
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
- lock_list.clear();
bone_last_frame++;
- if (editor->get_edited_scene())
- _find_canvas_items_span(editor->get_edited_scene(), canvas_item_rect, Transform2D());
+ 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;
@@ -2577,7 +2950,6 @@ void CanvasItemEditor::_update_scrollbars() {
Point2 ofs;
if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) {
-
v_scroll->hide();
ofs.y = canvas_item_rect.position.y;
} else {
@@ -2638,6 +3010,7 @@ void CanvasItemEditor::_update_scroll(float) {
editor->get_scene_root()->set_global_canvas_transform(transform);
viewport->update();
+ viewport_base->update();
}
void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
@@ -2684,88 +3057,117 @@ void CanvasItemEditor::_set_full_rect() {
undo_redo->commit_action();
}
+void CanvasItemEditor::_zoom_minus() {
+ if (zoom < MIN_ZOOM)
+ return;
+ zoom /= 2.0;
+
+ _update_scroll(0);
+ viewport->update();
+ viewport_base->update();
+}
+
+void CanvasItemEditor::_zoom_reset() {
+ zoom = 1;
+ _update_scroll(0);
+ viewport->update();
+ viewport_base->update();
+}
+
+void CanvasItemEditor::_zoom_plus() {
+ if (zoom > MAX_ZOOM)
+ return;
+
+ zoom *= 2.0;
+ _update_scroll(0);
+ viewport->update();
+ viewport_base->update();
+}
+
+void CanvasItemEditor::_toggle_snap(bool p_status) {
+ snap_active = p_status;
+ viewport->update();
+ viewport_base->update();
+}
+
void CanvasItemEditor::_popup_callback(int p_op) {
last_option = MenuOption(p_op);
switch (p_op) {
- case SNAP_USE: {
- snap_grid = !snap_grid;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked(idx, snap_grid);
+ case SHOW_GRID: {
+ show_grid = !show_grid;
+ 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_SHOW_GRID: {
- snap_show_grid = !snap_show_grid;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
- edit_menu->get_popup()->set_item_checked(idx, snap_show_grid);
- viewport->update();
+ case SNAP_USE_NODE_PARENT: {
+ snap_node_parent = !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);
+ } break;
+ case SNAP_USE_NODE_ANCHORS: {
+ snap_node_anchors = !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);
+ } break;
+ case SNAP_USE_NODE_SIDES: {
+ snap_node_sides = !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);
+ } break;
+ case SNAP_USE_OTHER_NODES: {
+ snap_other_nodes = !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);
+ } break;
+ case SNAP_USE_GRID: {
+ snap_grid = !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);
} break;
case SNAP_USE_ROTATION: {
snap_rotation = !snap_rotation;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
- edit_menu->get_popup()->set_item_checked(idx, 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);
} break;
case SNAP_RELATIVE: {
snap_relative = !snap_relative;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
- edit_menu->get_popup()->set_item_checked(idx, 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);
viewport->update();
+ viewport_base->update();
} break;
case SNAP_USE_PIXEL: {
snap_pixel = !snap_pixel;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx, 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);
} break;
case SNAP_CONFIGURE: {
- ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
snap_dialog->popup_centered(Size2(220, 160));
} break;
case SKELETON_SHOW_BONES: {
skeleton_show_bones = !skeleton_show_bones;
- int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->set_item_checked(idx, 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();
} break;
- case ZOOM_IN: {
- if (zoom > MAX_ZOOM)
- return;
- zoom = zoom * (1.0 / 0.5);
- _update_scroll(0);
+ case SHOW_HELPERS: {
+ show_helpers = !show_helpers;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
+ view_menu->get_popup()->set_item_checked(idx, show_helpers);
viewport->update();
- return;
} break;
- case ZOOM_OUT: {
- if (zoom < MIN_ZOOM)
- return;
-
- zoom = zoom * 0.5;
- _update_scroll(0);
+ case SHOW_RULERS: {
+ show_rulers = !show_rulers;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
+ view_menu->get_popup()->set_item_checked(idx, show_rulers);
viewport->update();
- return;
-
+ viewport_base->update();
} break;
- case ZOOM_RESET: {
- zoom = 1;
- _update_scroll(0);
- viewport->update();
- return;
-
- } break;
- case ZOOM_SET: {
-
- updating_value_dialog = true;
-
- dialog_label->set_text(TTR("Zoom (%):"));
- dialog_val->set_min(0.1);
- dialog_val->set_step(0.1);
- dialog_val->set_max(800);
- dialog_val->set_value(zoom * 100);
- value_dialog->popup_centered(Size2(200, 85));
- updating_value_dialog = false;
-
- } break;
case LOCK_SELECTED: {
List<Node *> &selection = editor_selection->get_selected_node_list();
@@ -3112,7 +3514,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_bone_", true);
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3131,7 +3533,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_bone_", Variant());
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3151,7 +3553,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
canvas_item->set_meta("_edit_ik_", true);
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3171,7 +3573,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_ik_", Variant());
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3234,15 +3636,19 @@ 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("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
- ClassDB::bind_method("_dialog_value_changed", &CanvasItemEditor::_dialog_value_changed);
ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
ClassDB::bind_method("_tool_select", &CanvasItemEditor::_tool_select);
ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed);
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
- ClassDB::bind_method("_viewport_draw", &CanvasItemEditor::_viewport_draw);
- ClassDB::bind_method("_viewport_gui_input", &CanvasItemEditor::_viewport_gui_input);
+ ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
+ ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base);
+ ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_gui_input);
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);
@@ -3284,64 +3690,92 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->set_area_as_parent_rect();
bottom_split = memnew(VSplitContainer);
- bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
add_child(bottom_split);
+ bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
palette_split = memnew(HSplitContainer);
- palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
bottom_split->add_child(palette_split);
+ palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
- Control *vp_base = memnew(Control);
- vp_base->set_v_size_flags(SIZE_EXPAND_FILL);
- palette_split->add_child(vp_base);
+ viewport_base = memnew(Control);
+ palette_split->add_child(viewport_base);
+ viewport_base->connect("draw", this, "_draw_viewport_base");
+ viewport_base->connect("gui_input", this, "_viewport_base_gui_input");
+ 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);
- ViewportContainer *vp = memnew(ViewportContainer);
- vp->set_stretch(true);
- vp_base->add_child(vp);
- vp->set_area_as_parent_rect();
- vp->add_child(p_editor->get_scene_root());
+ viewport_scrollable = memnew(Control);
+ viewport_base->add_child(viewport_scrollable);
+ viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS);
+ viewport_scrollable->set_draw_behind_parent(true);
+ viewport_scrollable->set_area_as_parent_rect();
+ viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH));
+
+ ViewportContainer *scene_tree = memnew(ViewportContainer);
+ viewport_scrollable->add_child(scene_tree);
+ scene_tree->set_stretch(true);
+ scene_tree->set_area_as_parent_rect();
+ scene_tree->add_child(p_editor->get_scene_root());
viewport = memnew(CanvasItemEditorViewport(p_editor, this));
- vp_base->add_child(viewport);
+ viewport_scrollable->add_child(viewport);
+ viewport->set_mouse_filter(MOUSE_FILTER_PASS);
viewport->set_area_as_parent_rect();
viewport->set_clip_contents(true);
+ viewport->connect("draw", this, "_draw_viewport");
h_scroll = memnew(HScrollBar);
- v_scroll = memnew(VScrollBar);
-
viewport->add_child(h_scroll);
- viewport->add_child(v_scroll);
- viewport->connect("draw", this, "_viewport_draw");
- viewport->connect("gui_input", this, "_viewport_gui_input");
-
h_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED);
- v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED);
-
h_scroll->hide();
+
+ v_scroll = memnew(VScrollBar);
+ viewport->add_child(v_scroll);
+ v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED);
v_scroll->hide();
+
+ 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->set_focus_mode(FOCUS_NONE);
+
+ zoom_reset = memnew(ToolButton);
+ zoom_hb->add_child(zoom_reset);
+ zoom_reset->connect("pressed", this, "_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->set_focus_mode(FOCUS_NONE);
+
updating_scroll = false;
- viewport->set_focus_mode(FOCUS_ALL);
handle_len = 10;
first_update = true;
select_button = memnew(ToolButton);
- select_button->set_toggle_mode(true);
hb->add_child(select_button);
+ select_button->set_toggle_mode(true);
select_button->connect("pressed", this, "_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(TTR("Select Mode") + " $sc\n" + 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"));
move_button = memnew(ToolButton);
- move_button->set_toggle_mode(true);
hb->add_child(move_button);
+ move_button->set_toggle_mode(true);
move_button->connect("pressed", this, "_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);
- rotate_button->set_toggle_mode(true);
hb->add_child(rotate_button);
+ rotate_button->set_toggle_mode(true);
rotate_button->connect("pressed", this, "_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"));
@@ -3349,25 +3783,60 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
list_select_button = memnew(ToolButton);
- list_select_button->set_toggle_mode(true);
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->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);
- pivot_button->set_toggle_mode(true);
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->set_tooltip(TTR("Click to change object's rotation pivot."));
pan_button = memnew(ToolButton);
- pan_button->set_toggle_mode(true);
hb->add_child(pan_button);
+ pan_button->set_toggle_mode(true);
pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN));
pan_button->set_tooltip(TTR("Pan Mode"));
hb->add_child(memnew(VSeparator));
+ snap_button = memnew(ToolButton);
+ hb->add_child(snap_button);
+ snap_button->set_toggle_mode(true);
+ snap_button->connect("toggled", this, "_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));
+
+ snap_config_menu = memnew(MenuButton);
+ hb->add_child(snap_config_menu);
+ snap_config_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
+ snap_config_menu->set_h_size_flags(SIZE_SHRINK_END);
+ snap_config_menu->set_tooltip(TTR("Snapping options"));
+
+ PopupMenu *p = snap_config_menu->get_popup();
+ p->connect("id_pressed", this, "_popup_callback");
+ p->set_hide_on_checkable_item_selection(false);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_grid", TTR("Snap to grid")), SNAP_USE_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
+ p->add_submenu_item(TTR("Smart snapping"), "SmartSnapping");
+
+ smartsnap_config_popup = memnew(PopupMenu);
+ p->add_child(smartsnap_config_popup);
+ smartsnap_config_popup->set_name("SmartSnapping");
+ smartsnap_config_popup->connect("id_pressed", this, "_popup_callback");
+ smartsnap_config_popup->set_hide_on_checkable_item_selection(false);
+ 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_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES);
+
+ hb->add_child(memnew(VSeparator));
+
lock_button = memnew(ToolButton);
hb->add_child(lock_button);
@@ -3391,35 +3860,23 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
- edit_menu = memnew(MenuButton);
- edit_menu->set_text(TTR("Edit"));
- hb->add_child(edit_menu);
- edit_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
+ skeleton_menu = memnew(MenuButton);
+ hb->add_child(skeleton_menu);
- PopupMenu *p;
- p = edit_menu->get_popup();
+ p = skeleton_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap")), SNAP_USE);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid")), SNAP_SHOW_GRID);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap..")), SNAP_CONFIGURE);
+ p->connect("id_pressed", this, "_popup_callback");
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
p->add_separator();
- p->add_submenu_item(TTR("Skeleton.."), "skeleton");
- skeleton_menu = memnew(PopupMenu);
- p->add_child(skeleton_menu);
- skeleton_menu->set_name("skeleton");
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
- skeleton_menu->add_separator();
- skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
- skeleton_menu->add_separator();
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
- skeleton_menu->set_hide_on_checkable_item_selection(false);
- skeleton_menu->connect("id_pressed", this, "_popup_callback");
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+ p->set_hide_on_checkable_item_selection(false);
+ p->connect("id_pressed", this, "_popup_callback");
+
+ hb->add_child(memnew(VSeparator));
view_menu = memnew(MenuButton);
view_menu->set_text(TTR("View"));
@@ -3427,11 +3884,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
view_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
p = view_menu->get_popup();
-
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_in", TTR("Zoom In")), ZOOM_IN);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_out", TTR("Zoom Out")), ZOOM_OUT);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset")), ZOOM_RESET);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_set", TTR("Zoom Set..")), ZOOM_SET);
+ 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_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);
@@ -3502,23 +3957,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_dialog->connect("confirmed", this, "_snap_changed");
add_child(snap_dialog);
- value_dialog = memnew(AcceptDialog);
- value_dialog->set_title(TTR("Set a Value"));
- value_dialog->get_ok()->set_text(TTR("Close"));
- add_child(value_dialog);
-
- Label *l = memnew(Label);
- l->set_text(TTR("Snap (Pixels):"));
- l->set_position(Point2(5, 5));
- value_dialog->add_child(l);
- dialog_label = l;
-
- dialog_val = memnew(SpinBox);
- dialog_val->set_anchor(MARGIN_RIGHT, ANCHOR_END);
- dialog_val->set_begin(Point2(15, 25));
- dialog_val->set_end(Point2(-10, 25));
- value_dialog->add_child(dialog_val);
- dialog_val->connect("value_changed", this, "_dialog_value_changed");
select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture));
selection_menu = memnew(PopupMenu);
@@ -3527,22 +3965,35 @@ 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);
+
key_pos = true;
key_rot = true;
key_scale = false;
+ show_grid = false;
+ show_helpers = false;
+ show_rulers = false;
zoom = 1;
- snap_offset = Vector2(0, 0);
- snap_step = Vector2(10, 10);
+ grid_offset = Point2();
+ grid_step = Point2(10, 10);
+ grid_step_multiplier = 0;
snap_rotation_offset = 0;
snap_rotation_step = 15 / (180 / Math_PI);
- snap_grid = false;
- snap_show_grid = false;
+ snap_active = false;
+ snap_node_parent = true;
+ snap_node_anchors = true;
+ snap_node_sides = true;
+ snap_other_nodes = true;
+ snap_grid = true;
snap_rotation = false;
snap_pixel = false;
skeleton_show_bones = true;
- skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES), true);
- updating_value_dialog = false;
+ 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;
@@ -3573,7 +4024,7 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) {
canvas_item_editor->show();
canvas_item_editor->set_fixed_process(true);
VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
- canvas_item_editor->viewport->grab_focus();
+ canvas_item_editor->viewport_base->grab_focus();
} else {
@@ -3742,7 +4193,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
target_pos -= texture_size / 2;
}
// there's nothing to be used as source position so snapping will work as absolute if enabled
- target_pos = canvas->snap_point(target_pos, Vector2());
+ target_pos = canvas->snap_point(target_pos);
editor_data->get_undo_redo().add_do_method(child, "set_position", target_pos);
}
@@ -3776,22 +4227,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
- Point2 pos;
- Node2D *parent_node2d = Object::cast_to<Node2D>(parent);
- if (parent_node2d) {
- pos = parent_node2d->get_global_position();
- } else {
- Control *parent_control = Object::cast_to<Control>(parent);
- if (parent_control) {
- pos = parent_control->get_global_position();
- }
+ CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent);
+ if (parent_ci) {
+ Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point);
+ target_pos = canvas->snap_point(target_pos);
+ target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos);
+ editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
}
- Transform2D trans = canvas->get_canvas_transform();
- Vector2 target_pos = (p_point - trans.get_origin()) / trans.get_scale().x - pos;
- // in relative snapping it may be useful for the user to take the original node position into account
- Vector2 start_pos = Object::cast_to<Node2D>(instanced_scene) ? Object::cast_to<Node2D>(instanced_scene)->get_position() : target_pos;
- target_pos = canvas->snap_point(target_pos, start_pos);
- editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
return true;
}
@@ -3870,6 +4312,20 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
continue;
}
memdelete(instanced_scene);
+ } else if (type == "Texture" ||
+ type == "ImageTexture" ||
+ type == "ViewportTexture" ||
+ type == "CurveTexture" ||
+ type == "GradientTexture" ||
+ type == "StreamTexture" ||
+ type == "AtlasTexture" ||
+ type == "LargeTexture") {
+ Ref<Texture> texture = ResourceLoader::load(files[i]);
+ if (texture.is_valid() == false) {
+ continue;
+ }
+ } else {
+ continue;
}
can_instance = true;
break;
@@ -3978,41 +4434,39 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
editor_data = editor->get_scene_tree_dock()->get_editor_data();
canvas = p_canvas;
preview_node = memnew(Node2D);
+
accept = memnew(AcceptDialog);
editor->get_gui_base()->add_child(accept);
selector = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(selector);
selector->set_title(TTR("Change default type"));
+ selector->connect("confirmed", this, "_on_change_type");
VBoxContainer *vbc = memnew(VBoxContainer);
+ selector->add_child(vbc);
vbc->set_h_size_flags(SIZE_EXPAND_FILL);
vbc->set_v_size_flags(SIZE_EXPAND_FILL);
vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE);
selector_label = memnew(Label);
+ vbc->add_child(selector_label);
selector_label->set_align(Label::ALIGN_CENTER);
selector_label->set_valign(Label::VALIGN_BOTTOM);
selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE);
- vbc->add_child(selector_label);
-
- button_group.instance();
btn_group = memnew(VBoxContainer);
+ vbc->add_child(btn_group);
btn_group->set_h_size_flags(0);
+ button_group.instance();
for (int i = 0; i < types.size(); i++) {
CheckBox *check = memnew(CheckBox);
+ btn_group->add_child(check);
check->set_text(types[i]);
check->connect("button_down", this, "_on_select_type", varray(check));
- btn_group->add_child(check);
check->set_button_group(button_group);
}
- vbc->add_child(btn_group);
-
- selector->connect("confirmed", this, "_on_change_type");
-
- selector->add_child(vbc);
- editor->get_gui_base()->add_child(selector);
label = memnew(Label);
label->add_color_override("font_color_shadow", Color(0, 0, 0, 1));
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index f61bfc9eb..af834507e 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -70,7 +70,6 @@ class CanvasItemEditor : public VBoxContainer {
EditorNode *editor;
enum Tool {
-
TOOL_SELECT,
TOOL_LIST_SELECT,
TOOL_MOVE,
@@ -82,15 +81,18 @@ class CanvasItemEditor : public VBoxContainer {
enum MenuOption {
SNAP_USE,
- SNAP_SHOW_GRID,
+ SNAP_USE_NODE_PARENT,
+ SNAP_USE_NODE_ANCHORS,
+ SNAP_USE_NODE_SIDES,
+ SNAP_USE_OTHER_NODES,
+ SNAP_USE_GRID,
SNAP_USE_ROTATION,
SNAP_RELATIVE,
SNAP_CONFIGURE,
SNAP_USE_PIXEL,
- ZOOM_IN,
- ZOOM_OUT,
- ZOOM_RESET,
- ZOOM_SET,
+ SHOW_GRID,
+ SHOW_HELPERS,
+ SHOW_RULERS,
LOCK_SELECTED,
UNLOCK_SELECTED,
GROUP_SELECTED,
@@ -163,6 +165,8 @@ class CanvasItemEditor : public VBoxContainer {
Tool tool;
bool first_update;
Control *viewport;
+ Control *viewport_base;
+ Control *viewport_scrollable;
bool can_move_pivot;
@@ -170,14 +174,28 @@ class CanvasItemEditor : public VBoxContainer {
VScrollBar *v_scroll;
HBoxContainer *hb;
+ ToolButton *zoom_minus;
+ ToolButton *zoom_reset;
+ ToolButton *zoom_plus;
+
Transform2D transform;
+ bool show_grid;
+ bool show_rulers;
+ bool show_helpers;
float zoom;
- Vector2 snap_offset;
- Vector2 snap_step;
+
+ Point2 grid_offset;
+ Point2 grid_step;
+ int grid_step_multiplier;
+
float snap_rotation_step;
float snap_rotation_offset;
+ bool snap_active;
+ bool snap_node_parent;
+ bool snap_node_anchors;
+ bool snap_node_sides;
+ bool snap_other_nodes;
bool snap_grid;
- bool snap_show_grid;
bool snap_rotation;
bool snap_relative;
bool snap_pixel;
@@ -204,18 +222,6 @@ class CanvasItemEditor : public VBoxContainer {
Vector<_SelectResult> selection_results;
- struct LockList {
- Point2 pos;
- bool lock;
- bool group;
- LockList() {
- lock = false;
- group = false;
- }
- };
-
- List<LockList> lock_list;
-
struct BoneList {
Transform2D xform;
@@ -255,6 +261,10 @@ class CanvasItemEditor : public VBoxContainer {
ToolButton *move_button;
ToolButton *rotate_button;
+ ToolButton *snap_button;
+ MenuButton *snap_config_menu;
+ PopupMenu *smartsnap_config_popup;
+
ToolButton *pivot_button;
ToolButton *pan_button;
@@ -264,8 +274,7 @@ class CanvasItemEditor : public VBoxContainer {
ToolButton *group_button;
ToolButton *ungroup_button;
- MenuButton *edit_menu;
- PopupMenu *skeleton_menu;
+ MenuButton *skeleton_menu;
MenuButton *view_menu;
HBoxContainer *animation_hb;
MenuButton *animation_menu;
@@ -278,6 +287,9 @@ class CanvasItemEditor : public VBoxContainer {
PopupMenu *selection_menu;
+ Control *top_ruler;
+ Control *left_ruler;
+
//PopupMenu *popup;
DragType drag;
Point2 drag_from;
@@ -290,6 +302,11 @@ class CanvasItemEditor : public VBoxContainer {
Ref<Texture> select_handle;
Ref<Texture> anchor_handle;
+ Ref<ShortCut> drag_pivot_shortcut;
+ Ref<ShortCut> set_pivot_shortcut;
+ 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);
@@ -300,10 +317,6 @@ class CanvasItemEditor : public VBoxContainer {
ConfirmationDialog *snap_dialog;
- AcceptDialog *value_dialog;
- Label *dialog_label;
- SpinBox *dialog_val;
-
CanvasItem *ref_item;
void _edit_set_pivot(const Vector2 &mouse_pos);
@@ -317,9 +330,8 @@ class CanvasItemEditor : public VBoxContainer {
void _prepare_drag(const Point2 &p_click_pos);
DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
- float _anchor_snap(float p_anchor, bool *p_snapped = NULL, float p_opposite_anchor = -1);
- Vector2 _anchor_to_position(Control *p_control, Vector2 anchor);
- Vector2 _position_to_anchor(Control *p_control, Vector2 position);
+ Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor);
+ Vector2 _position_to_anchor(const Control *p_control, Vector2 position);
void _popup_callback(int p_op);
bool updating_scroll;
@@ -330,7 +342,6 @@ class CanvasItemEditor : public VBoxContainer {
void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric);
void _append_canvas_item(CanvasItem *p_item);
- void _dialog_value_changed(double);
void _snap_changed();
void _selection_result_pressed(int);
void _selection_menu_hide();
@@ -339,26 +350,49 @@ class CanvasItemEditor : public VBoxContainer {
Point2 _find_topleftmost_point();
- void _find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform);
+ void _build_bones_list(Node *p_node);
+
+ void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform);
Object *_get_editor_data(Object *p_what);
- CanvasItem *get_single_item();
+ CanvasItem *_get_single_item();
int get_item_count();
void _keying_changed();
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
+ 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 _viewport_gui_input(const Ref<InputEvent> &p_event);
- void _viewport_draw();
+ void _draw_rulers();
+ void _draw_focus();
+ void _draw_grid();
+ void _draw_selection();
+ void _draw_axis();
+ void _draw_bones();
+ void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform);
+
+ void _draw_viewport();
+
+ void _viewport_base_gui_input(const Ref<InputEvent> &p_event);
+ void _draw_viewport_base();
void _focus_selection(int p_op);
+ void _snap_if_closer(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);
+
void _set_anchors_preset(Control::LayoutPreset p_preset);
void _set_full_rect();
+ void _zoom_minus();
+ void _zoom_reset();
+ void _zoom_plus();
+
+ void _toggle_snap(bool p_status);
+
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
@@ -402,7 +436,18 @@ protected:
static CanvasItemEditor *singleton;
public:
- Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
+ enum SnapMode {
+ SNAP_GRID = 1 << 0,
+ SNAP_PIXEL = 1 << 1,
+ SNAP_NODE_PARENT = 1 << 2,
+ SNAP_NODE_ANCHORS = 1 << 3,
+ SNAP_NODE_SIDES = 1 << 4,
+ SNAP_OTHER_NODES = 1 << 5,
+
+ SNAP_DEFAULT = 0x03,
+ };
+
+ Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0);
float snap_angle(float p_target, float p_start = 0) const;
Transform2D get_canvas_transform() const { return transform; }
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 3917c700f..8c4e1b8f2 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -52,7 +52,7 @@ void Polygon2DEditor::_notification(int p_what) {
uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons"));
b_snap_grid->set_icon(get_icon("Grid", "EditorIcons"));
- b_snap_enable->set_icon(get_icon("Snap", "EditorIcons"));
+ b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons"));
uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons"));
get_tree()->connect("node_removed", this, "_node_removed");
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 2c42150ce..c1b0fdb5d 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2566,11 +2566,18 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
String path = files[i];
RES res = ResourceLoader::load(path);
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (scene != NULL) {
- if (scene.is_valid()) {
- Node *instance = scene->instance();
- if (instance) {
- preview_node->add_child(instance);
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+ if (mesh != NULL || scene != NULL) {
+ if (mesh != NULL) {
+ MeshInstance *mesh_instance = memnew(MeshInstance);
+ mesh_instance->set_mesh(mesh);
+ preview_node->add_child(mesh_instance);
+ } else {
+ if (scene.is_valid()) {
+ Node *instance = scene->instance();
+ if (instance) {
+ preview_node->add_child(instance);
+ }
}
}
editor->get_scene_root()->add_child(preview_node);
@@ -2606,13 +2613,29 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s
}
bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
- Ref<PackedScene> sdata = ResourceLoader::load(path);
- if (!sdata.is_valid()) { // invalid scene
- return false;
+ RES res = ResourceLoader::load(path);
+
+ Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+
+ Node *instanced_scene = NULL;
+
+ if (mesh != NULL || scene != NULL) {
+ if (mesh != NULL) {
+ MeshInstance *mesh_instance = memnew(MeshInstance);
+ mesh_instance->set_mesh(mesh);
+ mesh_instance->set_name(mesh->get_name());
+ instanced_scene = mesh_instance;
+ } else {
+ if (!scene.is_valid()) { // invalid scene
+ return false;
+ } else {
+ instanced_scene = scene->instance();
+ }
+ }
}
- Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) { // error on instancing
+ if (instanced_scene == NULL) {
return false;
}
@@ -2661,7 +2684,8 @@ void SpatialEditorViewport::_perform_drop_data() {
continue;
}
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (scene != NULL) {
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+ if (mesh != NULL || scene != NULL) {
bool success = _create_instance(target_node, path, drop_pos);
if (!success) {
error_files.push_back(path);
@@ -2694,9 +2718,11 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian
List<String> scene_extensions;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
+ List<String> mesh_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions);
for (int i = 0; i < files.size(); i++) {
- if (scene_extensions.find(files[i].get_extension())) {
+ if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) {
RES res = ResourceLoader::load(files[i]);
if (res.is_null()) {
continue;
@@ -2710,6 +2736,13 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian
continue;
}
memdelete(instanced_scene);
+ } else if (type == "Mesh" || "ArrayMesh" || "PrimitiveMesh") {
+ Ref<Mesh> mesh = ResourceLoader::load(files[i]);
+ if (!mesh.is_valid()) {
+ continue;
+ }
+ } else {
+ continue;
}
can_instance = true;
break;
@@ -2854,8 +2887,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D);
ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W);
ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S);
- ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q);
- ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E);
+ ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_E);
+ ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q);
ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT);
preview_camera = memnew(Button);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 5b783493c..2fcba7e3c 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2016,6 +2016,5 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
clear_inherit_confirm->get_ok()->set_text(TTR("Clear!"));
add_child(clear_inherit_confirm);
- vbc->add_constant_override("separation", 4);
set_process_input(true);
}
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 284b25801..76e75cff0 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -1622,7 +1622,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles"));
tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles"));
tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles"));
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
tabs->set_area_as_parent_rect();
add_child(tabs);