godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 83 forks source link

Remove class_name in favor for registering scenes as types #2612

Closed Shadowblitz16 closed 3 years ago

Shadowblitz16 commented 3 years ago

Describe the project you are working on

SpaceShip game

Describe the problem or limitation you are having in your project

I just found out that class_name doesn't tie the script to the scene which is what most of my issues are based on. I think that class_name is confusing since its just a global alias of class but also only registers the script and a node. I think it would be more useful to register a whole scene as a type instead of just a script.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Basically you would have a right click menu or some sort of GUI that creates a new type out of the scene

This with #615 scripts would be bound to the scene type unless extended from the scene type.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

You would create a type from a script and then do..

extends MySceneType //with all children and scripts included

you would also be able to do..

class extends MySceneType:

If this enhancement will not be used often, can it be worked around with a few lines of script?

yes it would and I don't think so.

Is there a reason why this should be core and not an add-on in the asset library?

It would be used to tie the scene closer to scripts for static typing

KoBeWi commented 3 years ago

See also https://github.com/godotengine/godot/issues/21187 Stand-alone classes do have use (especially with inheritance), so instead of removing the functionality we should make it possible to bind them to scenes.

Shadowblitz16 commented 3 years ago

@KoBeWi I think Script inheritance should be removed as its a very unique thing to godot. However classes could still be able to extend from Scene or other types.

class extends MySceneType:
    ...

this gets into whether or not people like an extra indentation level but I think its not a issue as all classes in any language as this issue.

Shadowblitz16 commented 3 years ago

Updated the issue to be more clear. If your confused about the issue please ask questions I will try to explain this issue more the best I can

CedNaru commented 3 years ago

I'm all to be able to link a whole scene to a script instead of just one node. But script inheritance is something I personally use a lot so I wouldn't want it to disappear because reusing code would be much harder. So unless it can be replaced with something like Interfaces, traits, or partial classes, I want to keep it.

Shadowblitz16 commented 3 years ago

@CedNaru you would not lose script inheritance you just wouldn't be able to name your scripts. scene inherits scene script inherits script class inherits scene class inherits class

so while you can no longer name scripts, you could still implement something in a script and then extend it in a inherited scene. if you need a type you would use a class

zinnschlag commented 3 years ago

That does not seem reasonable. You do realise that a script is essentially a class? And since on a type-level a script is the most globalest anything global can be in Godot, it makes perfectly sense to add a global identifier (a.k.a class_name) to a script. This is a useful and elegant feature and it should not be removed.

On a related point: You seem to be proposing a lot of changes that would remove features from Godot (by replacing them with other features). And they all seem to be shot down rather harshly. I would like to provide another point of view onto this.

Godot is not a small toy only used by hobbyist any more. People have codebases of significant size. And in quite a few cases there are substantial financial interests behind these codebases.If your proposals would implemented and people wanted to move most/all their projects to newer versions of Godot, this would pose a huge problem.

I know Godot 4.0 has also breaking changes. But most of these are quite gentle and don't require substantial changes to existing code bases. There is still the idea of a tool floating around for automatically converting scripts in regards to trivial changes in 4.0 (renaming of node types and maybe simple syntax adjustments). In fact on the top of my head I can think of only a single 4.0 feature that would require me to dive down into my code and make manual changes (assuming this tool is implemented as suggested). I figure about 10-15h of work. Two days at most. Considering the huge benefits that 4.0 will bring, that is an easy sell.

Your proposed changes on the other hand are anything but simple. They change the foundation of Godot in fundamental ways and they are certainly not gentle. I quickly went over my code and made a (very) rough estimate. Assuming all your proposals of this type would be implemented I would be looking at about 100h of work. Even with my somewhat workaholic nature that means at least two weeks of lost productivity. That is a hard sell, especially since these changes would provide no benefit to me.

I doubt that I am the only one in this position. Even if these changes would be perceived as resulting in a usability improvement they would still be very likely to be shot down. It would require an improvement of overwhelming strength to give such a proposal any chance of succeeding.

