-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Add the ability to expose nodes for direct access in instantiated scenes #84018
base: master
Are you sure you want to change the base?
Conversation
This will work with imported gltf scenes? |
Also please update your branch by rebasing instead of merging, important skill to get used to with contributing, see the pr workflow for details |
aacbd8c
to
c85dded
Compare
3d44605
to
ac26465
Compare
ac26465
to
2144053
Compare
You have reset your branch and this closes the PR, if you update your branch this can be reopened |
Sorry, still trying to get a grip on correct way of updating my repo from main while keeping my changes. I've pushed my new changes up. This includes a somewhat functional version of this pr. |
3233eac
to
5257a35
Compare
5257a35
to
03e1647
Compare
Forgive me if this is a dumb question. I've been following this PR with interest because having a feature like editable children but without breaking things if an edited node gets moved around seemed very useful, but I managed to miss this. How/why was this aspect lost? Maybe this would be a more compelling feature if this advantage could be retained? Perhaps nodes in a scene could have an Exposed Name that is independent of its unique name within that scene? I think it would be nice to decouple these two things.
I'd also like to express some disagreement with this. Even only the feature of explicitly specifying which child nodes are intended to be commonly accessed in the editor in parent scenes is still useful on its own. It is a documenting expression of intent of how to interact with the instanced scene. This can be added without removing the option to just immediately gain access to the whole subtree via editable children when that's what's needed, and that is a good thing. Having more than one way to do something is not necessarily a bad thing. I think this is true especially as it applies to bringing more options and flexibility for dealing with Godot's node hierarchy, which I feel can be very ungainly at the moment because of that lack of flexibility, particularly when working with instanced scenes. |
@pineapplemachine It was dropped because it was causing some issues (I don't remember the specifics, everything should be outlined in the conversation above) and the consensus was to leave it as-is for now and wait for Node UIDs to become a thing eventually, which would solve this issue. |
Trying to catch up, I think I've got a handle on why the unique names were dropped? I have a suggestion: The child scene should possess metadata indicating a subtree path to every exposed node. Then when the location of an exposed node within the parent is represented as e.g. A node's exposed name would be defined separately from its unique name. These are two functions that are important to have decoupled - internal implementation vs. external interface. This decoupling would allow a scene re-exposing a node from a child scene to expose it with a different, more descriptive name than it has in the child scene. Also, importantly, it would allow having two instances of a child scene, and to re-expose the node(s) of one child with different names than those of the other child. So, in the example in this previous comment #84018, Take for example a scene itself named There'd also be the possibility to incorporate this into node path syntax, in case it's useful to represent the location specifically using a node path? Something like I'm aware that a node having one internal and one external name/identifier isn't something the editor is at all set up to accommodate right now, and so this could end up being clumsy from a UI standpoint. But it seems like this may preempt some significant obstacles to usability with instanced scenes if this could become a thing, and the UI can always be improved over time. I'm not fully clear on exactly how UIDs are planned to work, so maybe that is an ideal solution to wait for that would already solve all problems? But it seems like the issue here runs a little deeper than just representing a reference to the node, right? Particularly because of the issue of duplicate names? |
I completely agree that the reliability on change is a must for godot. This is a logical approach and I considered something similar when hitting roadblocks (using internal/external paths/uids), and using meta data cleans it up a bit more. Node UIDs fundamentally shift the way node references are managed, replacing path-based referencing with ID-based referencing, which directly solves the primary issue of why editable children and exposed nodes are unreliable on change. So I think it's best to await that feature instead of adding temporary bloat to this one to make it work like that. I know I'll be following that pr with great anticipation :) |
b99c6a2
to
ace5a9b
Compare
|
4b5a1d3
to
38b8eb0
Compare
Currently there seems to be an issue with connecting signals to exposed nodes. Signals won't get connected even though the editor shows it in the first place. When closing and reopening the scene after connecting a signal, the connection is lost. Trying to connect the signal again crashes the editor. Screencast.From.2024-12-23.02-05-12.mp4 |
thanks for testing, will take a look |
It seems that The crash part of the issue was unrelated to this PR. diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index f916875c0d..9b189babd2 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -1090,7 +1090,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, HashMap<Node *, int> &node_map, HashMap<Node *, int> &nodepath_map) {
// Ignore nodes that are within a scene instance.
- if (p_node != p_owner && p_node->get_owner() && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner()) && !p_node->has_meta(META_MARKED_FOR_EXPOSURE)) {
+ if (p_node != p_owner && p_node->get_owner() && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner()) && !p_node->has_meta(META_EXPOSED_IN_INSTANCE)) {
return OK;
} |
38b8eb0
to
f4b239c
Compare
Thanks @timoschwarzer, that was definitely meant to be EXPOSED vs MARKED, this didn't immediately fix the saving for me, however adding in checks like I have for _parse_node did, probably due to the multiple inheritance of my test scene. Thanks for the bug find!
|
I've been using this PR for some time merged on top of the most recent master and I love it.
In this case RoomOne and RoomTwo collision polygons are switched around in the instanced scene.
|
a56e24d
to
0d2217e
Compare
@novhack thanks so much for giving this test drive and finding these issues!
The issue arises when it tries to find the path to an exposed node and can't, the nodes within the path are not renamed before this check is made. so its looking for the old name of the node... The p_parent->get_metadata(0) does not get updated with the correct path. I've tracked this down to a scene like this: the parent nodes are not being added to the node_cache within renaming instance reproduces the errors you're seeing. Doozy of an issue and hard to find the solution since I havn't seen this node_cache stuff too much before now. Main takeaways:
|
The behavior for point 3 depends:
Regarding the node cache, I don't know it it's related, but note that it is currently bugged sometimes (#100812). |
|
0d2217e
to
e05df31
Compare
e05df31
to
5418e0f
Compare
@timoschwarzer for this scene, Where should sib be in the hierarchy? or what if we put sib between p1child1 and p1child2? I can't think of a consistent way of handling this beyond limiting the user to placing siblings (via editor) either before or after all exposed nodes or disallowing it alltogether. |
@yahkr I might miss something, but from intuition I think in the example you sent sib should be placed on after parent1. If you define these two rules for placing siblings in the editor:
...then it should end up in a defined position in the tree for all cases, shouldn't it? |
Another solution that I think would be fine here is disallowing placing siblings between exposed nodes, so that exposed nodes will always be shown at the top in the tree below the scene root and you can only place siblings after the exposed nodes. |
Updated 11/1/2024
Description
This pull request implements a feature that significantly enhances Godot's scene editing capabilities. It allows specific nodes within a scene to be exposed, making them visible and allowing their properties to be overridden when the scene is instantiated elsewhere. I believe it is an improved version of editable children.
Note
Important
The use of unique names has been removed from this PR (#84018 (comment)) as there were too many issues with it, once #86960 is merged this PR should function like originally planned
Example 1
With this PR we can modify the properties of the exposed nodes and append child nodes to them, this lets us create super flexible scenes and use them like so:
and this is the same scene with editable children enabled. Far messier and poorer UX
Example 2
For a simple scene like the following, we expose the Sprite2D, the resulting tscn looks like this:
In another scene we instantiate this simple scene and override the exposed node's rotation property and add a child node to the exposed node. We also modify the color of the exposed node to orange
.tscn with this pr using exposed nodes:
.tscn with editable children and doing the same thing:
[node name="scene_1" type="Node2D"] [node name="scene_0_instance" parent="." instance=ExtResource("1_mdjal")] [node name="Exposed_0" parent="scene_0_instance/Parent" index="0"] self_modulate = Color(1, 0.666667, 0, 1) [node name="Child_Of_Exposed" type="Sprite2D" parent="scene_0_instance/Parent/Exposed_0" index="0"] position = Vector2(100, 30) scale = Vector2(0.5, 0.5) texture = SubResource("CompressedTexture2D_3sd7o") + [editable path="scene_0_instance"]
Sample Project
TODO
I think that this pr addresses the following proposals: