-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
Yet another node copy-paste PR #34892
Conversation
Chin up, @KoBeWi! 5th time is the charm! 😉 |
I rebased the PR, because there were some conflicts. One line was lost as a result of that and I don't know what it was :I Anyways, I've been testing this for few months and seems to work very well. Copy-pasting on the same scene is like duplicate + move, while between scenes works like "Merge From Scene" (including all it's problems, i.e. unexpected resource sharing). IMO this should be fine to merge already >_> |
fe38c66
to
b5ab0e1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! Thanks for implementing this feature. I've started to use it on my custom branch and it generally works fine. I'll keep sending you feedback as I get to do more tests in different scenarios.
I've left a few comments on the code itself, and here are the two issues I've spotted so far:
- When pasting a node with connected signals:
The path to node is set to "." in the pasted node and it shows this error:
ERROR: Condition "!common_parent" is true. Returning: NodePath()
at: Node::get_path_to (scene\main\node.cpp:1645)
Callstack:
Node::get_path_to(const Node * p_node) Line 1645 C++
Node::_duplicate_signals(const Node * p_original, Node * p_copy) Line 2264 C++
Node::duplicate_from_editor(Map<Node const *,Node *,Comparator<Node const *>,DefaultAllocator> & r_duplimap) Line 2165 C++
SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) Line 475 C++
SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) Line 98 C++
- Deleting a node from the tree doesn't work anymore, it triggers this error:
ERROR: Error calling from signal 'confirmed' to callable: SceneTreeDock::_delete_confirm : Method expected 1 arguments, but called with 0..
at: Object::emit_signal (core\object.cpp:1181)
Can be fixed by setting a default value in the method binding:
ClassDB::bind_method(D_METHOD("_delete_confirm"), &SceneTreeDock::_delete_confirm, DEFVAL(false));
for (Map<const Node *, Node *>::Element *E2 = duplimap.front(); E2; E2 = E2->next()) { | ||
Node *d = E2->value(); | ||
editor_data->get_undo_redo().add_do_method(d, "set_owner", owner); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This process is different from what is currently done in the TOOL_DUPLICATE
case, where it only changes the owner on nodes that were already owned by the one being copied. I'm not sure what cases are covered this way, but should it be the same here?
In general, could duplicate and paste share most of the code since they are similar processes? (apart from the fact paste also handles separate scenes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, they do share much of the code. Though the most important part is duplicate_from_editor()
. I just tried to make a common method that would be called in both cases and well, it didn't work. The method I use in paste is much simplified and adjusted to work in scenarios that duplicate doesn't happen (like, copying scene root or pasting across the scenes).
Is the difference you spotted important? The code never failed me (and I've been using it since it was PRed here), but maybe there's some edge case I didn't predict and it breaks everything (not like it's possible to make the code perfect anyways).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it's important, and in the duplicate code it was there from the beginning so it's difficult to confirm the reason why it's done this way. I guess time will tell :)
My main point was that it might be safer and cleaner to use a common method, but if the two cases are too different to do that it's fine.
Not sure how to avoid this error, other than removing the error on non-common parent and just aborting.
It works for me, the binding you quoted no longer exists. Are you testing on master? |
I haven't investigated the details, but since duplicating a node doesn't trigger this error, could there be a way to avoid it without removing it completely?
I was initially testing on a different branch, but I have the same issue on master. After clicking ok in the delete confirmation popup, nothing happens and I get an error.
|
Ok, fixed the dialog bug. I missed it, because I'm deleting without confirmation 🙃 |
@akien-mga This PR seems ready to move on :) Since this feature has high demand, it would be nice to merge to master soon (if needed, after review from code owners) so more contributors can start testing it! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs squashed commits, but otherwise seems fine to me.
Using duplicate_from_editor makes sense, as it kind of guaranteed that the difficult part is handled by something already working in the editor.
Squashed. |
So I noticed that there were some problems after recent changes in core, but should be all fine now. |
eda93b2
to
f78dd54
Compare
I added a second commit that makes sure that built-in resources from nodes pasted to other scenes are unique (i.e. not shared between scenes). |
Update: Nevermind, I am wrong. As we discussed in chat, in this case it makes more sense that users will expect the new copy/paste to create new (duplicated) content. If you want the local one you copy from the local scene. |
f78dd54
to
8d28faa
Compare
Some shadowed declarations are breaking Linux. |
8d28faa
to
36494e8
Compare
Ok sorted out the shadowing. Turns out I could move one of the loops to the outside scope (line 474 in scene tree dock). |
Thanks! |
Ура. Спасибо, Comrade! |
This, together with removal of Merge From Scene, also resolves #31744. |
Following the failure of #31616, here's another attempt to close #3720 (counting all PRs so far, isn't it 5th one already?). I'll be angry if this one isn't merged eventually :/
In my previous PR, the problem was that copy-paste wasn't working like if you duplicated the node, so now I literally used duplicate(). The PR introduces node_clipboard variable, which is a list of copied nodes. Basically you can select multiple nodes and they will be duplicated into the list. If you copy, but the list already has elements, they are freed.
Paste makes yet another copy of these nodes and puts them under the node you have selected. The fact that I used duplicate (
duplicate_from_editor()
to be precise) ensures that all references and everything is correctly kept. If you copy a node with resource, the pasted node will still reference the same resource. What's more interesting, you can copy a scene root and paste it into another scene, which will create an instance (xd). Paste has already anti-cyclic-reference safeguards.The Cut operation might be arguable though. When you cut-paste a file, the original file is moved to the new location. I tried to do that, but I've ran into infinite number of reference-related problems, so my Cut operation works like in text editors. It's the same as Copy, but also deletes the node.