TL;DR: Maybe refrain from making proposals that remove stuff people depend upon and instead make proposals that add things. No guarantee of course that these will be accepted, but at least they won't be met with the same level of hostility.

YuriSizov commented 3 years ago

To add to what @zinnschlag brilliantly said... We created this repository with the idea that people would provide detailed and well planned concepts for feature proposals. That means delving into the engine source, figuring out possible implementation, etc. While we are lenient and don't close proposals that fail that, core changes definitely need that level of planning. Being aware of the internal complexity would also put into perspective possible hurdles for the end users when adapting to changes.

Shadowblitz16 commented 3 years ago

@zinnschlag I understand there are breaking changes but this is because godot got way to popular too fast before the engine had a clear design.

Also you say godot isn't a toy but it still uses a custom scripting language that doesn't support alot a features because it would be too hard for beginners. I mean features get shut down because people complain of too many keywords also it still doesn't have exceptions

What other engines or languages allow you to name or extend a script? because I can't think of any. Most object oriented programming is done with structs or classes not whole scripts which is confusing to new users coming from other languages and also promotes bad practice when going to other languages from godot.

I know godot is not other engines or languages but that doesn't mean it should stay with the unique and unhealthy way it does things.

I understand that code will be majorly broken but its for future maintainability.

@pycbouh I close most of my issues not just because they fail but because I have a hard time communicating in the first place. its hard for me to write a perfect issue when I have a hard time communicating to the people I do know. when I write these issues its because I really do think its a good idea.

I don't see why godot even started this..

class_name Something extends Node, res://icon.png
    @export
    property

when this works perfectly fine..

