-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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 link scene with class #21187
Comments
Why would a class necessarily be linked to a scene, when a scene could also not have a script as its root and still be registerable? |
I agree with @Zylann that having this be something where we directly tie a script to a scene is a bad design because they don't actually have a 1-to-1 relationship. If they did, Godot wouldn't support multiple instances of a script in a scene. And arbitrarily preventing a "scene-enabled" script from being re-used in a scene, for safety reasons, would be a sensible response to this feature, but overall useless/awkward to do. I agree that we should be able to define type names for scenes in general though and then be able to create them directly from the editor. If that scene just so happens to have a script at its root, then that's just a bonus. I've detailed my own proposal in the separate issue referenced above. |
Just to be clear @kubecz3k, if we were instead to let you manually tie a name and/or icon to a scene file (either in editing the PackedScene resource in the Inspector, by making changes in a new tab of the ProjectSettings window, or some other method that hasn't been discussed yet) and you could then instance a scene in the CreateDialog using that name/icon, is that something that would fulfill the needs of this Issue? If the scene you've created has your script class at its root, then we could use the root node's inheritance information to determine where to place it in the CreateDialog. This would effectively link the scene to the script "matter-of-factly" and not because of some sort of explicit pairing, which is much more loose and flexible. |
^ In fact, doing it this way would be even better since you wouldn't need to bother announcing a class name for the script itself; you therefore never end up in a situation where someone could instance the script by name and have it not work because the scene's content is absent from the script's environment. Instead, the most user-friendly way of creating the content is by creating the scene by name, rather than referencing the script at all. |
I'm very interested in this as well. Couldn't there be a way to simply "Register Scene as Node"? Like we add an option in the dropdown menu: Then somewhere in the Then we just load the I think I can make a plugin to do that, but I dunno if we can access these dropdown menus from a plugin. |
TL;DR; I have an idea on how to implement this in a relatively simple way. Check bottom for steps involved. I've been doing some thinking about this. I keep thinking that I'd expect the notion of a "scene class" to exist, but the more I've examined the notion of what a class is, the less I see usefulness out of making scenes full classes. Instead, I can see how using named scenes in an editor-only context would be the simplest way to go. This actually solves the exact problem of this Issue without adding any undue complexity to the engine. Here's a list of "class" features:
Now, the feature that this Issue revolves around is about adding feature 5, the CreateDialog creation, to scenes and presumably to also allow these scenes to have an editor-recognized global name (feature 1a) and ideally also a custom icon (feature 2). These features alone could be implemented strictly within the Editor if we stored the information in the EditorData and serialized it in the Project Settings, just like we do with script class editor icons. However, if we wanted to support feature 1b as well so that scripts can get the PackedScene resource by referencing its name alone, then the data would have to be stored in a runtime-accessible location, similar to the ScriptServer in core. This doesn't sound like something reduz would allow since it adds content to core purely for a possible use-case that no one has specifically requested. Features 2 and 3 don't really make sense in the context of scenes anyway since scenes don't inherently have any logic API built into them outside of scripts. As such, I think we should go with an implementation that adds custom names to scenes only within the editor and which subsequently allows those scenes to show up in the CreateDialog. Here's my implementation proposal:
What do you all think? Edit: Looking at the EditorAutoloadSettings class, it seems like it already does all of the data management and ProjectSettings serialization, so there wouldn't be a need to have any Hashmap in EditorData (steps 1 and 3 would be handled by step 2). |
I've basically spent the whole day thinking about this Issue, and I'm starting to believe that it is actually the key to incredibly simplifying pretty much everything about Godot's user-defined type system.
So each of the primary use cases of registering scenes under their own name each involve much more complex logic based on introducing more variance to the necessary API when handling "types" and each of these use cases become MUCH more simple to handle if one mandates a 1-to-1 relationship between scenes and named scripts. Rather than dictating how a scene is used, all this would do is dictate how a script is instantiated. And this makes sense anyway since scripts that are reliant on their scene structure to work don't make sense when instantiated independently in the first place. In order to prevent "hiding information from the user," we can introduce a global GDScript method (which could also be made a global method in the GD namespace in C#, etc. for other languages) that instantiates a bound scene instead of just a script when one passes a scene-bound script class's name to it.
If we then combine this with other methods that fetch the inherited class name (until You can even then create a custom export alternative for strings that lets you export a class name, mandate a base class, and then have the Inspector generate a dropdown of available types to select for the class name (which could then be plugged into the global Mandating the scene->script relationship also simplifies gathering reflection information down the line once we add support for generating documentation of scripted types. Scenes can't define methods and whatnot anyway, so it isn't like scenes need names that could potentially be passed to any such And, of course, this would also allow us to easily have the CreateDialog display This would eliminate several Issues (many of which I've created) with a simple and elegant solution that barely adds any complexity to the engine. So yeah...I'm probably gonna start working on this. Thoughts? |
Well, I talked with reduz, and making the changes I suggested (or any type-related changes to the CreateDialog for that matter) are being rejected. @akien-mga You may want to close this Issue as a result. The only way to solve OP's problem would be to expand custom types to support scenes (which will soon be deprecated in favor of script classes), register scenes with names through some other means (probably considered as unnecessary extra settings / maintanence), or make changes to the engine's core so that scene data can be bound to a script class (which reduz won't approve).
Anything that abstracts scenes away behind a script will be rejected. |
I noticed that you can pretty much already do this by making the following type of script class:
I've tested it, and it does the job just fine. And since any derived type can pretty easily do this, one can define types which know how to replace themselves with scenes at any point of the inheritance hierarchy they want (effectively meeting the demand of this feature). |
not quite since signals will not work in this scenario (nor connecting from or to the node) |
@kubecz3k Connect in what way? Couldn't you instantiate the scene, set up any necessary connections, and then replace itself with it? Give an example? |
@willnationsdev oh sorry! It's working in tool mode :) |
@willnationsdev is it possible to use some variation on this code that can work after a node enters the tree, or otherwise have a script detect when it's a replacement of itself? I want to use this without needing to register a separate "scaffolding" class to set up the scene for each of my objects, but when I try using If used as-is in a script to replace its attached node with a scene containing the same script, it causes an infinite loop and crashes the editor. |
@nobuyukinyuu The script example above is not capable of having its own functionality within the generated scene. It is strictly a "template generation" script that masquerades the scene as a script class, so having it be present within the generated scene would naturally lead to an infinite loop. If all you want to do is add some script-based configuration of the scene before it gets replaced, all you have to do is change Is that what you meant? |
Mainly, I was just hoping of being able to set up all of the nodes with one call in a scene which I have an associated Since _replace() is still being called (presumably) in between |
I'm not sure what you are losing out on. The way the node above works is that it will replace itself with the other scene, which presumably has its own script class as a root. You can then also create a script class for global namespacing that stores a constant for your scene, if you want to reference the scene directly by name in script code. So, for example, if you want the trifecta of CreateDialog instantiation, runtime instantiation, and script class type checking:
Now...I can see how this is a lot of boilerplate/complexity just to make this work for one script class in all the various use cases. So I'll have to think more on another approach that might simplify things more. |
I'll keep trying to think of a clever way to at least get these things without having to extend to special instantiators and copies of both registered classes and their templates showing up in the add node dialog. I really only want to make my existing stuff a little easier to add to my scenes instead of always having to drag them in from the FileSystem tab (they live in various places based on their use case). You're right when you say all of these things are possible, but they're not clean and I think the complexity defeats the purpose, if only a little. Specifically, having 2 similarly-named things in the Add Node dialog for each registered type is making me flinch. |
@nobuyukinyuu Well, what I just realized, thinking about it for a bit, is that we have two referential domains that cannot be coalesced without one losing access to a valid reference. There are two things you could do:
In the first case, if executed at runtime, you run the risk of third-party nodes with cached references to you becoming invalidated. In the second case, you run the risk of the child nodes in the new scene caching a reference to their parent upon creation and THEN getting reparented to your new node's hierarchy, effectively invalidating their reference. In either case, a reference could become invalid. The only guaranteed way would be if you could track all object references, but I don't think that is possible (it would require language-level reference tracking, like garbage collection, that would require periodic cleanups). Now, if you already know your domain situation and are confident that you could make use of either one of those algorithms effectively, then you could probably write a quick script to do things, but coming up with a generic engine/editor-level solution that comes with runtime consistency with the editor-time content doesn't seem realistic to me thus far. No matter what, you'd be developing some kind of hack. |
I've figured out a way to do it by using
Edit: I didn't think about references to an instance of this created at runtime by a script; this would likely invalidate a reference somewhere then, I'm assuming? |
@nobuyukinyuu Correct.
|
Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine. The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker. If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance! |
Issue description:
The new ability to define classes by using 'class' keyword is great. But it would be better if we could somehow link class script with proper scene for the purpose of instancing new nodes in 'create new node' dialog.
The spirit in which I work with Godot is that I'm using many small nodes when writing scripts, linking signals in inspector, defining positions with gizmos, or just dividing bigger logic into smaller pieces. This way my scenes are more verbose and are easier for me to work with.
So currently, most of my class scripts will be useless directly after instancing, which can be frustrating for other team members.
The text was updated successfully, but these errors were encountered: