-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
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
GDScript 2.0 (old) #39093
GDScript 2.0 (old) #39093
Conversation
I understood correctly: func my_func():
print("Hello!")
func _ready():
my_func() # It works.
my_func.call() # It works.
var x = my_func
x.call() # It works.
x() # This does not work. ? |
Given the frequency at which
This is a huge thing. To the point it is the default for every string in C#, Java, Lua, Javascript and... maybe Python? It may have a use far more than we think, and then requiring to use About dictionaries, they can be used a lot in GDScript because apart from classes, that's the only other way to represent named associative data. Considering we can declare them this way: var d = {
one = "Hello",
two = "World"
}
print(d.one, d.two) At the moment this still uses var d = {
&"one": "Hello",
&"two": "World"
}
print(d[&"one"], d[&"two"]) Sadly I can see why it may not be simple to do such a choice, at least with dictionaries...
I didn't know this was even a thing :O |
Will enums be 2nd class citizens or still 3rd? |
@dalexeev yes, that is correct. |
Well, I'm not sure if "frequency" is the defining point. It's more like it's tangent to execution.
In a way, yes, maybe making StringName by default is more useful. OTOH, many of this can be done behind the user's knowing. If you are passing as parameter to a function that accepts a StringName, it'll be converted automatically. So it's more of a question on when do you need to intern the string, which many times don't make much difference. It might be something to consider. I probably wouldn't make multiline strings a StringName though.
My idea is to make that use StringName by default. This still need to be fixed in core though, because Main problem is that there's a difference between attribute and subscript (that is, doing I have to think about it and also consult with reduz.
Against all odds this is actually a documented feature.
Well, |
d23b565
to
733f73f
Compare
Any way of preventing confusion between |
Not against that syntax. but it would be great if it could also be omitted when it can be inferred, like these cases: var name: StringName = "foo"
call("bar") # expected parameter is of type StringName |
I'm a pretty new Godot user, but I thought you might want to hear from a 'common folk'. The first class signals sound awesome. However, I am confused about the need for StringName. Are there optimizations that can be had by using such a class? Also, The removal of typed parameters seems like a regression. I've found them immensely valuable as I learn Godot and GDscript. Maybe I misunderstood and the final PR will have them back? It seems like the readability of GDScript will decrease if we add more symbols, especially to strings as in the example from @Zylann . Maybe there are optimizations I am not aware of that would come with such changes, but I am not excited about StringName.
|
Thats fantastic! I was often struggling with circular references, which would then create a cascade of script-errors, when i am using class_name + static typing in a lot of classes. |
Yes, StringNames are much cheaper to compare to each other compared to regular Strings. This kind of optimization is also found in many other languages.
They haven't been implemented yet, but they will be re-added before the final release.
To solve the usability issues, we could make StringName the default (or automatically infer its use when required). |
This is the standard way for me to reference nodes
Not using this will mean that any change to the tree will break paths with sometimes hard to find bugs. While using this ensures it will always work if I can run the scene. Will this line still be possible after the update and how would it look? (Its a bit awkward to write and I wish I could write somthing like this instead)
|
Sound really exciting!
I think this should be transparent for the users to keep the readability and simplicity of GDScript. @Reneator better to be patient and let the team have a clean restart, this PR is a big change, this is also the time to make or give your feedback on proposals. They are some about typing, i.e., make a fully typed workflow possible (any type, nullabe & way to force the typing) and many others. |
Random suggestion, but what if instead of making normal ( Alternatively, can we somehow use the same sigil for nodepaths and string names? (Gut feeling says "no" on this one, but maybe...) |
#16863 (comment), #16863 (comment): I think @Zylann's remark is pretty significant. Conceptually,
I understand that this is for performance, but this behavior is rather unusual and can be confusing. Do you plan to allow the use of |
What about the target parameter of If so, that sounds like good behaviour to me.
|
@nathanfranke I think path to the function already has target baked in. |
@katoneko Thanks, makes a lot more sense now 😄 |
|
Yeah, I remember that... and it makes me wonder how could a script/class could create a new instance of itself then, without having to rely on stunts like |
Something like this, but this makes little sense:
So, there are 3 reasonable options:
|
In practice I don't feel there's much of a difference. Having the constructor called Python is different because you create instances with It also simplify type checking, since
AFAIK it wasn't possible before to have a naked I believe this can be simply solved by adding a static reference to the same script, like |
@Geequlim https://www.patreon.com/posts/funding-and-up-36771862
|
@yuyubibibobibo: For a language with an ecosystem, use Python bindings. |
I just read the entire proposal thread on annotations and it seems to be a dope feature. I never actually encountered @"Nodepath" syntax before so I'm assuming NameString& and Nodepath^ wouldn't affect too many people. GD Script 2.0 really is an awesome upgrade. |
Please avoid making such statements. You make it sound like we have to change GDScript because we got money for it, while in reality, we asked for funding because we wanted to improve GDScript... There's a difference between doing work for the sake of using money (what your statement infers) and doing work that we planned to do, funding it with money that we requested for it. |
My reasoning is similar to rewrite of the renderer, audio engine, and other code that has been redone since Godot went open source: the code is stale, full of patches, using older non-optimized techniques, hard to maintain (be adding enhancements or fixing bugs). I took the opportunity to improve in the areas that caused confusing and had non-intuitive behavior: like First-class functions and signals is more a change in the engine API than GDScript itself.
GDScript is changing and breaking compatibility, but not by that much. I will work on a translating guide and possibly an automated tool. Won't be a long guide, because there isn't a lot to say. There's no reason to "write from zero". There will be things to adapt but not that much. In fact, I believe that GDScript changes in themselves will be less of a problem than translating the API changes from 3.x to 4.0.
We also lose stuff by adopting another language. The fact that we can add keywords (or now annotations) to change behavior specific to the engine is a great way to improve fast prototyping, which is one of the reasons GDScript exist. Like It's also a fallacy that "we can be free from the tedious tool chain development work and bug fixes". Maintaining a third-party language requires updating the engine and the bindings from the third-party, making sure the new additions still work, that it didn't introduce new bugs, etc. We also need debugger integration because we need to pause the game on a breakpoints. If you look at the C# bindings, you can see that there's a bunch of work to maintain that. Having an integrated code editor is something that a lot of people like. Even without now mainstream features, it's something that could be improved over time. I do believe this would be case even if a established language were introduced. The editor could be a LSP client that interact with language servers to provide the common completion and error-checking features. That could happen for GDScript, C#, or another language. And the thing is, if we were to drop GDScript, C# is already there and working, so that would be the new main language. If the point is using a established language with a vast ecosystem, you are free to use C#. |
Again: API changes will be a bigger problem than GDScript syntax changes. I had a plugin to convert from 2.1 to 3.0 and wasn't that much of a deal to rewrite (I also took the opportunity to clean up code, so it was a plus). |
Is # Before:
tween.interpolate_property(self, "variable", variable, new_value, duration)
# After:
tween.interpolate_property(&variable, variable, new_value, duration)
# (The color of "&" and "variable" in the code highlight should be the same.)
# Or only:
tween.interpolate_property(&"variable", variable, new_value, duration)
# ? |
@dalexeev |
@Zylann With the bitwise AND operator? But it is binary, not unary. And code highlighting greatly affects perception. I think the choice of the |
&"quoted_string_with_ampersand" can have single colour as well. |
will it now be possible to store superclass of A in a variable something like what Python can do class Z:
def x(self):
print ('Z x')
class A(Z):
def x(self):
print ('A x')
class B:
a = A()
def y(self):
super(A, self.a).x()
B().y()
# prints `Z x` |
Superseded by #40598. |
Can |
The |
Yeah, my bad, I was just reading it quickly and it's late. I like that connect is becoming first-class too. If all the gdscript "string" mechanisms are wiped out completely it'll be a glorious day. |
EDIT: The discussion here is quite lengthy now and a lot of cross-talk. I can answer small questions here (about the current PR, not future plans) but if you have a proposal to change something I'd prefer that you open a new issue and link it here, so the discussion can be contained in a thread. If you have a feature request you need to follow the GIP procedure.
This is a basic version of what we call "GDScript 2.0" (not an official name since GDScript changes with each engine version). The point is that this breaks compatibility much more than the previous updates.
The reason is that we can take the opportunity to clean up both implementation and design, allowing for a less-confusing language in which we can simplify the more complex constructs into a cleaner appearance. Also the implementation of GDScript has been patched so much that it became super difficult to understand (I can get some blame for introducing static types, which increase the complexity much more).
Most of the things remain the same, so it's not a completely new language. But people will have to relearn some stuff. I will write a new documentation page with the new syntax and everything so the reference will be complete (EDIT: already done it in godotengine/godot-docs#3623). Here I'll highlight most of what is change and what is still missing (which I'll be working on next).
This is only a partial version, mostly to show users what to expect sooner rather than later, and also to show what I'm working on.
Changes
Annotations
Some keywords have been replaced by annotations, as outlined in the proposal: godotengine/godot-proposals#828.
@tool
,@onready
, and the RPC keywords (@remote
,@master
,@puppet
,@remotesync
,@mastersync
,@puppetsync
) are now annotations.@tool
must be the first thing in the file (apart from comments) otherwise it doesn't work.Exporting now uses the annotations listed in the proposal: godotengine/godot-proposals#828 (comment)
Ignoring warnings will also be done with annotations. But there's no warnings yet, so it's not added for now.
yield
is nowawait
The
yield
keyword is removed in favor ofawait
. You can useawait some_signal
which works the same asyield
did before. You can also doawait my_func()
which is the same asyield(my_func(), "completed")
but it also works if the function isn't a coroutine: it'll just run synchronously and get the returned value. Note that ifmy_func()
returns a signal, then it will wait for that signal to be emitted._init
is nownew
The_init
constructor was declared in object but only really called in GDScript. Since you doMyClass.new()
to create a new instance, it makes more sense to use the same name as constructor. This also simplifies type checking as it doesn't need to rename the method name in some peculiar cases.I reverted this change for the reason outlined here: #39093 (comment)
super
keyword for super callsThe previous syntax for super calls was to use
.func_name()
which can be confused as a continuation of the previous line. Now you to to explicitly usesuper.func_name()
. If you want to call the same function you are in, thensuper()
is enough. This is also valid for constructors, so the old_init().()
syntax isn't valid anymore. There's no validation yet, but when type-checks are added back it will enforce asuper()
call in the constructor if the super class also have a custom constructor.First-class functions and signals
Now that we have
Signal
andCallable
as Variant types, they are used to represent first-class object. So instead of calling$Button.connect("button_up", self, "on_button_up")
you can get the signal and connect to the function name:$Button.button_up.connect(on_button_up)
. This avoids the use of strings.Note that Callable has a
call()
function. So if you want to pass functions around you need to call them like this:var x = my_func; x.call()
. Usingx()
won't work.String types
Now we have
StringName
in Variant so a notation for it was added:&"This is StringName"
. Those are interned strings which are better to use when equality tests are frequent. Since@
is now used for annotations, writing NodePaths need the^
prefix instead:^"This/Is/NodePath"
.Broken things
Since this is an initial pull request (as I wanted to have it partially working and possible to test ASAP), a bunch of things are still not working at all, as they need to be re-implemented with the new parser code.
Type checks
This will require quite some more time to add back. But in the bright side it should work much better than before. Including a fix to the dreaded issues with cycles.
You can use types in your code, but they won't do anything. This includes casting.
Code completion
Since this relies partially on type checks, it will also be done later.
Warnings
Similarly to the previous point, this also heavily relies on type-checking.
Language server
This relied on the parser code. It will be updated to use the new parser.
setget
My intention is to replace this with properties (see godotengine/godot-proposals#844). I haven't implemented yet to wait the discussion to show possible things that I could be missing. Still,
setget
as it was will be replaced, so I didn't implement the old way.Some optimizations
The old code already had some optimizations in place like reducing constant expression on compilation, and replacing
range
infor
loop to not allocate an array. This is undone for now but will be added back soon. Main reason is that the new code will be able to do a better job reducing those expressions by waiting until more information is available.Probably something else
I tried my best to test the code with some weird scenarios, but users never fail to surprise me. Eventually I'll go back to my project to automate GDScript testing which will avoid regressions from being introduced.
If something is broken, you can open an issue. However, unless it's something really bad I'll refrain doing anything before the next phase is completed.
I also haven't tested in release yet, so no guarantee it's fully working (note that nobody should be using the master branch in production, so this shouldn't be a big deal).
What about traits, lambdas, etc.?
My plan is to first make GDScript work back in the way it was, apart from the actual syntax changes. Then I'll work on new features. Even though there's quite some time before Godot 4.0 enters feature freeze, I prefer to delay working on new features. If we need to release 4.0 without those, it's not the end of the world.