@export(res://icon.png)
class Something extends Node:
   @export
    property

I think its insane people to want to keep the current Godot system when there are much better proven systems (and no I'm not talking about the node system I think that's actually one of the things Godot did right) I am mostly talking about how scripts are handled and custom types

Most of this should have been thought about at the beginning of godot's life and not in version 4.0 where we still can't make custom node's in gdscript

so pardon me if I don't think godot is perfect, and if I don't know how to program in c++, but I am just trying to suggest ideas that make game developers lives easier in the long run.

Shadowblitz16 commented 3 years ago

if you guys think we should keep class_name for now then at least mark it as obsolete, so people have time to move their code over.

thats what should have happened to keywords like export and onready for gdscript 2.0

dalexeev commented 3 years ago

209 Replace class_name with MyClass extends Node with implicit icon path

1208 Remove class_name in favor of class

1842 Remove the class_name keyword and use only class

2612 Remove class_name in favor for registering scenes as types

It's more correct to say "rename" rather than "remove". The purpose of class_name is to register the script in the global namespace. We don't need to remove this feature.

Shadowblitz16 commented 3 years ago

@dalexeev I just don't see why need to register scripts when we can move the code into a class and use that. then we can have multiple objects per script which lets us reduce filesystem clutter.

edit IDK tho I guess it comes down to if people want to support languages that doesn't support OOP

YuriSizov commented 3 years ago

Most of this should have been thought about at the beginning of godot's life and not in version 4.0 where we still can't make custom node's in gdscript

Named scripts weren't a part of Godot back then. They only happened in 3.x. It's a new feature, which is why it feels undercooked to you. It wasn't polished by years yet.

Shadowblitz16 commented 3 years ago

@pycbouh thats most likely it. I just know godot is hard for me to grasp due to alot of type limitations it has. and I know people that have tried godot and leave due to these limitations

KoBeWi commented 3 years ago

I just don't see why need to register scripts when we can move the code into a class and use that. then we can have multiple objects per script

That would be a good idea actually, but it's difficult to do due to limitations of the current system. To load a class, you need to load the whole script. So if you e.g. make a script with class A and class B and then want to instance only class A, you still need to load the whole Script resource. The classes are still registered by filename, even if they are named.

YuriSizov commented 3 years ago

so pardon me ... if I don't know how to program in c++

Then you have to accept the fact that none of your ideas will ever be implemented, because you haven't done the hard part yet. And nobody else will do it for you. Developers are not oblivious to the challenges that everyone faces, but they cannot plan your idea for you.

Shadowblitz16 commented 3 years ago

@pycbouh I know but there isn't much else I can do without spending 4 years of my life learning c++. I know c++ is one of those languages that take a while to master due to its complexity

Shadowblitz16 commented 3 years ago

@KoBeWi the problem with gdscript is to load classes without a script you would need to register them globally with a type name. but that will flood the namespace and I think redez said he didn't want custom namespaces. hopefully he will change his mind sometime in the future

YuriSizov commented 3 years ago

the problem with gdscript is to load classes without a script you would need to register them globally with a type name

Like I've told you before in an issue about built-in scripts: to load anything, whether it is somehow "registered globally" or not, you need to find it in a filesystem, load and parse the file, and then locate your class there. It's impossible to do otherwise.

dalexeev commented 3 years ago

I just don't see why need to register scripts when we can move the code into a class and use that. then we can have multiple objects per script which lets us reduce filesystem clutter.

1 file (script) = 1 class (named or unnamed). Inner classes are helper objects rather than standalone entities, and are best not used outside the script.

Shadowblitz16 commented 3 years ago

the problem with gdscript is to load classes without a script you would need to register them globally with a type name

Like I've told you before in an issue about built-in scripts: to load anything, whether it is somehow "registered globally" or not, you need to find it in a filesystem, load and parse the file, and then locate your class there. It's impossible to do otherwise.

Yes I know but the file can be bound to a global typename as well as the section of code for the class. This is mainly a issue with how godot handles scripts, most languages use something like a import or using statement to link files together, which is what godot could have done and then just run the script on the node when needed

zinnschlag commented 3 years ago

@Shadowblitz16 It seems you don't like the overall design of Godot very much and you consider it immature. There is the problem.

I and certainly a lot of other people here like the design of Godot. A lot. We don't want it to change in substantial ways. Speaking only for myself I find it very clean and very mature. Of course there are things that could be improved. But these are additions or minor adjustments. And the upcoming 4.0 stuff, which is still very much in line with the design principles of Godot as we have it today.

You repeatedly mentioned that Godot does things differently from all other engines. Now of the big ones I have only experience with two (Unreal and a tiny bit of Unity). From what I can tell you are right. And that is Godot's main selling point. As I said, I tried other engines and I disliked how they were doing things. Intensely. In fact Godot is the first general purpose game engine that does not make me want to hit my head against the wall until I pass out.

I will not get into a discussion which overall design is better, because there is a large amount of subjectivity involved and these discussions are a waste of time. Different people like different things. One can agree to disagree. If you want so much to be changed, maybe Godot is just the wrong engine for you? Have you considered that? Starting from a baseline that is closer to your needs seems a sensible approach. From what I am reading you may be served better with something like Unity.

Shadowblitz16 commented 3 years ago

@zinnschlag what does class_name bring that class and named scenes don't? I can guarantee my suggestion brings more to the table then what godot currently has

Right now people can't separate their scripts from their scenes/nodes without breakage They also can't enforce people to extend their scripts instead of attach new ones This design basically supports breakage by allowing someone to attach a script that might not have the required functions and properties that not only that scene and its children depend on but other scenes and scripts instantiating it.

^ THIS RIGHT HERE IS THE MAIN PROBLEM ^

Also the godot docs say the design philosophy is oop, which is not what it does with nodes and scenes.

attaching a script to node/scene != oop extending a node/scene as custom implementation == oop

Make up your minds I closed my oop suggestions because you guys didn't like them, now I am suggesting a new way for your dumb 1 script ecs and you guys still downvote it.

Also no I don't like unity

Shadowblitz16 commented 3 years ago

an ideal workflow would either be..

- scripts are nodes/scenes and can extend them
- scripts can only be extended
- only one script is allowed

or

- scripts are attached to nodes/scenes
- script can only be extended
- many scripts are allowed

right now it is..

- scripts are attached to nodes/scenes
- script can removed from scenes even if they are not the same type or cannot possibly run
- only one script is allowed

which is basically taking all the negatives from both

which again leaves possibility for misuse and doesn't bring any use over the other two

aaronfranke commented 3 years ago

It sounds like your use cases are things that aren't what class_name was designed for. In which case, just don't use class_name. You can reference the script by path for things like the is operator instead of class_name. Just because naming classes is not something that applies to your project, does not mean that it makes sense to prevent other people from having named classes.

class_name is for defining your own class. It is both expected and extremely useful to be able to extend them. Tell me, what if you were not allowed to extend Node2D? That would be stupid, and would make developing 2D games impossible.

I just found out that class_name doesn't tie the script to the scene which is what most of my issues are based on.

You mention many times that you want scripts to be tied to scenes. Not every script is the root of a scene, and many scripts are indeed reusable. Scripts being tied to scenes is not the intended function of class_name.

Right now people can't separate their scripts from their scenes/nodes without breakage

That depends on how generic the script is. It is totally possible to create a script that depends on a specific configuration of nodes that is not useful anywhere else. It is also totally possible to have general-purpose classes that are useful everywhere. For example, most of the built-in classes in Godot are generally useful, Node2D does not require a specific scene structure and in fact is a base class for most objects in a 2D game. VBoxContainer is also general-purpose and can be re-used anywhere without being tied to a scene. The list goes on and on.

They also can't enforce people to extend their scripts instead of attach new ones

Why do you feel the need to prevent other developers from doing something? Has it occurred to you that if you don't want to replace a script, you can just choose to not do that in your game?

Also the godot docs say the design philosophy is oop, which is not what it does with nodes and scenes.

Actually, that is what Godot does. Classes (including nodes and scripts) are literally object-oriented programming. Scenes are groups of nodes, and can also be thought of as objects.

what does class_name bring that class and named scenes don't?

For one, the ability to use class_name on something that isn't the root of a scene. For another, the ability to have a named class at the root of a scene that isn't.

I can guarantee my suggestion brings more to the table then what godot currently has

It really, truly, actually, genuinely, does not. It brings less to the table, it takes away functionality for no good reason.

Duroxxigar commented 3 years ago

I just found out that class_name doesn't tie the script to the scene which is what most of my issues are based on. I think that class_name is confusing since its just a global alias of class but also only registers the script and a node. I think it would be more useful to register a whole scene as a type instead of just a script.

Why would class_name tie a script to a scene? A scene is a collection of nodes, which are classes in of themselves. It makes complete sense why class_name would give you the node (and script attached to it) when trying to add it to the scene, because you are adding a new node. Each script is an unnamed class in Godot. When using class_name - it registers the class, with a name, in the global registry. Thus, you are making a new class and nodes are classes. extends is GDScript's keyword for inheriting a class (again, which nodes are). In Java it is also extends, C# and C++ just use :, and python just has you place it in parenthesis ().

Trying to register a scene as a type would be neigh impossible. What kind of type would it be? You have a collection of nodes, all of which can be different types. For example, say you want to add UI in your player scene in 3D. Every 3D node inherits from Spatial ultimately. But no UI node derives from Spatial. So what type should this scene be? Would it be of type Spatial or CanvasItem? You have almost two entirely different inheritance trees. (Multiple Inheritance is considered a poor practice for the vast majority of use cases)

Not to mention if people place multiple scripts in a scene (I am one who does such things).

What other engines or languages allow you to name or extend a script? because I can't think of any.

Unity, Unreal and I'm sure others. These are just the two I have more experience with. Inheritance is quite common.

Most object oriented programming is done with structs or classes not whole scripts which is confusing to new users coming from other languages and also promotes bad practice when going to other languages from godot.

A script is a class, so I'm not sure what you're talking about. Classes/inheritance trip up new users as a concept. It isn't specific to Godot. What bad practice is being promoted? Can you give details about this?

I think its insane people to want to keep the current Godot system when there are much better proven systems (and no I'm not talking about the node system I think that's actually one of the things Godot did right) I am mostly talking about how scripts are handled and custom types

Again - what part of Godot is not using established practices? It already is using inheritance, allows you to use it in GDScript, and promotes composition with the way you build scenes out of nodes. What other proven system are you referring to that Godot doesn't already employ?

I just don't see why need to register scripts when we can move the code into a class and use that. then we can have multiple objects per script which lets us reduce filesystem clutter. edit IDK tho I guess it comes down to if people want to support languages that doesn't support OOP

You are creating a class and using that. That is what a script is. That is what a node is. A scene is a collection of nodes (read classes). This is the composition part of OOP, which OOP actually tells you to do if you follow the traditional principles of OOP. Again - GDScript does in fact support OOP.

Right now people can't separate their scripts from their scenes/nodes without breakage

They certainly can and often times, people do. This is a code architecture flaw on your part - not Godot's.

They also can't enforce people to extend their scripts instead of attach new ones

What do you mean by this? Like make an abstract class?

This design basically supports breakage by allowing someone to attach a script that might not have the required functions and properties that not only that scene and its children depend on but other scenes and scripts instantiating it.

This is a tool and user problem, not an GDScript design problem. Yes, we could have a way for the engine to ensure that the script that you are putting on a node does in fact inherit from that node/class in some way shape or form. I don't think it has been suggested though. But it isn't necessarily a bad idea. Note - It DOES tell give you an error in the script editor but I'm talking about when you drag n' drop the script on a node - a dialog warning could pop up.

As for it being a user problem - again, this is a code architecture problem. I would suggest refining your approach and looking at it again. Making reusable scripts is not impossible in Godot.

Also the godot docs say the design philosophy is oop, which is not what it does with nodes and scenes. attaching a script to node/scene != oop extending a node/scene as custom implementation == oop

Nodes are classes. Scripts are classes. They also extend classes. That is inheritance, cut n' dry. A scene is also OOP, as it favors composition of nodes (classes), which is an OOP principle. The main thing that GDScript doesn't support, that is OOP, is encapsulation. Everything in Godot is an object. It is in fact, an OOP environment.

Shadowblitz16 commented 3 years ago

It sounds like your use cases are things that aren't what class_name was designed for. In which case, just don't use class_name. You can reference the script by path for things like the is operator instead of class_name. Just because naming classes is not something that applies to your project, does not mean that it makes sense to prevent other people from having named classes.

class_name is for defining your own class. It is both expected and extremely useful to be able to extend them. Tell me, what if you were not allowed to extend Node2D? That would be stupid, and would make developing 2D games impossible. and isn't that what class if for?

We shouldn't have to use is if we can guarantee a custom node with script or scene has the requirements the other scripts need to run. Also I told you class can do this, and like you said below it just needs to be supported. so obviously your ignoring me.

I just found out that class_name doesn't tie the script to the scene which is what most of my issues are based on.

You mention many times that you want scripts to be tied to scenes. Not every script is the root of a scene, and many scripts are indeed reusable. Scripts being tied to scenes is not the intended function of class_name.

I just want the ability to package a scene and its logic into a type that can't be messed with this is why there are immutable structs and accessor keywords in other languages because sometimes you don't want people messing with it

Right now people can't separate their scripts from their scenes/nodes without breakage

That depends on how generic the script is. It is totally possible to create a script that depends on a specific configuration of nodes that is not useful anywhere else. It is also totally possible to have general-purpose classes that are useful everywhere. For example, most of the built-in classes in Godot are generally useful, Node2D does not require a specific scene structure and in fact is a base class for most objects in a 2D game. VBoxContainer is also general-purpose and can be re-used anywhere without being tied to a scene. The list goes on and on.

Its far harder to write a script that can be used anywhere then a script that relies on nodes to do something. Also you can't use builtin Godot nodes like VBoxContainer as a example because they have internal logic that can't be messed with, custom node and scenes scripts can be.

They also can't enforce people to extend their scripts instead of attach new ones

Why do you feel the need to prevent other developers from doing something? Has it occurred to you that if you don't want to replace a script, you can just choose to not do that in your game?

because the script I attach to my node is there to do something or provide a interface for another script to use.

Also the godot docs say the design philosophy is oop, which is not what it does with nodes and scenes.

Actually, that is what Godot does. Classes (including nodes and scripts) are literally object-oriented programming. Scenes are groups of nodes, and can also be thought of as objects.

Scenes are nothing more then c++ types behind the engine everything is. Also I know scenes and scripts are classes but their relationship is not. because if it were, then when we would extended a node the script would not exist in the scene tree,because it would be the node

what does class_name bring that class and named scenes don't?

For one, the ability to use class_name on something that isn't the root of a scene. For another, the ability to have a named class at the root of a scene that isn't.

repeating yourself? like I said above, classes can do this too it just needs to be supported.

I can guarantee my suggestion brings more to the table then what godot currently has

It really, truly, actually, genuinely, does not. It brings less to the table, it takes away functionality for no good reason.

I just provided why your wrong and why the godot devs fail to see the bigger picture. if godot wants to become anything other then a household gameengine that got popular because it was easy for game developers to throw something together in it, the devs needs to take in account peoples problems and not just shutdown something because it "hides implementation"

aaronfranke commented 3 years ago

Also I told you class can do this, and like you said below it just needs to be supported. so obviously your ignoring me.

It's already supported, with the existing class_name system. We don't need scenes as types for this.

I just want the ability to package a scene and its logic into a type that can't be messed with

Ignoring for the moment that I don't like built-in scripts: You can do this with built-in scripts.

Its far harder to write a script that can be used anywhere then a script that relies on nodes to do something.

And for this reason, you want to take away the ability for other people to make their own classes?

Also you can't use builtin Godot nodes like VBoxContainer as a example because they have internal logic that can't be messed with, custom node and scenes scripts can be.

The code is available to anyone to mess with, it's just compiled into the engine. You can choose to not modify a file in your project, just like you can choose to not modify box_container.cpp in the Godot source code.

If you say that it doesn't count because this is part of the engine and not the project... well, you also said "can't be messed with" as a reason for wanting "the ability to package a scene and its logic into a type", which would be the same thing but in your project.

It's literally not possible to make something that truly "can't be messed with". Somewhere, it's a text file (or similar). It is trivial to modify a text file. There is extremely little difference between somehow packaging a script to not be "messed with" and placing it in a folder named do_not_mess_with_this_folder. Godot can't add a method to etch immutable runes into a stone (even if so, you can just get a new stone). Literally anything in your project can be messed with, your argument doesn't make any sense.

Scenes are nothing more then c++ types behind the engine everything is.

C++ classes are object-oriented programming.

because if it were, then when we would extended a node the script would not exist in the scene tree,because it would be the node

That's the idea, the node is an instance of the script. The fact that this isn't seamless is a known inconvenience.

like I said above, classes can do this too it just needs to be supported.

It's already supported, with the existing class_name system. We don't need scenes as types for this.

dalexeev commented 3 years ago

I like the current state of affairs and find the design clean enough. Even the fact that only one script can be attached to one node is correct in terms of the Godot architecture and OOP (since multiple inheritance is not supported).

Yes, there are some problems in this place, and they are well covered in #1935. Plus, I have several ways to get around this problem, which I use while there is no universal solution to this problem.

In my opinion, #1935 suggest a pretty good solution to this problem. But I can imagine how to adapt your proposal so that it is also an acceptable option, roughly equal to #1935. It is necessary to remove the part about that scripts can inherit scenes and vice versa. And we need to add the ability to register scenes globally (in the Project Settings, but this is not autoloads), it does not matter whether the script is attached to the scene root or not. Then you can do this:

var my_scene := MyGlobalScene.instance()
# Similar to
# var my_scene = load("res://path/to/scene.tscn")
# but GDScript automatically detects the type of the variable
# by looking at the root of the globally registered scene.

Then class_name can only be used for simple scripts without a scene file, and scene registration can be used for scenes.

MyGlobalScene can also be used as a type name (x is MyGlobalScene). Therefore, this option is likely to be more difficult to implement than #1935.

Shadowblitz16 commented 3 years ago

OK obviously I can't convince you guys. I could spend hours requoting you to try to get you to see the bigger picture. and you can spend hours quoting me with partial wordings to disagree

The point is this. Most other OOP game engines and languages have a way to enforce a interface on a type This is a proven system to allow other types to use it. Right now the only thing godot has that supports this is signals and even then its bound to the script that can be removed

If I have a scene called weapon like so.. Position2D (weapon)

There is no way I can guarantee a interface for that scene, and I will always need to load it with a string path that might change and break.

Also again no you can't make scripts that work on any node because they rely on the behaviors of the root node type and its children

Until either the godot devs admit that we need a way to strongly tie the scene and script together so people can interface with it, then I don't know what to tell you. I guess I just deal with it or switch to unity

dalexeev commented 3 years ago

Trying to register a scene as a type would be neigh impossible. What kind of type would it be? You have a collection of nodes, all of which can be different types.

The type of scene is determined by the type of its root node (taking into account the fact that a script can be attached to it). See #1935 and other related suggestions.

Also I would be interested to know the opinion of @willnationsdev on this topic.

KoBeWi commented 3 years ago

OK obviously I can't convince you guys. […] Until either the godot devs admit that we need a way to strongly tie the scene and script together so people can interface with it, then I don't know what to tell you.

Before convincing devs, you need to convince the community. None of your comments here attracted a single upvote, only confusion and disapproval. Which means that no one else wants this proposal. It can't even be considered in this state.

willnationsdev commented 3 years ago

Seems I'm late to the party. Thanks for the mention @dalexeev.

I will say that I once submitted a much more complicated core-changing pull request to Godot that allowed both Scenes and Scripts to be given global names, and it was all stored in a new singleton called the TypeDB. However, that proposal 1) had a ton of problems with its implementation since I was still pretty new to Godot at the time, 2) didn't appeal to reduz who was adamant that global names for scenes weren't necessary, and 3) eventually lead to reduz writing the first form of the script class system (with class_name) that we have today.

