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

Fix for "Save Branch as Scene" #45937

Merged
merged 1 commit into from
Mar 1, 2021
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
20 changes: 17 additions & 3 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2321,10 +2321,14 @@ void SceneTreeDock::_new_scene_from(String p_file) {

Node *base = selection.front()->get();

Map<Node *, Node *> reown;
reown[editor_data->get_edited_scene_root()] = base;
Node *copy = base->duplicate_and_reown(reown);
Map<const Node *, Node *> duplimap;
Node *copy = base->duplicate_from_editor(duplimap);

if (copy) {
for (int i = 0; i < copy->get_child_count(); i++) {
_set_node_owner_recursive(copy->get_child(i), copy);
}

Ref<PackedScene> sdata = memnew(PackedScene);
Error err = sdata->pack(copy);
memdelete(copy);
Expand Down Expand Up @@ -2354,6 +2358,16 @@ void SceneTreeDock::_new_scene_from(String p_file) {
}
}

void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner) {
if (!p_node->get_owner()) {
p_node->set_owner(p_owner);
}

for (int i = 0; i < p_node->get_child_count(); i++) {
_set_node_owner_recursive(p_node->get_child(i), p_owner);
}
}

static bool _is_node_visible(Node *p_node) {
if (!p_node->get_owner()) {
return false;
Expand Down
1 change: 1 addition & 0 deletions editor/scene_tree_dock.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ class SceneTreeDock : public VBoxContainer {
void _import_subscene();

void _new_scene_from(String p_file);
void _set_node_owner_recursive(Node *p_node, Node *p_owner);

bool _validate_no_foreign();
bool _validate_no_instance();
Expand Down
112 changes: 1 addition & 111 deletions scene/main/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const

if (get_filename() != "") { //an instance
node->set_filename(get_filename());
node->data.editable_instance = data.editable_instance;
}

StringName script_property_name = CoreStringNames::get_singleton()->_script;
Expand Down Expand Up @@ -2267,74 +2268,6 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc
}
#endif

void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const {
if (get_owner() != get_parent()->get_owner()) {
return;
}

Node *node = nullptr;

if (get_filename() != "") {
Ref<PackedScene> res = ResourceLoader::load(get_filename());
ERR_FAIL_COND_MSG(res.is_null(), "Cannot load scene: " + get_filename());
node = res->instance();
ERR_FAIL_COND(!node);
} else {
Object *obj = ClassDB::instance(get_class());
ERR_FAIL_COND_MSG(!obj, "Node: Could not duplicate: " + String(get_class()) + ".");
node = Object::cast_to<Node>(obj);
if (!node) {
memdelete(obj);
ERR_FAIL_MSG("Node: Could not duplicate: " + String(get_class()) + ".");
}
}

List<PropertyInfo> plist;

get_property_list(&plist);

for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
String name = E->get().name;

Variant value = get(name).duplicate(true);

node->set(name, value);
}

List<GroupInfo> groups;
get_groups(&groups);

for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
node->add_to_group(E->get().name, E->get().persistent);
}

node->set_name(get_name());
p_new_parent->add_child(node);

Node *owner = get_owner();

if (p_reown_map.has(owner)) {
owner = p_reown_map[owner];
}

if (owner) {
NodePath p = get_path_to(owner);
if (owner != this) {
Node *new_owner = node->get_node(p);
if (new_owner) {
node->set_owner(new_owner);
}
}
}

for (int i = 0; i < get_child_count(); i++) {
get_child(i)->_duplicate_and_reown(node, p_reown_map);
}
}

// Duplication of signals must happen after all the node descendants have been copied,
// because re-targeting of connections from some descendant to another is not possible
// if the emitter node comes later in tree order than the receiver
Expand Down Expand Up @@ -2389,49 +2322,6 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
}
}

Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
ERR_FAIL_COND_V(get_filename() != "", nullptr);

Object *obj = ClassDB::instance(get_class());
ERR_FAIL_COND_V_MSG(!obj, nullptr, "Node: Could not duplicate: " + String(get_class()) + ".");

Node *node = Object::cast_to<Node>(obj);
if (!node) {
memdelete(obj);
ERR_FAIL_V_MSG(nullptr, "Node: Could not duplicate: " + String(get_class()) + ".");
}
node->set_name(get_name());

List<PropertyInfo> plist;

get_property_list(&plist);

for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
String name = E->get().name;
node->set(name, get(name));
}

List<GroupInfo> groups;
get_groups(&groups);

for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
node->add_to_group(E->get().name, E->get().persistent);
}

for (int i = 0; i < get_child_count(); i++) {
get_child(i)->_duplicate_and_reown(node, p_reown_map);
}

// Duplication of signals must happen after all the node descendants have been copied,
// because re-targeting of connections from some descendant to another is not possible
// if the emitter node comes later in tree order than the receiver
_duplicate_signals(this, node);
return node;
}

static void find_owned_by(Node *p_by, Node *p_node, List<Node *> *p_owned) {
if (p_node->get_owner() == p_by) {
p_owned->push_back(p_node);
Expand Down
2 changes: 0 additions & 2 deletions scene/main/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ class Node : public Object {
Array _get_node_and_resource(const NodePath &p_path);

void _duplicate_signals(const Node *p_original, Node *p_copy) const;
void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const;
Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = nullptr) const;

TypedArray<Node> _get_children() const;
Expand Down Expand Up @@ -366,7 +365,6 @@ class Node : public Object {
bool is_processing_unhandled_key_input() const;

Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const;
Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const;
#ifdef TOOLS_ENABLED
Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const;
Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const Map<RES, RES> &p_resource_remap) const;
Expand Down