Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #15470 "Crash on drag and drop scene file on empty scene" #15516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 70 additions & 40 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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() {
Expand Down Expand Up @@ -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"));
Expand All @@ -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);
}
}
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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) {
Expand All @@ -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();
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/canvas_item_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down