In other issues like #1935 and those related to it, @Shadowblitz16 and I have discussed various possible implementations of ways to fix the script-scene disparity in the API. More specifically, the disparity that...

  1. Scripts and Scenes support divergent, parallel inheritance hierarchies.
  2. Scenes don't have type recognition as classes within the Godot framework, despite them being representative of classes in most use cases. This is because they are more akin to a constructor rather than an actual class. They do not extend Script.

As for this proposal, based on my understanding of the original post, I don't think transferring the privilege of having a name from scripts to scenes is the right solution. For one, it's immediately more natural for a script, which is a literal class in OOP, to be allowed to have a name compared to granting a scene one. Scenes may be the stereotypical starting point for building things in Godot from a user perspective, but structurally, Godot is still very much built upon the OOP foundations of its core which revolves around ClassDB, Object, and Script. Anything that sacrifices the usability of the low-level systems is not likely to be supported by community members by my guess.

That's not to say there aren't flaws in Godot's OOP core though. For example, if you request reflection data from a script, it returns the data for both that script and all of its inherited scripts. That's because Object just knows it has a script, but not whether the implementation of that script's language understands or respects inheritance between multiple scripts. The only way to get semi-accurate reflection data is to separately fetch reflection data from each script in the inheritance chain and manually create a diffed collection yourself. However, even that isn't enough as evidenced by godotengine/godot#32428 which was reverted because of godotengine/godot#43491. To get truly accurate data, you have to get a ScriptInstance to call its _get_property_list() method since it dynamically produces new reflection values. Getting side-tracked here, but you get the idea. It certainly isn't perfect.

