-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Ability to export Node types instead of just NodePaths #1048
Comments
I think I am against having the exported property function the same as an exported resource, where there is a dropdown for new etc. , would be better for it to functionally act the same as a NodePath export |
I will look into drafting a PR for this soon |
I have completed the basic functionality, however I think it's a little bit wonky, and have not implemented the setgets originally mentioned by @Zylann . Right now I'm having it function like a hidden onready, so |
I think the biggest issue with being able to update the exported nodepath in real time is that there would need to be some sort of generic templated setgets for every single export of a type, where the setter would:
All of this could possibly be encapsulated in either a new variant type or object maybe |
The really hairy part about the setter only taking a NodePath is that then the variable cannot be reassigned with a new instance of its Node. Maybe the setter needs to be able to take a NodePath, then it will run get_node, or another instance of its native type or script, then it will simply assign. |
After some discussion with creikey: Goal: Allow exporting of NodePath properties which automatically resolve to a reference to the Node. Condensing the acquisition of the path, and storage of its return value to one line. How, part 1:
This creates a NodePath dialogue in the Inspector. When the User selects a Path, get_node() is called, and the returned value is set to foo. How, part 2: When a Scene is saved, since Object References can not be serialized. The relative path to the node is gotten and stored instead. Using Node.get_path_to() When a Scene is loaded, and a properties type or export hint is not of type NodePath, but a NodePath is found in the file. This path is resolved upon onready. How, part 3: To preserve RemoteTree functionality, like when loading a Scene: When a Node Reference would be remotely set. Instead set the NodePath, then resolve it in the running Game. The Second half of Part 2, and Part 3, can also be described thus: When setting a value to a property. If that value is a NodePath, and the Type hint is not. Resolve the path, then set the result instead. |
one of the issues with nodepaths is that they are relative to the node the script is on. passing a reference to a node would be much better as it would no longer be tied to the node the script is on and you would directly be able to access its properties and methods as well however I disagree with this.. there is no reason someone needs to dynamically type a node. |
You can not export a direct reference. It must be serialized as a NodePath for saving and loading. This has nothing to do with runtime behavior. Setting a direct reference to a node not within the current scene isnt something you can do in the editor either.
Ultimately
|
Yes, we know that you can't export a reference. That's why this issue exists... |
This original issue existed because the use case of connecting up an existing node directly to a node script property isn't as straightforward as it could be. It works in a certain way because it's only about setting a reference to a node that already exists and can be referred to in I see "reference" mentionned but we need to be careful about what we mean by that, so to clarify just in case:
I tend to agree to that. Why would the user be required to type Besides with export type inference it could be shortened as: export var player : Sprite And it would also work in C#: [Export] public Sprite _player; Or any language that can tell Godot "this property has this type and I export it". Then it could be assigned by the scene loader (since the scene loader knows the paths, it's a specific syntax in |
At present, as far as I know, there's also no way to make the editor only let you set the exported NodePath to a certain Node type. Built-in Node types seem able to do this (see Node A and B properties on Joint2D that only accept RigidBodies, for example), but, as far as I know, there's no way to do it through script. |
It seems a bunch of users doing these one-liners:
It's nice to represent a dependency in one line like this, but also this is way too much code to express this. It also works (_dependent_node is either a valid Node2D or not). It would maybe be nice to perhaps syntactic sugar this in 4.0, if this is the easiest solution to expressing an external reference dependency, but only being able to serialize a NodePath. But ya, I agree, something better would be a NodePath + Type. Maybe type information could somehow be added to path syntax (prefix or suffix or something). example: 'res://::Node2D::./../nodes/someNode2D'. |
Unfortunately that code seems to exploit a particular scenaro in GDScript. If you do this in a I think such a feature does not even need the user to deal with |
This works fine for static typing. And any script or tool script will break if _dependent_node isn't valid. Exploit or not, it seems a lot of users are using that code to setup a dependent reference in a single declaration. And ya I agree, such a feature doesn't need. I'm just more or less commenting on whats being done in the wild right now. |
It will break if the tool script requires the node to be set. That's precisely why I mention tool scripts. Sure just adding
In your scenario yes, but theoretically, not in editor. If you add a static type When left untyped, it's a nice workaround for in-game properties though. |
Ya, again, like I mentioned this is more commenting on what users are doing. Whether that's in theory or not, in practice it's obvious that people want to express this dependency as a single declaration. And this is what's currently being used as a workaround as opposed to declaring & maintaining multiple variables to express a single dependency. I'm not sure if you'll be able to get rid of NodePath entirely in this proposal. Important to be able to serialize the dependency in a way that will fail at runtime if the serialized path can't resolve to an actual node. Also consider copy and paste working now with nodes, (I think copy & paste in the editor is purely in-memory, but I could be wrong). |
Mostly users just want to export+assign and use the dependency immediately as a node reference in code. They don't really care that under the hood it's serialized as a NodePath or whatever. But consider this: If I export a NodeRef or whatever type is proposed here and assign it to some sibling node, and then copy pasta this node into an entirely different scene what happens? (Tricky to do with a reference type. Lots of edge cases). Which is why I'd argue NodePath or some underlying resource type is still what we want to use to implement this functionality. Which then brings this full-circle to still doing something that is more syntactic sugar to accomplish what users actually want (less boilerplate to express this type of dependency). |
There still has to be a nodepath in
You can serialize the copied scene (so it becomes a nodepath, no longer an object in memory) and then deserialize into the destination scene. The same logic runs: if what you copied had a path to a sibling that's not part of your selection, then deserialization won't assign the property because it won't be within the data you copied, and it will come up as null.
Then that's a different feature: typing nodepaths. If you want this then the property will be a nodepath. |
My proposed approach already solves all this. |
You COULD do this, but last I checked this is not how copy/paste, undo/redo is done in the engine right now, and would be a very large undertaking to change this. imo probably very unlikely to be implemented like this. @TheDuriel, I'm in agreement with your approach syntax wise, but I disagree that the path should be resolved/written at scene save/load time. I think it should be resolved at assignment time. |
Yeah... I don't like this tbh, that's one of the reasons. I had to deal with that stuff already in the past and that's how I solved it (it even worked across two editors) |
So basically it's the same as a NodePath export but it automatically sets it to Right now I do this, which is messy and adds an extra variable and line: export var node_: NodePath
onready var node: = get_node(node_) as Node With this feature that code could be replaced with this and it would look identical in the Inspector: export var node: Node |
For the record: on the 22.2.2022 there was some discussion regarding this on rocketchat in #gdscript. The consensus was that this is a desired feature, but the implementation details are still a bit unclear. https://chat.godotengine.org/channel/gdscript?msg=dMaetkhmJxXGGaR73 |
|
I wonder again why node resolution has to wait all the way to ready at all... since the scene loader |
For this example I put it in ready, simply because it seems like a big hassle to do so in PackedScene and I couldn't find the place to put it. |
I think this is all about exposing already present feature in Godot. You can always filter nodes by Type in the Node Selector panel. Edit: After reading a bit, I understand the problem. Maybe the node could be instanced just like |
Is this happening in 4.0 or not yet? I'd like to add it to 4.0 if it's not currently in the codebase and the gdscript source is settling down somewhat |
Implemented by godotengine/godot#62185 (core) and godotengine/godot#62470 (GDScript). Might still need some similar changes for C# support, and any other language bindings that implement property hints as a language feature. |
@akien-mga Yes please, we need this on the C# side too. The inability to type node paths properly is a big deal, and I'm very happy to see it's being addressed in Godot 4. |
Wait what about exporting custom node types defined with class_name? |
Proposed here: #4785 |
I am currently on Godot 4.0 stable, where nodes can be exported and used in a running. However, when paired with the [Tool] attribute, the exported nodes would return null while the script is running in the editor. Is this intended, or is this feature not supported yet? |
Header/Notice: This is a revival of the old issue here. Mentioning @Zylann as they are the creator of the old issue.
Describe the project you are working on:
This is useful for all project types, but it is particularly useful with things like UI with lots of containers and hierarchy.
Describe the problem or limitation you are having in your project:
If someone would like to export a reference to a node that can be edited from the editor, there is a lot of boilerplate script code for each variable and the editor-side is not necessarily intuitive. (Clicking the
NodePath
variable and selecting a node rather than just dragging the node into the space).Previous code example:
Describe the feature / enhancement and how it helps to overcome the problem or limitation:
The feature enhancement I (and others) propose is to have a shorter syntax that handles the
NodePath
s. Basically, a simpler code format that behaves the same as the previous code.New code proposal:
@export var my_label: Label
Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
See the code proposal above.
If this enhancement will not be used often, can it be worked around with a few lines of script?:
This can be worked around in only two lines, but those lines are very redundant, especially in cases where several nodes are exported. Also, this is an extremely common use-case that has come up several times in most (if not all) of my projects.
Is there a reason why this should be core and not an add-on in the asset library?:
This is core in the script and not sure if it is possible to work around with an add-on.
The text was updated successfully, but these errors were encountered: