summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_track_editor.cpp2
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_data.cpp8
-rw-r--r--editor/editor_file_dialog.cpp15
-rw-r--r--editor/editor_inspector.cpp10
-rw-r--r--editor/editor_spin_slider.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp151
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp66
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp6
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp8
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h1
-rw-r--r--editor/scene_tree_dock.cpp36
-rw-r--r--editor/scene_tree_editor.cpp2
14 files changed, 200 insertions, 111 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 39e863ae0f..52c984cbc0 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -5758,7 +5758,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
box_selection = memnew(Control);
add_child(box_selection);
- box_selection->set_as_toplevel(true);
+ box_selection->set_as_top_level(true);
box_selection->set_mouse_filter(MOUSE_FILTER_IGNORE);
box_selection->hide();
box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw));
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index adb09532eb..a3deb95130 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -846,7 +846,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
audioprev_hbc->add_child(audio_value_preview_label);
slider->add_child(audio_value_preview_box);
- audio_value_preview_box->set_as_toplevel(true);
+ audio_value_preview_box->set_as_top_level(true);
Ref<StyleBoxFlat> panel_style = memnew(StyleBoxFlat);
panel_style->set_bg_color(Color(0.0f, 0.0f, 0.0f, 0.8f));
audio_value_preview_box->add_theme_style_override("panel", panel_style);
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 5118ccacad..1002c4917b 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -936,7 +936,13 @@ void EditorData::script_class_save_icon_paths() {
}
}
- ProjectSettings::get_singleton()->set("_global_script_class_icons", d);
+ if (d.empty()) {
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
+ ProjectSettings::get_singleton()->clear("_global_script_class_icons");
+ }
+ } else {
+ ProjectSettings::get_singleton()->set("_global_script_class_icons", d);
+ }
ProjectSettings::get_singleton()->save();
}
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index ba9f27f65f..2140b6bd13 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -60,7 +60,7 @@ VBoxContainer *EditorFileDialog::get_vbox() {
void EditorFileDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) {
- // update icons
+ // Update icons.
mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
@@ -94,7 +94,7 @@ void EditorFileDialog::_notification(int p_what) {
}
set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int());
- // update icons
+ // Update icons.
mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
@@ -138,9 +138,7 @@ void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
handled = true;
}
if (ED_IS_SHORTCUT("file_dialog/toggle_hidden_files", p_event)) {
- bool show = !show_hidden_files;
- set_show_hidden_files(show);
- EditorSettings::get_singleton()->set("filesystem/file_dialog/show_hidden_files", show);
+ set_show_hidden_files(!show_hidden_files);
handled = true;
}
if (ED_IS_SHORTCUT("file_dialog/toggle_favorite", p_event)) {
@@ -1385,6 +1383,11 @@ void EditorFileDialog::_bind_methods() {
}
void EditorFileDialog::set_show_hidden_files(bool p_show) {
+ if (p_show == show_hidden_files) {
+ return;
+ }
+
+ EditorSettings::get_singleton()->set("filesystem/file_dialog/show_hidden_files", p_show);
show_hidden_files = p_show;
show_hidden->set_pressed(p_show);
invalidate();
@@ -1646,7 +1649,7 @@ EditorFileDialog::EditorFileDialog() {
filter->connect("item_selected", callable_mp(this, &EditorFileDialog::_filter_selected));
confirm_save = memnew(ConfirmationDialog);
- //confirm_save->set_as_toplevel(true);
+ //confirm_save->set_as_top_level(true);
add_child(confirm_save);
confirm_save->connect("confirmed", callable_mp(this, &EditorFileDialog::_save_confirm_pressed));
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 2e716a636e..9900e8184d 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -48,7 +48,7 @@ Size2 EditorProperty::get_minimum_size() const {
if (!c) {
continue;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
continue;
}
if (!c->is_visible()) {
@@ -117,7 +117,7 @@ void EditorProperty::_notification(int p_what) {
if (!c) {
continue;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
continue;
}
if (c == bottom_editor) {
@@ -179,7 +179,7 @@ void EditorProperty::_notification(int p_what) {
if (!c) {
continue;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
continue;
}
if (c == bottom_editor) {
@@ -1133,7 +1133,7 @@ void EditorInspectorSection::_notification(int p_what) {
if (!c) {
continue;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
continue;
}
if (!c->is_visible_in_tree()) {
@@ -1225,7 +1225,7 @@ Size2 EditorInspectorSection::get_minimum_size() const {
if (!c) {
continue;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
continue;
}
if (!c->is_visible()) {
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index ac61a75a6c..efc966c6c4 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -483,7 +483,7 @@ EditorSpinSlider::EditorSpinSlider() {
grabber = memnew(TextureRect);
add_child(grabber);
grabber->hide();
- grabber->set_as_toplevel(true);
+ grabber->set_as_top_level(true);
grabber->set_mouse_filter(MOUSE_FILTER_STOP);
grabber->connect("mouse_entered", callable_mp(this, &EditorSpinSlider::_grabber_mouse_entered));
grabber->connect("mouse_exited", callable_mp(this, &EditorSpinSlider::_grabber_mouse_exited));
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 8caa4aeeaf..266df78949 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -184,8 +184,11 @@ String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String
String EditorSceneImporterGLTF::_sanitize_bone_name(const String &name) {
String p_name = name.camelcase_to_underscore(true);
- RegEx pattern_del("([^a-zA-Z0-9_ ])+");
- p_name = pattern_del.sub(p_name, "", true);
+ RegEx pattern_nocolon(":");
+ p_name = pattern_nocolon.sub(p_name, "_", true);
+
+ RegEx pattern_noslash("/");
+ p_name = pattern_noslash.sub(p_name, "_", true);
RegEx pattern_nospace(" +");
p_name = pattern_nospace.sub(p_name, "_", true);
@@ -200,8 +203,10 @@ String EditorSceneImporterGLTF::_sanitize_bone_name(const String &name) {
}
String EditorSceneImporterGLTF::_gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name) {
- const String s_name = _sanitize_bone_name(p_name);
-
+ String s_name = _sanitize_bone_name(p_name);
+ if (s_name.empty()) {
+ s_name = "bone";
+ }
String name;
int index = 1;
while (true) {
@@ -379,13 +384,17 @@ Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_
Vector<uint8_t> buffer_data;
String uri = buffer["uri"];
- if (uri.findn("data:application/octet-stream;base64") == 0) {
- //embedded data
+ if (uri.begins_with("data:")) { // Embedded data using base64.
+ // Validate data MIME types and throw an error if it's one we don't know/support.
+ if (!uri.begins_with("data:application/octet-stream;base64") &&
+ !uri.begins_with("data:application/gltf-buffer;base64")) {
+ ERR_PRINT("glTF: Got buffer with an unknown URI data type: " + uri);
+ }
buffer_data = _parse_base64_uri(uri);
- } else {
- uri = p_base_path.plus_file(uri).replace("\\", "/"); //fix for windows
+ } else { // Relative path to an external image file.
+ uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
buffer_data = FileAccess::get_file_as_array(uri);
- ERR_FAIL_COND_V(buffer.size() == 0, ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri);
}
ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR);
@@ -1261,12 +1270,28 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
return OK;
}
+ // Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images
+
const Array &images = state.json["images"];
for (int i = 0; i < images.size(); i++) {
const Dictionary &d = images[i];
+ // glTF 2.0 supports PNG and JPEG types, which can be specified as (from spec):
+ // "- a URI to an external file in one of the supported images formats, or
+ // - a URI with embedded base64-encoded data, or
+ // - a reference to a bufferView; in that case mimeType must be defined."
+ // Since mimeType is optional for external files and base64 data, we'll have to
+ // fall back on letting Godot parse the data to figure out if it's PNG or JPEG.
+
+ // We'll assume that we use either URI or bufferView, so let's warn the user
+ // if their image somehow uses both. And fail if it has neither.
+ ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specific an 'uri' or 'bufferView'.");
+ if (d.has("uri") && d.has("bufferView")) {
+ WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'bufferView' will take precedence.");
+ }
+
String mimetype;
- if (d.has("mimeType")) {
+ if (d.has("mimeType")) { // Should be "image/png" or "image/jpeg".
mimetype = d["mimeType"];
}
@@ -1275,23 +1300,52 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
int data_size = 0;
if (d.has("uri")) {
+ // Handles the first two bullet points from the spec (embedded data, or external file).
String uri = d["uri"];
- if (uri.findn("data:application/octet-stream;base64") == 0 ||
- uri.findn("data:" + mimetype + ";base64") == 0) {
- //embedded data
+ if (uri.begins_with("data:")) { // Embedded data using base64.
+ // Validate data MIME types and throw an error if it's one we don't know/support.
+ if (!uri.begins_with("data:application/octet-stream;base64") &&
+ !uri.begins_with("data:application/gltf-buffer;base64") &&
+ !uri.begins_with("data:image/png;base64") &&
+ !uri.begins_with("data:image/jpeg;base64")) {
+ ERR_PRINT("glTF: Got image data with an unknown URI data type: " + uri);
+ }
data = _parse_base64_uri(uri);
data_ptr = data.ptr();
data_size = data.size();
- } else {
- uri = p_base_path.plus_file(uri).replace("\\", "/"); //fix for windows
- Ref<Texture2D> texture = ResourceLoader::load(uri);
- state.images.push_back(texture);
- continue;
+ // mimeType is optional, but if we have it defined in the URI, let's use it.
+ if (mimetype.empty()) {
+ if (uri.begins_with("data:image/png;base64")) {
+ mimetype = "image/png";
+ } else if (uri.begins_with("data:image/jpeg;base64")) {
+ mimetype = "image/jpeg";
+ }
+ }
+ } else { // Relative path to an external image file.
+ uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
+ // The spec says that if mimeType is defined, we should enforce it.
+ // So we should only rely on ResourceLoader::load if mimeType is not defined,
+ // otherwise we should use the same logic as for buffers.
+ if (mimetype == "image/png" || mimetype == "image/jpeg") {
+ // Load data buffer and rely on PNG and JPEG-specific logic below to load the image.
+ // This makes it possible to load a file with a wrong extension but correct MIME type,
+ // e.g. "foo.jpg" containing PNG data and with MIME type "image/png". ResourceLoader would fail.
+ data = FileAccess::get_file_as_array(uri);
+ ERR_FAIL_COND_V_MSG(data.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load image file as an array: " + uri);
+ data_ptr = data.ptr();
+ data_size = data.size();
+ } else {
+ // Good old ResourceLoader will rely on file extension.
+ Ref<Texture2D> texture = ResourceLoader::load(uri);
+ state.images.push_back(texture);
+ continue;
+ }
}
- }
+ } else if (d.has("bufferView")) {
+ // Handles the third bullet point from the spec (bufferView).
+ ERR_FAIL_COND_V_MSG(mimetype.empty(), ERR_FILE_CORRUPT, "glTF: Image specifies 'bufferView' but no 'mimeType', which is invalid.");
- if (d.has("bufferView")) {
const GLTFBufferViewIndex bvi = d["bufferView"];
ERR_FAIL_INDEX_V(bvi, state.buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
@@ -1307,45 +1361,36 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
data_size = bv.byte_length;
}
- ERR_FAIL_COND_V(mimetype == "", ERR_FILE_CORRUPT);
+ Ref<Image> img;
- if (mimetype.findn("png") != -1) {
- //is a png
+ if (mimetype == "image/png") { // Load buffer as PNG.
ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE);
-
- const Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size);
-
- ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
-
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(img);
-
- state.images.push_back(t);
- continue;
- }
-
- if (mimetype.findn("jpeg") != -1) {
- //is a jpg
+ img = Image::_png_mem_loader_func(data_ptr, data_size);
+ } else if (mimetype == "image/jpeg") { // Loader buffer as JPEG.
ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE);
+ img = Image::_jpg_mem_loader_func(data_ptr, data_size);
+ } else {
+ // We can land here if we got an URI with base64-encoded data with application/* MIME type,
+ // and the optional mimeType property was not defined to tell us how to handle this data (or was invalid).
+ // So let's try PNG first, then JPEG.
+ ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE);
+ img = Image::_png_mem_loader_func(data_ptr, data_size);
+ if (img.is_null()) {
+ ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE);
+ img = Image::_jpg_mem_loader_func(data_ptr, data_size);
+ }
+ }
- const Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size);
-
- ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
-
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(img);
-
- state.images.push_back(t);
+ ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT, "glTF: Couldn't load image with its given mimetype: " + mimetype);
- continue;
- }
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(img);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
+ state.images.push_back(t);
}
- print_verbose("Total images: " + itos(state.images.size()));
+ print_verbose("glTF: Total images: " + itos(state.images.size()));
return OK;
}
@@ -1505,7 +1550,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
state.materials.push_back(material);
}
- print_verbose("Total materials: " + itos(state.materials.size()));
+ print_verbose("glTF: Total materials: " + itos(state.materials.size()));
return OK;
}
@@ -3056,6 +3101,8 @@ Node3D *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_b
}
Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+ print_verbose(vformat("glTF: Importing file %s as scene.", p_path));
+
GLTFState state;
if (p_path.to_lower().ends_with("glb")) {
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 402ec5d80d..c06580df26 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -548,7 +548,7 @@ void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, c
const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
- if (canvas_item && !canvas_item->is_set_as_toplevel()) {
+ if (canvas_item && !canvas_item->is_set_as_top_level()) {
_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
@@ -591,7 +591,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item) {
- if (!canvas_item->is_set_as_toplevel()) {
+ if (!canvas_item->is_set_as_top_level()) {
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
@@ -767,7 +767,7 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n
if (!lock_children || !editable) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item) {
- if (!canvas_item->is_set_as_toplevel()) {
+ if (!canvas_item->is_set_as_top_level()) {
_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
@@ -2599,12 +2599,28 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
}
void CanvasItemEditor::_update_cursor() {
- CursorShape c = CURSOR_ARROW;
- bool should_switch = false;
- if (drag_selection.size() != 0) {
- float angle = drag_selection[0]->_edit_get_rotation();
- should_switch = abs(Math::cos(angle)) < Math_SQRT12;
+ // Compute an eventual rotation of the cursor
+ CursorShape rotation_array[4] = { CURSOR_HSIZE, CURSOR_BDIAGSIZE, CURSOR_VSIZE, CURSOR_FDIAGSIZE };
+ int rotation_array_index = 0;
+
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+ if (selection.size() == 1) {
+ float angle = Math::fposmod((double)selection[0]->get_global_transform_with_canvas().get_rotation(), Math_PI);
+ if (angle > Math_PI * 7.0 / 8.0) {
+ rotation_array_index = 0;
+ } else if (angle > Math_PI * 5.0 / 8.0) {
+ rotation_array_index = 1;
+ } else if (angle > Math_PI * 3.0 / 8.0) {
+ rotation_array_index = 2;
+ } else if (angle > Math_PI * 1.0 / 8.0) {
+ rotation_array_index = 3;
+ } else {
+ rotation_array_index = 0;
+ }
}
+
+ // Choose the correct cursor
+ CursorShape c = CURSOR_ARROW;
switch (drag_type) {
case DRAG_NONE:
switch (tool) {
@@ -2626,38 +2642,28 @@ void CanvasItemEditor::_update_cursor() {
break;
case DRAG_LEFT:
case DRAG_RIGHT:
+ c = rotation_array[rotation_array_index];
+ break;
case DRAG_V_GUIDE:
- if (should_switch) {
- c = CURSOR_VSIZE;
- } else {
- c = CURSOR_HSIZE;
- }
+ c = CURSOR_HSIZE;
break;
case DRAG_TOP:
case DRAG_BOTTOM:
+ c = rotation_array[(rotation_array_index + 2) % 4];
+ break;
case DRAG_H_GUIDE:
- if (should_switch) {
- c = CURSOR_HSIZE;
- } else {
- c = CURSOR_VSIZE;
- }
+ c = CURSOR_VSIZE;
break;
case DRAG_TOP_LEFT:
case DRAG_BOTTOM_RIGHT:
+ c = rotation_array[(rotation_array_index + 3) % 4];
+ break;
case DRAG_DOUBLE_GUIDE:
- if (should_switch) {
- c = CURSOR_BDIAGSIZE;
- } else {
- c = CURSOR_FDIAGSIZE;
- }
+ c = CURSOR_FDIAGSIZE;
break;
case DRAG_TOP_RIGHT:
case DRAG_BOTTOM_LEFT:
- if (should_switch) {
- c = CURSOR_FDIAGSIZE;
- } else {
- c = CURSOR_BDIAGSIZE;
- }
+ c = rotation_array[(rotation_array_index + 1) % 4];
break;
case DRAG_MOVE:
c = CURSOR_MOVE;
@@ -3620,7 +3626,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans
Transform2D parent_xform = p_parent_xform;
Transform2D canvas_xform = p_canvas_xform;
- if (canvas_item && !canvas_item->is_set_as_toplevel()) {
+ if (canvas_item && !canvas_item->is_set_as_top_level()) {
parent_xform = parent_xform * canvas_item->get_transform();
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
@@ -3689,7 +3695,7 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
Transform2D parent_xform = p_parent_xform;
Transform2D canvas_xform = p_canvas_xform;
- if (canvas_item && !canvas_item->is_set_as_toplevel()) {
+ if (canvas_item && !canvas_item->is_set_as_top_level()) {
parent_xform = parent_xform * canvas_item->get_transform();
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 944bf9913c..b2fd855834 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -3566,7 +3566,7 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const
return point + offset;
}
-AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_toplevel_transform) {
+AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) {
AABB bounds;
const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(p_parent);
@@ -3591,7 +3591,7 @@ AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, boo
bounds = AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
}
- if (!p_exclude_toplevel_transform) {
+ if (!p_exclude_top_level_transform) {
bounds = p_parent->get_transform().xform(bounds);
}
@@ -6810,7 +6810,7 @@ void EditorNode3DGizmoPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material); //, DEFVAL(Ref<EditorNode3DGizmo>()));
BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name"));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_priority"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden"));
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index b3dc4ef5f2..4f627b1d0c 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -450,7 +450,7 @@ private:
Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
Vector3 _get_instance_position(const Point2 &p_pos) const;
- static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_toplevel_transform = true);
+ static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform = true);
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 35e8f560b0..1651de4048 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -226,6 +226,13 @@ void VisualShaderGraphPlugin::update_constant(VisualShader::Type p_type, int p_n
links[p_node_id].graph_node->set_size(Size2(-1, -1));
}
+void VisualShaderGraphPlugin::update_node_size(int p_node_id) {
+ if (!links.has(p_node_id)) {
+ return;
+ }
+ links[p_node_id].graph_node->set_size(Size2(-1, -1));
+}
+
void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) {
links[p_node_id].input_ports.insert(p_port_id, { p_button });
}
@@ -2516,6 +2523,7 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_
void VisualShaderEditor::_float_constant_selected(int p_index, int p_node) {
if (p_index == 0) {
+ graph_plugin->update_node_size(p_node);
return;
}
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 60a354d1fd..d43af82238 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -111,6 +111,7 @@ public:
void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name);
void update_constant(VisualShader::Type p_type, int p_node_id);
int get_constant_index(float p_constant) const;
+ void update_node_size(int p_node_id);
VisualShader::Type get_shader_type() const;
VisualShaderGraphPlugin();
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index d9c95b1944..75dc840738 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1318,32 +1318,50 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
if (si) {
List<PropertyInfo> properties;
si->get_property_list(&properties);
+ NodePath root_path = p_base->get_path();
for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
String propertyname = E->get().name;
Variant p = p_base->get(propertyname);
if (p.get_type() == Variant::NODE_PATH) {
- // Goes through all paths to check if its matching
+ NodePath root_path_new = root_path;
for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- NodePath root_path = p_base->get_path();
+ if (root_path == F->get().first) {
+ root_path_new = F->get().second;
+ break;
+ }
+ }
+ // Goes through all paths to check if its matching
+ for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
NodePath rel_path_old = root_path.rel_path_to(F->get().first);
- NodePath rel_path_new = F->get().second;
-
- // if not empty, get new relative path
- if (F->get().second != NodePath()) {
- rel_path_new = root_path.rel_path_to(F->get().second);
- }
-
// if old path detected, then it needs to be replaced with the new one
if (p == rel_path_old) {
+ NodePath rel_path_new = F->get().second;
+
+ // if not empty, get new relative path
+ if (!rel_path_new.is_empty()) {
+ rel_path_new = root_path_new.rel_path_to(F->get().second);
+ }
+
editor_data->get_undo_redo().add_do_property(p_base, propertyname, rel_path_new);
editor_data->get_undo_redo().add_undo_property(p_base, propertyname, rel_path_old);
p_base->set(propertyname, rel_path_new);
break;
}
+
+ // update if the node itself moved up/down the tree hirarchy
+ if (root_path == F->get().first) {
+ NodePath abs_path = NodePath(String(root_path).plus_file(p)).simplified();
+ NodePath rel_path_new = F->get().second.rel_path_to(abs_path);
+
+ editor_data->get_undo_redo().add_do_property(p_base, propertyname, rel_path_new);
+ editor_data->get_undo_redo().add_undo_property(p_base, propertyname, p);
+
+ p_base->set(propertyname, rel_path_new);
+ }
}
}
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 5a504da397..3dee4a229f 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -251,7 +251,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
if (can_rename) { //should be can edit..
String warning = p_node->get_configuration_warning();
- if (warning != String()) {
+ if (!warning.empty()) {
item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning());
}