Ultimately, I'd like for #1935 to get implemented and then see how far that can take us. You wouldn't be able to give a name to a scene, but at that point, scripts and scenes become less indistinguishable. You would be able to infer the interface of a loaded scene based on the reflection data of its bound script. You would be able to infer the scene dependencies (child nodes, signals, etc.) of a script based on its bound scene data. These kinds of changes allow for much better feedback in all areas of the engine and could even extend to language servers for editing in other text editors. Provide a way for users to get the bound scene from a script and vice-versa and things will be in a decent shape. After that, we can then look into where the pain points are in terms of performance for gathering reflection data / memory loading and figure out which parts of the engine should cache things where to optimize workflows as needed.

Edit: And in case people are wondering, I don't really have time to implement #1935 anytime soon as my work priorities escalated in recent months, so someone else would likely need to take up the mantle on that.

dalexeev commented 3 years ago

reduz who was adamant that global names for scenes weren't necessary

I didn't know about it, but it makes sense. Other languages will still not be able to implement scene inheritance. And giving a global name to a resource (like an image or audio) is unnecessary.

YuriSizov commented 3 years ago

Well, technically all resources have a global "name": it's their file path (or scene file path + id for built-in resources). But indeed we must not forget that Scenes are nothing but data. They aren't code, they only declare node hierarchy, types and properties. Which is why without a script they are basically nothing in terms of types and dependencies.

