瀏覽代碼

Merge pull request #15516 from StateOff/fixes_crash_on_drop_scene_file

Fixes #15470 "Crash on drag and drop scene file on empty scene"
Rémi Verschelde 7 年之前
父節點
當前提交
4a25a4e53f
共有 2 個文件被更改,包括 71 次插入40 次删除
  1. 70 40
      editor/plugins/canvas_item_editor_plugin.cpp
  2. 1 0
      editor/plugins/canvas_item_editor_plugin.h

+ 70 - 40
editor/plugins/canvas_item_editor_plugin.cpp

@@ -4435,6 +4435,7 @@ void CanvasItemEditorViewport::_on_change_type_closed() {
 void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
 	label->set_position(get_global_position() + Point2(14, 14) * EDSCALE);
 	label_desc->set_position(label->get_position() + Point2(0, label->get_size().height));
+	bool add_preview = false;
 	for (int i = 0; i < files.size(); i++) {
 		String path = files[i];
 		RES res = ResourceLoader::load(path);
@@ -4456,9 +4457,12 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
 					}
 				}
 			}
-			editor->get_scene_root()->add_child(preview_node);
+			add_preview = true;
 		}
 	}
+
+	if (add_preview)
+		editor->get_scene_root()->add_child(preview_node);
 }
 
 void CanvasItemEditorViewport::_remove_preview() {
@@ -4603,6 +4607,14 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
 void CanvasItemEditorViewport::_perform_drop_data() {
 	_remove_preview();
 
+	// Without root dropping multiple files is not allowed
+	if (!target_node && selected_files.size() > 1) {
+		accept->get_ok()->set_text(TTR("Ok"));
+		accept->set_text(TTR("Cannot instantiate multiple nodes without root."));
+		accept->popup_centered_minsize();
+		return;
+	}
+
 	Vector<String> error_files;
 
 	editor_data->get_undo_redo().create_action(TTR("Create Node"));
@@ -4613,30 +4625,40 @@ void CanvasItemEditorViewport::_perform_drop_data() {
 		if (res.is_null()) {
 			continue;
 		}
-		Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
 		Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
-		if (texture != NULL) {
-			Node *child;
-			if (default_type == "Light2D")
-				child = memnew(Light2D);
-			else if (default_type == "Particles2D")
-				child = memnew(Particles2D);
-			else if (default_type == "Polygon2D")
-				child = memnew(Polygon2D);
-			else if (default_type == "TouchScreenButton")
-				child = memnew(TouchScreenButton);
-			else if (default_type == "TextureRect")
-				child = memnew(TextureRect);
-			else if (default_type == "NinePatchRect")
-				child = memnew(NinePatchRect);
-			else
-				child = memnew(Sprite); // default
-
-			_create_nodes(target_node, child, path, drop_pos);
-		} else if (scene != NULL) {
-			bool success = _create_instance(target_node, path, drop_pos);
-			if (!success) {
-				error_files.push_back(path);
+		if (scene != NULL && scene.is_valid()) {
+			if (!target_node) {
+				// Without root node act the same as "Load Inherited Scene"
+				Error err = EditorNode::get_singleton()->load_scene(path, false, true);
+				if (err != OK) {
+					error_files.push_back(path);
+				}
+			} else {
+				bool success = _create_instance(target_node, path, drop_pos);
+				if (!success) {
+					error_files.push_back(path);
+				}
+			}
+		} else {
+			Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
+			if (texture != NULL && texture.is_valid()) {
+				Node *child;
+				if (default_type == "Light2D")
+					child = memnew(Light2D);
+				else if (default_type == "Particles2D")
+					child = memnew(Particles2D);
+				else if (default_type == "Polygon2D")
+					child = memnew(Polygon2D);
+				else if (default_type == "TouchScreenButton")
+					child = memnew(TouchScreenButton);
+				else if (default_type == "TextureRect")
+					child = memnew(TextureRect);
+				else if (default_type == "NinePatchRect")
+					child = memnew(NinePatchRect);
+				else
+					child = memnew(Sprite); // default
+
+				_create_nodes(target_node, child, path, drop_pos);
 			}
 		}
 	}
@@ -4661,14 +4683,14 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
 		if (String(d["type"]) == "files") {
 			Vector<String> files = d["files"];
 			bool can_instance = false;
-			for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least one
+			for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least once
 				RES res = ResourceLoader::load(files[i]);
 				if (res.is_null()) {
 					continue;
 				}
 				String type = res->get_class();
 				if (type == "PackedScene") {
-					Ref<PackedScene> sdata = ResourceLoader::load(files[i]);
+					Ref<PackedScene> sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
 					Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
 					if (!instanced_scene) {
 						continue;
@@ -4682,7 +4704,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
 						   type == "StreamTexture" ||
 						   type == "AtlasTexture" ||
 						   type == "LargeTexture") {
-					Ref<Texture> texture = ResourceLoader::load(files[i]);
+					Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
 					if (texture.is_valid() == false) {
 						continue;
 					}
@@ -4708,6 +4730,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
 }
 
 void CanvasItemEditorViewport::_show_resource_type_selector() {
+	_remove_preview();
 	List<BaseButton *> btn_list;
 	button_group->get_buttons(&btn_list);
 
@@ -4719,6 +4742,17 @@ void CanvasItemEditorViewport::_show_resource_type_selector() {
 	selector->popup_centered_minsize();
 }
 
+bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
+
+	for (int i = 0; i < selected_files.size(); ++i) {
+		if (ResourceLoader::load(selected_files[i])->get_class() != "PackedScene") {
+			return false;
+		}
+	}
+
+	return true;
+}
+
 void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
 	bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
 	bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
@@ -4728,6 +4762,8 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
 	if (d.has("type") && String(d["type"]) == "files") {
 		selected_files = d["files"];
 	}
+	if (selected_files.size() == 0)
+		return;
 
 	List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
 	if (list.size() == 0) {
@@ -4737,25 +4773,19 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
 		} else {
 			drop_pos = p_point;
 			target_node = NULL;
-			_show_resource_type_selector();
-			return;
 		}
 	}
-	if (list.size() != 1) {
-		accept->get_ok()->set_text(TTR("I see.."));
-		accept->set_text(TTR("This operation requires a single selected node."));
-		accept->popup_centered_minsize();
-		_remove_preview();
-		return;
-	}
 
-	target_node = list[0];
-	if (is_shift && target_node != editor->get_edited_scene()) {
-		target_node = target_node->get_parent();
+	if (list.size() > 0) {
+		target_node = list[0];
+		if (is_shift && target_node != editor->get_edited_scene()) {
+			target_node = target_node->get_parent();
+		}
 	}
+
 	drop_pos = p_point;
 
-	if (is_alt) {
+	if (is_alt && !_only_packed_scenes_selected()) {
 		_show_resource_type_selector();
 	} else {
 		_perform_drop_data();

+ 1 - 0
editor/plugins/canvas_item_editor_plugin.h

@@ -576,6 +576,7 @@ class CanvasItemEditorViewport : public Control {
 	void _remove_preview();
 
 	bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
+	bool _only_packed_scenes_selected() const;
 	void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point);
 	bool _create_instance(Node *parent, String &path, const Point2 &p_point);
 	void _perform_drop_data();