godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.14k stars 96 forks source link

Annotations in GDScript #828

Closed vnen closed 4 years ago

vnen commented 4 years ago

Describe the project you are working on: The GDScript compiler.

Describe the problem or limitation you are having in your project: Excessive keywords and complex syntax for some features (export, setget). Some keywords are allowed as identifiers to overcome this, but it ends up being a bit hacky.

Describe the feature / enhancement and how it helps to overcome the problem or limitation: Adding annotation syntax to GDScript to offload the amount of reserved words. With the potential possibility of including meta-data to scripts so first- and third-party tools can use them to provide extra features.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: This follows up from my initial idea on godotengine/godot#20318.

Annotations are used to extend a GDScript with functionality that is not directly tied to behavior. That includes editor attributes, such as tool and export, networking tags like master and puppet, tweaking warning reporting (instead of comments), and other small things like delayed initialization (onready).

Note: setget will be removed in favor of properties, so this won't be moved to an annotation. I'll open a different proposal for what I have in mind.

Annotation syntax

Annotations start with an @ (at sign) followed by an identifier that represents the annotation, e.g. @tool.

For the annotations that have parameters, you can send the arguments inside parenthesis like a function call:

@export_enum(One, Two, Three)
var counter: int

Optionally, you can name the arguments to make it clear if needed:

@export_range(start=0, end=100, step=1)
var ranged: int = 0