willnationsdev commented 3 years ago

@pycbouh Well, even a script-class scene still has a "type" to some degree; the C++ class of its root node. The scene simply constitutes an extra layer of custom constructor logic to initialize fields differently and create/configure child nodes. And that is information that is traditionally accounted for by the constructor of a class. Therefore, you could argue that a script-less scene is still representative of a custom class - it's just that Godot does not formally attribute a name to the class. But in OOP terms, any scene is comparative to a class to some degree.

YuriSizov commented 3 years ago

Yes, you can argue that. You can even argue that declarative programming is still programming 🙂 At any rate, my point was that I don't see a reason to not allow naming scenes. I've had to use a workaround described in https://github.com/godotengine/godot-proposals/issues/1935#issuecomment-823008616 and I would've gladly exchanged it for a named scene that loads everything related to it, including scripts attached to its nodes.

willnationsdev commented 3 years ago

@pycbouh On the surface, I think that granting the ability to give global names to PackedScene resources is fine. Afterwards though, it cascades into a variety of issues that I foresee.

You have to contend with users who complain about wanting to have scripts and scenes share a name. If you choose to support that, how do you differentiate between the two when accessing it? If not, then it becomes part of a style guide we have to maintain about naming conventions for scenes versus script classes (e.g. ending in *Scn).

