|
@@ -4326,7 +4326,7 @@ void Node3DEditorViewport::_remove_preview_material() {
|
|
|
spatial_editor->set_preview_material_surface(-1);
|
|
|
}
|
|
|
|
|
|
-bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
|
|
|
+bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) const {
|
|
|
if (p_desired_node->get_scene_file_path() == p_target_scene_path) {
|
|
|
return true;
|
|
|
}
|
|
@@ -4437,7 +4437,7 @@ void Node3DEditorViewport::_perform_drop_data() {
|
|
|
|
|
|
_remove_preview_node();
|
|
|
|
|
|
- Vector<String> error_files;
|
|
|
+ PackedStringArray error_files;
|
|
|
|
|
|
undo_redo->create_action(TTR("Create Node"), UndoRedo::MERGE_DISABLE, target_node);
|
|
|
undo_redo->add_do_method(editor_selection, "clear");
|
|
@@ -4453,7 +4453,7 @@ void Node3DEditorViewport::_perform_drop_data() {
|
|
|
if (mesh != nullptr || scene != nullptr) {
|
|
|
bool success = _create_instance(target_node, path, drop_pos);
|
|
|
if (!success) {
|
|
|
- error_files.push_back(path);
|
|
|
+ error_files.push_back(path.get_file());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -4461,12 +4461,7 @@ void Node3DEditorViewport::_perform_drop_data() {
|
|
|
undo_redo->commit_action();
|
|
|
|
|
|
if (error_files.size() > 0) {
|
|
|
- String files_str;
|
|
|
- for (int i = 0; i < error_files.size(); i++) {
|
|
|
- files_str += error_files[i].get_file().get_basename() + ",";
|
|
|
- }
|
|
|
- files_str = files_str.substr(0, files_str.length() - 1);
|
|
|
- accept->set_text(vformat(TTR("Error instantiating scene from %s"), files_str.get_data()));
|
|
|
+ accept->set_text(vformat(TTR("Error instantiating scene from %s."), String(", ").join(error_files)));
|
|
|
accept->popup_centered();
|
|
|
}
|
|
|
}
|
|
@@ -4475,12 +4470,17 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
|
|
|
preview_node_viewport_pos = p_point;
|
|
|
|
|
|
bool can_instantiate = false;
|
|
|
+ bool is_cyclical_dep = false;
|
|
|
+ String error_file;
|
|
|
|
|
|
if (!preview_node->is_inside_tree() && spatial_editor->get_preview_material().is_null()) {
|
|
|
Dictionary d = p_data;
|
|
|
if (d.has("type") && (String(d["type"]) == "files")) {
|
|
|
Vector<String> files = d["files"];
|
|
|
|
|
|
+ // Track whether a type other than PackedScene is valid to stop checking them and only
|
|
|
+ // continue to check if the rest of the scenes are valid (don't have cyclic dependencies).
|
|
|
+ bool is_other_valid = false;
|
|
|
// Check if at least one of the dragged files is a mesh, material, texture or scene.
|
|
|
for (int i = 0; i < files.size(); i++) {
|
|
|
bool is_scene = ClassDB::is_parent_class(ResourceLoader::get_resource_type(files[i]), "PackedScene");
|
|
@@ -4502,30 +4502,40 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
|
|
|
if (!instantiated_scene) {
|
|
|
continue;
|
|
|
}
|
|
|
+ Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
|
|
|
+ if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
|
|
|
+ memdelete(instantiated_scene);
|
|
|
+ can_instantiate = false;
|
|
|
+ is_cyclical_dep = true;
|
|
|
+ error_file = files[i].get_file();
|
|
|
+ break;
|
|
|
+ }
|
|
|
memdelete(instantiated_scene);
|
|
|
- } else if (mat.is_valid()) {
|
|
|
+ } else if (!is_other_valid && mat.is_valid()) {
|
|
|
Ref<BaseMaterial3D> base_mat = res;
|
|
|
Ref<ShaderMaterial> shader_mat = res;
|
|
|
|
|
|
if (base_mat.is_null() && !shader_mat.is_null()) {
|
|
|
- break;
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
spatial_editor->set_preview_material(mat);
|
|
|
- break;
|
|
|
- } else if (mesh.is_valid()) {
|
|
|
+ is_other_valid = true;
|
|
|
+ continue;
|
|
|
+ } else if (!is_other_valid && mesh.is_valid()) {
|
|
|
// Let the mesh pass.
|
|
|
- } else if (tex.is_valid()) {
|
|
|
+ is_other_valid = true;
|
|
|
+ } else if (!is_other_valid && tex.is_valid()) {
|
|
|
Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D);
|
|
|
new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex);
|
|
|
|
|
|
spatial_editor->set_preview_material(new_mat);
|
|
|
- break;
|
|
|
+ is_other_valid = true;
|
|
|
+ continue;
|
|
|
} else {
|
|
|
continue;
|
|
|
}
|
|
|
can_instantiate = true;
|
|
|
- break;
|
|
|
}
|
|
|
}
|
|
|
if (can_instantiate) {
|
|
@@ -4539,6 +4549,11 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (is_cyclical_dep) {
|
|
|
+ set_message(vformat(TTR("Can't instantiate: %s."), vformat(TTR("Circular dependency found at %s"), error_file)));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
if (can_instantiate) {
|
|
|
update_preview_node = true;
|
|
|
return true;
|