Annotations can be on the same line as the affected statement (order doesn't matter):

@remote @export var x: String = "something"

There are only script level and class level annotations. So they can't go inside a function. Invalid annotations will be reported as errors, to prevent subtle bugs from typos.

I'm not sure yet how to provide a system for user-defined annotations, this can be part of a different proposal or extended from this one.

Export hints

We discussed this at the Godot Sprint in January and the winning idea is that each export kind has its own annotation name. This will potentially simplify completion and hints. Types will be retrieved from GDScript typing system to avoid redundancy.

A few examples:

@export var x: int # Assume basic integer hint
@export_file("*.jpg", "*.png") var file # Can receive filters as arguments
@export_multiline var text: String # String but show big text box

enum MyEnum { One, Two, Three }
@export var enumerated: MyEnum = MyEnum.One # Using enum as type hint 

I'll try to come up with an exhaustive list in the next days.

Also, we can leverage this to implement sections:

@export_section(name="My section")
# Every subsequent export will be on the same section.

Completion

Code completion should list possible annotations after type the initial @. For annotations that require arguments, it should show tooltips with the expect arguments and potentially list valid values (e.g. valid warnings to enable/disable).

This also includes highlighting for recognized annotations.


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

Is there a reason why this should be core and not an add-on in the asset library?: It's intrinsic to the GDScript implementation, cannot be provided as an addon.

reduz commented 4 years ago

My 2cents on this.

Example

C++:

PropertyInfo("something",PROPERTY_HINT_RANGE,"0,5,0.01")
PropertyInfo("something",PROPERTY_HINT_FLAGS,"aflag,anotherflag")
PropertyInfo("something",PROPERTY_HINT_ENUM,"One,Two,Three")
PropertyInfo("something",PROPERTY_HINT_FILE,"*.json")

Using GDScript autoconversion:

@export_range(0,5,0.01)
@export_flags("aflag","anotherflag")
@export_enum("One","Two","Three")
@export_file("*.json")

so what happened here?

This ensures we don't have to maintain a parallel system for exporting hints. Having special cases for exporting resource types or enums is fine, but as a base the autoconversion should just work.

ThakeeNathees commented 4 years ago

some other use cases I can think of


## to register class names
@class_name("MyClass")

## ignore warnings
@ignore_warning("unused_argument")
func _process(delta):
    pass

## and for override functions
@override
func _to_string()->String():
    return "str"
willnationsdev commented 4 years ago

I think this proposal looks great.

I'd also like to emphasize that I think leaving room for a future proposal to enable user-defined exports is a good idea. It paves the way for people to design UX in their projects that is better optimized for use with their own custom tools. I prefer having to flip between code text and the editor GUI as little as possible. If I can write my own tools to have script code declaratively trigger behaviors in the editor based on what I tell my scripts to be or do, then that empowers me to code the way I want to, to build more powerful editor tools, etc. Of course, some practical use cases of user-defined signals should be outlined for it to actually be implemented. And again, that would likely be for a separate proposal after the release of 4.0.

As for additional annotations to add to the list...

# Class-level annotation.
# Adds group names to the Node upon instantiation.
# similar to `onready`, but tied directly to `add_to_group()`
@groups("enemy", "goomba")

# Likewise, a delayed registration for a signal connection.
# Must be applied to a variable with the onready annotation.
@onready
@connect("body_entered", self, "_on_body_entered", ["Hello"], CONNECT_ONESHOT)
var area := get_node("Area2D") as Area2D

# Method annotation.
# Allow users to easily export one-off buttons for the Inspector
# that execute a parameterless, void-returning function.
@export_button("Click Me!")
func _do_the_thing() -> void:
    print("Hello World!")

Exporting a method as a button is tracked in godotengine/godot#9380.

samdze commented 4 years ago

I think being able to define and use custom annotations is the main attraction of them. Having export hints, setget, etc. moved to annotations alone doesn't change a whole lot.

I'd consider annotations just a way to assign inspectable metadata to properties, classes, etc. so that e.g. Godot plugins can check for them and act accordingly (even the built-in ones).

So what if I want to get the annotations assigned to a property? I'd guess I'll have to get the proper PropertyInfo and check if it has the annotation I'm looking for. Isn't a refactor of how PropertyInfos are constructed in the C++ side needed to support this? Other scripting languages could then benefit from this new metadata system.

willnationsdev commented 4 years ago

@samdze

I suspect that, rather than change how PropertyInfo objects are designed, annotations will instead be a language-specific feature. But in order for it to be usable by the editor at all, you still need some low-level Script interface method that exposes whatever metadata the annotations will define.

This way, C#'s attributes and GDScript's annotations can both be capable of exposing the same information through metadata-specific callbacks. We would then modify the Editor to get property annotations by fetching the object's metadata rather than be getting the property list (or something of that nature).

There should be no need to modify PropertyInfo to accommodate the changes while still enabling each language to have their own means of supplying metadata in a common interface.

I'm still not in-the-know about the discussions on the topic though, so maybe a different methodology is planned?

vnen commented 4 years ago
@class_name("MyClass")

## ignore warnings
@ignore_warning("unused_argument")
func _process(delta):
    pass

## and for override functions
@override
func _to_string()->String():
    return "str"

Class name won't be an annotation since it's part of the script itself.

Override is something I thought in the past as well, potentially showing a warning if it's missing.

vnen commented 4 years ago

@willnationsdev

I'd also like to emphasize that I think leaving room for a future proposal to enable user-defined exports is a good idea.

Well, user-defined exports still needs to be handled by the editor in some fashion, so if/when this is done we can integrate in GDScript. Using annotations for export already make this potential addition easier IMO.


@samdze

I think being able to define and use custom annotations is the main attraction of them. Having export hints, setget, etc. moved to annotations alone doesn't change a whole lot.

I'd consider annotations just a way to assign inspectable metadata to properties, classes, etc. so that e.g. Godot plugins can check for them and act accordingly (even the built-in ones).

I'm okay with custom annotations, but there's no plan for that yet (that is I don't know how that would work). We'll need a second proposal with detailed use-cases so we can cover what's needed.

Right now we could add a @meta annotation that would work like set_meta in the script (and maybe on instances too, but preferably not IMO), so you can associate arbitrary data with the class. Won't be tied to any particular member but it could be useful for now.

This will also be added for GDScript only, as each language has their own way of adding metadata, so it won't go PropertyInfo. You'll need a GDScript instance to be able to access this data, but that should be expected.

vnen commented 4 years ago

I compiled all the export hints that makes sense to expose:

@export # Basic: built-in types, resources, enums, typed arrays. Inferred from variable type.
@export_enum("values"...) # Custom ad-hoc enum, typed integer.
@export_file("filters"...) # Local file
@export_dir # Local dir.
@export_global_file("filters"...) # Global file
@export_global_dir # Global dir.
@export_multiline # Multiline string
@export_placeholder("placeholder") # Placeholder for text field
@export_range(min, max, step = 1, slider1 = "", slider2 = "") # Integer/float range. slider can be "or_greater", or "or_lesser"
@export_exp_range(min, max, step = 1, slider1 = "", slider2 = "") # Same as range, exponential slider
@export_exp_easing(hint1 = "", hint2 = "") # Exponential easing function (Math::ease), use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation", "inout")
@export_color_no_alpha # Color, but ignore alpha component in the editor
@export_node_path("type") # NodePath, but restrict to a certain Node type
@export_flags("values"...) # Bit flags (multiple values can be selected)
@export_flags_2d_render # 2D render layers selector (int)
@export_flags_2d_physics # 2D physics layers selector (int)
@export_flags_3d_render # 3D render layers selector (int)
@export_flags_3d_physics # 3D physics layers selector (int)

The only one different from the PropertyHint enum is the node_path because I feel like node_path_valid_types is a bit too much. Those hints are nowhere defined as strings, so we have to sprinkle custom logic to define this anyway (maybe it should be rename internally too). It's also not currently exposed (there's an open PR to do it but it's not merged), but I believe it makes sense to add, since it's easier with this new system.

Additionally, we can add special annotations for categories and groups:

@export_category("category")
@export_group("group", "prefix") # All variables with name starting with "prefix" are added to the group.

Those create internal properties with the correct PROPERTY_USAGE_ value set. There's also a PROPERTY_USAGE_SUBGROUP but it's nothing uses it so I'm not sure how it looks. If it's useful it can be exposed too.

samdze commented 4 years ago

@vnen I'm a bit concerned about annotations that both export the variable and also assign a special PropertyEditor in the inspector. That's because when custom annotations will be supported the only way you could use them to override the property editor will be to assign two annotations to a property: @export and @custom_annotation, and that would be the case for custom editors only, when built-in ones only need a single "export + special editor" annotation. So, mine is a coherency concern.

I see how this could be resolved in two ways:

  1. @export becomes the only annotation that effectively exports a property. The property is exported with the default property editor if nothing else is specified. The export prefix will be stripped off the other built-in special editor annotations names:
    
    // @export annotation needed
    @export @enum("values"...) # Custom ad-hoc enum, typed integer.
    @export @file("filters"...) # Local file
    @export @dir # Local dir.

@export @custom_a("values"...) etc...

2. User defined annotations will be given the power to internally assign the export flag to the property they are assigned to. So custom annotation that want to provide custom editors can be used like built-in export annotations (export prefix recommended):

@export_global_dir # Global dir.

@export_custom_a("values"...) @export_custom_b(hint1 = "", hint2 = "") @export_custom_c etc...


I think I prefer this second option, as it also keeps `@export_category(...)` and `@export_group(...)` coherent with everything else.
willnationsdev commented 4 years ago

@samdze

So, either a separate annotation or one that overrides the effect of another? I mean, all it really comes down to is, if you've got an annotation that is applied to a property, then the script logic implementing the annotation will need to have read/write access to the PropertyInfo generated for the property.

At that point, you'd be able to implement either strategy, and it would be up to the user who is writing the custom annotation to determine whether they want it to be separate or an override. @vnen's work at the moment, to create the built-in annotations, will likely have little to no impact on the aspects you've distinguished above.

samdze commented 4 years ago

That comes to how doable it is to expose such functionality to user defined annotations and how easily they can manipulate PropertyInfos.

If complete freedom can be provided in a user-friendly way, then yes, the current built-in annotation naming is ok and the user could take either solution (even if built-in annotations would keep the @export_something naming scheme, so the same for custom ones should be recommended).

Otherwise, a custom annotation couldn't be used like a built-in @export_something one, because it would need an additional @export annotation to properly work.

Maybe I'm worrying too much and custom annotations will easily be able to provide all the needed functionality.

Shadowblitz16 commented 4 years ago

so this is what I had in mind for reducing the amount of annotation per line...

@annotation_a(value)
@annotation_b()

could become (could as in optional)

[@annotation_a(value), @annotation_b]
lentsius-bark commented 4 years ago

I know very little about annotations in other languages but what's being discussed here looks like a fun addition to GDScript. Looking forward to it.

vnen commented 4 years ago

@Shadowblitz16

so this is what I had in mind for reducing the amount of annotation per line...

@annotation_a(value)
@annotation_b()

could become (could as in optional)

[@annotation_a(value), @annotation_b]

It's already in my proposal that you'll be able to do this (doesn't matter if annotations have arguments or not):

@remote @export var x: String = "something"
vnen commented 4 years ago

@samdze

That comes to how doable it is to expose such functionality to user defined annotations and how easily they can manipulate PropertyInfos.

If complete freedom can be provided in a user-friendly way, then yes, the current built-in annotation naming is ok and the user could take either solution (even if built-in annotations would keep the @export_something naming scheme, so the same for custom ones should be recommended). [...] Maybe I'm worrying too much and custom annotations will easily be able to provide all the needed functionality.

There's not a proposal for custom annotations yet. I don't really see anything in this one that would hinder custom annotations in the future, but before I go that route I need to see how people are going to use custom annotations, and for that I need an actual proposal. Otherwise I might add stuff that nobody uses and miss something that many people expect.

If custom annotations are able to edit the PropertyInfo, then they can change the hint and usage to be an actual export, there's no need to combine with the builtin @export one. In fact, you could make one called @export_my_thing that looks like the builtin ones.

AFAIK there's nothing in PropertyInfo that allows a custom editor, so this needs to be done before we allow annotations to do it (well, can be at the same time, but it's an idea on its own). This can be part of the custom annotations proposal.

samdze commented 4 years ago

@vnen Mine was quite a future concern on an hypothetical naming issue.

If custom annotations are able to edit the PropertyInfo, then they can change the hint and usage to be an actual export, there's no need to combine with the builtin @export one. In fact, you could make one called @export_my_thing that looks like the builtin ones.

Yes, that's what i meant by "provide all the needed functionality"

AFAIK there's nothing in PropertyInfo that allows a custom editor, so this needs to be done before we allow annotations to do it (well, can be at the same time, but it's an idea on its own). This can be part of the custom annotations proposal.

And this is what I was talking about when I mentioned that a refactor of PropertyInfo could be required/preferred as I personally don't like the fact that built-in hints are hardcoded as an enum and custom ones are completely excluded from this system and would need an additional one.

We'll talk about it in deep in the future.

Talking about this proposal, how would I inspect the annotations assigned to a property/method/class? Is a system to get the property-bound, method-bound, class-bound etc. metadata expected to be added? Let's say I have an inspector plugin that activates a special property editor on properties that have the @onready annotation, how would the API be?

vnen commented 4 years ago

Talking about this proposal, how would I inspect the annotations assigned to a property/method/class? Is a system to get the property-bound, method-bound, class-bound etc. metadata expected to be added?

This is also not included here. For much of the same reason: I don't know yet how people are gonna use it.

I'm not against it, but I want to gather real use cases before committing to it. If nobody opens a proposal for custom annotations, I'll make one once I have time and ideas in mind.

jknightdoeswork commented 4 years ago

I think this looks great, and I love @willnationsdev idea to have annotations to hook up signals, but I'm not sure if I am understanding him correctly.

I'm thinking something like this would connect some_function to my_area's body_entered signal:

@connect(my_area, "body_entered")
func some_function():
   #some code...

For export_node_path, I love that you have type added. I came here to this repo to propose export(NodePath, SomeType), so that's awesome!

The other thing I was thinking that would be nice is if there was a way to avoid explicitly coding the subsequent get_node call that exporting a NodePath necessitates.

Like maybe there could be export_node instead of export_node_path and export_node sets the value of the get_node call to the variable instead of just setting the node path?

so this syntax:

@export_node(Control)
var my_main_menu

would now make my_main_menu be typed to Control.

At runtime my_main_menu would be the Control referred to by the node path linked in the editor - not just the NodePath to the Control.

willnationsdev commented 4 years ago

@jknightdoeswork The example signal connection annotation I gave was having the annotation be placed on an onready Node property rather than on a method. So, yeah, it could conceivably be done either way.

@onready
@connect("body_entered", self, "some_function")
var area := get_node("Area2D") as Area2D

# Implied to connect signal onready? onready annotation doesn't make sense for a method.
@connect(area, "body_entered")
func some_function():
    pass

The latter syntax, if onready is always assumed, is arguably more concise. It also makes cleanup easier if you later choose to remove the callback since you only have to update the code in one place.


I also agree that, in addition to having the export_node_path(type) version to properly mimic the PROPERTY_HINT_* flags, we should also have an export_node(type) flag that does the same thing, but handles the Node assignment for you, if at all conceivable. It'd take some modifications to allow the Editor to read and respond to the annotations with error messages like Node configuration warnings.

For example, if the node is a descendant, then you can push initialization till @onready. If it's an ancestor, then you can setup initialization as part of a signal connection to the ancestor's ready signal once it has been initialized. Doing this all behind-the-scenes would make its usability really, really good. If nothing has been assigned for it, you can set a configuration warning.

You could also make it more transparent and just create Node configuration warnings in the editor if people don't add an @onready or @connect annotation for the corresponding NodePath assigned in the Inspector, but making users require a code change in the script because the Inspector wasn't given a compatible value is really bizarre, so I think it'd be better to hide the details from the end-user. Still, this means that you'd ultimately be having the editor trigger changes in the GDScript's code. Or forcing the GDScript to have multiple data points available for the editor to configure and leave some of it unused and hidden if it pertains to the other option (ancestor vs. descendant).

Edit: Also, for generic configuration warnings not associated with a particular script implementation, see #922 which I just opened recently.

YuriSizov commented 4 years ago

I just wanted to point out that a syntax like that

@connect(area, "body_entered")
func some_function():
    pass

would allow for signals connected via GUI to actually have their connect code put in the script. Currently it is possible to have a script file that doesn't tell the full picture without reliance on the editor UI. This would allow for consistency between a visual creation of a connection and a code-based one without any need to modify the _ready function.

matthew1006 commented 4 years ago

I have a few suggestions and questions:

Annotation blocks

Instead of writing this

@export var x
@export var y
@export var z

@onready var _on_ready_var_1
@onready var _on_ready_var_2
ect...

we could write this

@export:
    var x
    var y
    var z

@onready:
    var _on_ready_var_1
    var _on_ready_var_2

This would clean up a lot of variable declarations early on in a script and encourage grouping of variables/functions/etc. An example of this kind of functionality is present in D

@hint_* annotations

Instead of having many different @export* annotations, I suggest splitting them into separate @hint* annotations.

@export_range(0, 10) var x

becomes

@export @hint_range(0, 10) var x

This separates the concepts of exporting variables and export hints and would also act as a work around to an issue with my annotation block suggestion.

@export:
    var x
    var y
    @hint_range(-10, 10, 0.1) var x

@version annotation

I have previously suggested in issue #26649 for the addition of a version keyword to allow for conditional parsing of code based on the feature fags of the export template used (similar to the version keyword in D). Could this kind of functionality be done with an annotation? e.g.

@version("Windows") var file_path = "C:\\Users\\me\\files\\file.txt"
@version("x11") var file_path = "/home/me/files/file"

Would this be possible? Would it result in a name conflict because both variables have the same name? It shouldn't if this were done at parse time because one or both of the lines would be skipped.

Anyway, those are my ideas. What do you think?

willnationsdev commented 4 years ago

@matthew1006

I like the idea of being able to have @export: create a scope of auto-exported variables. And then being able to do @hint_* annotations within that makes sense. However, I would still want to make sure it also supports the standard @export_range() so that people aren't forced to stuff things into a new block when it isn't necessary (or if they just have all different hint annotations that they would be using anyway, in which case, using an @export block wouldn't make much of a difference).

+1 for the version / feature flags idea. That'd definitely be cool to have. I can already think of a game I worked on where that would've been useful since we had stuff that required different logic depending on whether you were on Windows versus Linux (exactly like your circumstance, except it wasn't about file paths).

jknightdoeswork commented 4 years ago

@matthew1006

I think @platform might be a more appropriate keyword than @version.

matthew1006 commented 4 years ago

@willnationsdev

File paths were probably a bad example. In fact any variable like that is probably a bad example as they can be set in the project settings.

My real world example where @version/@platform would have been handy was several projects using a custom module for interfacing Godot 2 with our company's custom software/hardware (Note: I didn't write this module). The stuff being interfaced with wasn't present in the development environment so the module would fail to initialise and crash the game but I had to work with what was given to me so I created a class in GDScript that masked the module. This class needed to be commented out before exporting or things wouldn't work. I can't count how many times I exported with that class still in place. Since Godot 3.0 I've replace that module with a GDNative library but the idea still stuck with me.

@jknightdoeswork

I agree, @platfrom does seem like a better name for it than @version although maybe something more generic might be better since it would probably work with all feature tags, including user defined ones in the export settings. Something like @feature would make more sense based on how it would work but I don't think that it would be intuitive or descriptive enough and I would rather it be short; preferably one word.

omicron321 commented 4 years ago

have you considered following language standards like Ecmascript, python standard or else ? because, from what i understand, gdscript was introduced to solve implementation/integration issues, but not to solve syntaxical/lexical issues.

note: this question is not specific to this issue edit: i.e. related to all other new language feature as well

jknightdoeswork commented 4 years ago

@Omicron666 What is your suggestion? Having a high level philosophical reason is fine, but the primary thing we are doing here is making real, concrete suggestions.

omicron321 commented 4 years ago

@Omicron666 What is your suggestion? Having a high level philosophical reason is fine, but the primary thing we are doing here is making real, concrete suggestions.

checking existing standards is a concrete process, when you start introducing new things like getsetter and many more things to come, in your own scripting language

Lucrecious commented 4 years ago

Suggestion for an annotation type for Godot 4.0 - allow for tool mode to be in exclusionary or inclusive modes.

The new change would keep this functionality working just fine.

@tool
export(int) var x := setget _x_set, _x_get
export(int) var y := setget _y_set, _y_get
@tool_exclude

# Unless specified all field and methods are not run in the editor.
# Only x getters/setters can be run in editor.
@tool(on)
export(int) var x := setget _x_set, _x_get

export(int) var y := setget _y_set, _y_get
@tool_include

# Unless specified all field and methods are run in the editor.
# Only y getters/setters can be run in editor.
@tool(off)
export(int) var x := setget _x_set, _x_get

export(int) var y := setget _y_set, _y_get

This would be really helpful with plugin creation, since most of the time, you just want one or two methods to be accessible in the editor (usually just export variables), the rest stills runs but can't be directly accessed. Similar to the remote* keywords.

@tool_exclude would also automatically set all process events to false unless otherwise specified with the annotation.

Thoughts?

vnen commented 4 years ago

@Omicron666

have you considered following language standards like Ecmascript, python standard or else ? because, from what i understand, gdscript was introduced to solve implementation/integration issues, but not to solve syntaxical/lexical issues.

note: this question is not specific to this issue edit: i.e. related to all other new language feature as well

Well, if we were to follow another language standard, it would be better to go the extra mile to bind the language in some way (which has proven to cause issues of various kinds). I'm not gonna make a hand-made implementation of JavaScript, which will likely be 100s of times slower than common implementations (v8, SpiderMonkey) and we will have to 1) make it work within Godot structure, 2) update every time the spec updates, 3) make sure it works with the edge case from some obscure library that some user is bound to try to use.

The fact that we control GDScript grammar allows us to integrate features that make sense for Godot (like yield/await and the $ shorthand), which would be unfeasible when using standard implementations. And implementing our version of ECMAScript or Python would be much more difficult than maintaining GDScript.

vnen commented 4 years ago

@Lucrecious you are asking for a new feature, which is independent of annotations (sure you can use the annotation syntax but that doesn't help backend code needed for it to work). So you should open a new proposal.

winteraa commented 4 years ago

would it be easily possible to add a convenience tweak to the if obj is Class parts? it currently is possible to do

if body is Player:
    var player := body as Player
    player.hurt(10)

but what would be cool if one could define a variable for that scope that has that asked type right away

if body is Player player:
    player.hurt(10)

I use it fairly often and do miss this option from C#.

EDIT: would be even cooler if this worked with traits too if those are getting into GDScript.

dalexeev commented 4 years ago

You can do this:

if body is Player:
    body.hurt(10)

or this:

var player := body as Player
if player:
    player.hurt(10)

GDScript isn't C/C++/C#.

winteraa commented 4 years ago

@dalexeev the first option does not give me auto completion on body for Player and the second option is just as verbose (but less readable) than what I had written above how it currently looks in GDScript.

I get that GDScript is not C/C#, but that's no reason not to improve it's workflow. 😕

dalexeev commented 4 years ago

the first option does not give me auto completion

It works for me:

200702-1

Godot 3.2.2. What is your version?

winteraa commented 4 years ago

that.... is interesting. 🤔

(Still, the variable is called body and the information that this is indeed a player can get lost if that if block is a bit larger. No precise naming, hence less readable code)

dalexeev commented 4 years ago

@winteraa Perhaps this is because the condition contains an additional check.

200702-1

In the case of and, this is a bug. In the case of or - this is the correct behavior, because the compiler cannot be sure of the type of the variable. However, this does not apply to annotations in GDScript.

I get that GDScript is not C/C#, but that's no reason not to improve it's workflow.

I meant the type name syntax. GDScript uses the name: type syntax.

Lucrecious commented 4 years ago

Maybe something like this should be allowed in GDScript.

if var player = object as Player:
    player.take_damage(100)
bojidar-bg commented 4 years ago

would it be easily possible to add a convenience tweak to the if obj is Class parts?

I'm pretty sure this is not on-topic on this proposal. Maybe move the discussion to a new proposal?

winteraa commented 4 years ago

Oh ups. For some reason I was certain this is kind of a general GDScript 2.0 thread. Apologies.

aaronfranke commented 4 years ago

For anyone who would like to test out the new annotation system, it has been implemented in this PR and is now available in the current master branch. You can either compile the engine to test it, or you can use iFire's Stern Flowers build.

Important note: The master branch is still unstable and has many bugs, so don't try to open any existing projects with it.

vnen commented 4 years ago

This is already implemented in https://github.com/godotengine/godot/pull/40598 so it can be closed now.

Any suggestion for improvement/change should be done as a new proposal.

h0lley commented 2 years ago

it's probably way too late for that, though I want to mention it none the less:

has it ever been considered to use @expose over @export as a keyword to expose variables to the inspector?

I think there's a couple of downsides in terms of ambiguity to the export keyword. since there's also the export in terms of exporting the project, looking up documentation can be cumbersome. I've often found myself on the wrong docs page or having to sift through search results. it can also be confusing when asking questions about it. for instance, which kind of export is being referred to frequently needs to be clarified in Discord help channels.

and lastly, I think expose just makes more sense in describing what the feature does.

just a thought.

YuriSizov commented 2 years ago

It's not all that the keyword does, though. It also makes that field serializable when you save resources using that script. That's not just scenes, that's also resources. And you can expose a property to the inspector without making it serializable too, but not with the keyword. So whether the export term is bad, expose is technically even less correct.

Calamander commented 2 years ago

Additionally, we can add special annotations for categories and groups:

@export_category("category")
@export_group("group", "prefix") # All variables with name starting with "prefix" are added to the group.

What happened with these though? Was it implemented in some way?

YuriSizov commented 2 years ago

Additionally, we can add special annotations for categories and groups:

@export_category("category")
@export_group("group", "prefix") # All variables with name starting with "prefix" are added to the group.

What happened with these though? Was it implemented in some way?

Not yet, it is tracked in https://github.com/godotengine/godot-proposals/issues/1255