It then also forces additional maintenance in the scripting API since each language has to implement its own separate solution for granting access to those globally accessible scenes, either via global variables (GDScript, VisualScript) or through some sort of singleton (C#, NativeScript).

Then there's access and its corresponding core architecture issue. Where are you gonna define the global variables or singleton? If a language-specific implementation is necessary, then the data must be deserialized from project.godot prior to the language singleton initialization in startup, and the only place to put something global that is centrally defined in the API is in /core. But if you look at PackedScene, it isn't even defined until /scene, which means you'd end up with part of /core dependent upon /scene (probably not a good idea? Wouldn't have thought so, but could be wrong).

If you had a generic system for globally named Resources, then it would make more sense for there to be a core singleton to maintain access points for those path-to-name mappings, at which point, language singletons could access it cleanly and the Editor could handle the PackedScene-specific logic for rendering a name LineEdit for the scene somewhere in the GUI (possibly with a config value to auto-prefill them with a default conventional name?). But you'd then have to convince folks that global names for all resources should be supported.

Long-story short, supporting named scenes opens many more cans of worms which, with #1935 implemented, becomes mostly handled by just adding a Script interface helper function to fetch bound scenes from scripts and then per-use-case making a dummy script with a statically-checked scene path. The feature then goes from needing a few thousand lines of code to implement to a few hundred.

Edit:

I would've gladly exchanged it for a named scene that loads everything related to it, including scripts attached to its nodes.

With scene-binding supported in scripts, the end-goal I think would be to implicitly make the instantiation of the script defer to the instantiation of the scene. You effectively state that the scene should become the constructor for the script's class. And in such a case, your goal would be achieved by simply doing MyClass.new() on the script. But it would require language-specific logic to check for the presence of the scene binding and, if it exists, simply instantiate it rather than doing the typical behavior. It's really quite dumb though because each language's implementation should end up being the same. It's just that each language has its own means of instantiating types (.new(), new Type(), etc.).