-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GDScript: Declarative signal connections, when $Button.pressed:
#7112
Comments
I haven't looked at your implementation, but from your description it appears that the special case of Something that could both free language space and solve that mentioned issue is to require
You do:
And so there would be no issue with I'm not sure how to feel about not using the keyword By the way, in general I'm in favor of declarative signal connections. A precedent that I like is VB.NET handle clauses. |
@theraot :O thank you for the quick feedback,
i don't see why requiring this would solve that issue, if you understand that 'notified' has a special meaning here, and know how to refer to it another way, 'self.notified', that shouldn't be a problem (as long as no new special modifiers like it are introduced) i did consider adding a function |
Right, so It is what I'd call a contextual keyword (a non reserved word that has an special meaning in a particular context), which terminology from C#. What I was thinking is that requiring Anyway, it is just my take. |
your take is valuable! |
While this could offer some convenience, I'm unsure how flexible it can be and how to handle a number of things like binds Other than the specified case of convenience with lambdas I don't see much of an inconvenience in just the current connect approach, and I'm struggling to see the justification in adding quite a significant new feature and syntax, and significant complexity to the parser and compiler For the I'd argue that while this could be convenient, it's so easy to work around that I don't feel it's worth the effort and complexity, there's also threading to be aware of, depending on when connecting and disconnecting happens etc. |
I can think of a solution for signals with arguments.
For binds we can do it the same way as current approach.
I hope I am clear. |
Wow this is a good suggestion. This could also be done at top level and we could get rid the difference between things like ready and _ready
Note that code is just a example of how signals and callbacks could work I am not suggesting that you invoke ready from ready |
@AThousandShips yes, this is easy to work around, i developed this while 4.0 was in development, it was meant to be submitted while gdscript 2.0 was in flux. i almost did before firefox ate my proposal (should have used google docs)
if you mean binding arguments to the end of a function object, you would just call the method in the body extends RigidBody2D
var player_id: int
when body_entered(body):
do_action_player(body, player_id) if you mean unbinding signal arguments, you just leave them unused: when body_entered(_body):
do_action_player(player_id) or leave out the parameter list: when body_entered:
do_action_player(player_id)
connecting happens just after |
Threading is a major concern with signals unless you're careful, this would risk worsening it by doing connecting in places that aren't safe:
Also keep in mind that if it's at |
:o wow thank you ! this is helpful, i didn't know this |
Surely these could be fixed? |
An alternative to a new keyword other than func is an annotation. @when(ready)
func _handle_ready():
print("I'mmmm ready!!!!") This would also convey that you can call this function without the signal being emitted. @when(hit)
@when(died)
func emit_noise():
print("Eugh!") Signals with arguments: @onready_when($GreetButton.toggled)
func handleHello (button_pressed: bool):
if button_pressed:
print("Hello!")
else:
print("Bye!") Add bindings to specific connections... @when($Button1.pressed, [$Button1])
@when($Button2.pressed, [$Button2])
func handleBtnPressed(button: Button):
print(button.text, " was pressed") For only connecting signals when they're emitted with a certain condition, I'd propose a new signal construction method that emits when the og signal emits with specific arguments. signal hp_changed(new_hp: int)
@when(hp_changed.emitted_with([0]))
func handle_died():
print("u ded")
@when(notified.emitted_with([NOTIFICATION_PREDELETE]))
func handle_about_to_delete():
print("so long") I do like the clean look of the original proposal, this mode here with @ looks rather clunky. But I do think it's more powerful, and less intrusive regarding new syntax, so easier to learn and implement. The fragments required for this implementation ( That is to say, there's many ways of implementing this if syntax is a problem -- I'm super on board with the idea of declarative connections like these. |
Describe the project you are working on
a 2D physics based space ship commander, with a decent amount of GUIs
Describe the problem or limitation you are having in your project
Connecting signals is almost always a bit messy, even if your logic is simple.
Option A:
Its a lambda, which is nice, but its in a function call which is in a function definition.
It has to get thrown in next to your other onready setup code.
The flags just kinda hang there and dont look right when the lambda is too big.
Option B:
Again not horrible, but I have to keep all the connection initialization code separate from what it does, and make sure I put that info in the function name itself, typing it again.
Changing any of that info means the function name should also change.
It also looks like c++ :(
Option C:
Cleanest looking one, but,,,
Is this connected in the .tscn file? Maybe.
I have to open the scene to see the icon next to the function.
Clicking on that icon does not tell me if its a oneshot or deferred connection.
I may have just not added '_once' to the default function name because it doesn't affect its behavior. So does it only emit once?
If i want to know, I can't find that info unless I go to the the node tab, signals page, right click on the connection, click edit... then I can see the checked box next to oneshot.
This could obviously be changed to make to information more accessible, but why should I even put the connection in the scene file in the first place?? i want to keep that info near the code being run
I don't use this one anymore.
My last point is that, (if you aren't using the lambda option), when you extend a script you can accidentally and unknowingly override a function with the same name in the super class, making for a very bad bug.
They may be minor gripes except for the last, but these are all the problems ive personally had with connecting to signals in godot.
there is another problem introduced in godot 4 that i've found this proposal 'solves':
the
_ready
,_process
,_physics_process
and functions all used to be called at all levels starting from the highest ancestor, the Object class, just like notifications.but because the behavior was unexpected, it was removed in favor of just requiring a call to
super._process()
, for example.its understandable, but unfortunate, because the old beavior was so useful, and once you learned it, very convenient.
now, if you forget to make the call to
super._process
, you get a very silent bug. not ideal.if you remove the base class
func _process
, you have to change all inherited classes that callsuper._process
. :/ (also the error only happens at runtime :///)the solution to this right now is to override
_notification
which is also a function, but does get called on all levels. it is the only that it makes sense this rule would apply toit requires a very 'C' like syntax
but you don't get the nice code organization you get from
func _process(delta):
you either have to throw alot of code into_notification
, or make a function identical to_ready
,_process
and_physics process
it also needs a call to
set_process(true)
for it to work, but this proposal can't do anything about thatDescribe the feature / enhancement and how it helps to overcome the problem or limitation
I'm proposing a new declarative syntax for connections to signals, to be able to describe a connection directly to the compiler
idea taken from here: #828 (comment)
and here: #2946
this is nice. and generic. and solves all the problems i mentioned:
when gui_input:
)when ready:
statements), better code organization (and they are called in the correct order)when [ready, $Button.pressed]:
andwhen notified [NOTIFICATION_READY, NOTIFICATION_PROCESS]
). it accepts an expression that evaluates to either a Signal or an array of Signals at runtimeif you understand signals and connections in gdscript you can easily understand what this new syntax will do.
an '@onready' annotation is required when using the
$Node
syntax. it could be detected and enable automatically, but i favor the extra information and consistency, even if it is boilerplatebinding is not here, because it wouldn't make sense with the unnamed functions
this
when notified ...
stuff is not the main syntax syntax being proposed, but it fits well along side it, and it's useful in the same ways.it would also provide a way to convert 3.x projects that use
func _process
while keeping its meaning the same, a big problem for me when i converted 2 of my projects. bit late tho :P, 4.0 is already outstill ive split it into 2 branches. https://github.com/rune-scape/godot/tree/rune-when-decl and https://github.com/rune-scape/godot/tree/rune-when-notified
most importantly, all these blocks of code (
when <signal>
andwhen notified
) get called in the default notification order, starting from the highest ancestor (the Object class), first declaration to last (if there are multiple in the same script)this means that
when ready:
works just likefunc _ready():
in godot 3.x with the benefit of being able to declare multiple blocks with the same signalDescribe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
there is a working version at https://github.com/rune-scape/godot/tree/rune-when-decl branched from 4.0.3-stable
I have been using this in the game i am working on for months now.
i've fixed bugs as they come up, there's just a couple small highlighting bugs i know of currently
i've had no problems so far teaching the syntax to the other programmers, one new to gdscript, one familiar
sdf-gen2.zip is a small gui project i made in an hour recently to create sdf textures (shader credit: queenofsquiggles)
If this enhancement will not be used often, can it be worked around with a few lines of script?
yes, theres nothing you can do with this feature that wasn't possible before, it simply adds a generic clean syntax for declaring connections that is very useful in GUI design
the only really new mechanic this brings is when declarations annotated with
@onready
get automatically refreshed when ready is re-emittedIs there a reason why this should be core and not an add-on in the asset library?
not possible with an addon
The text was updated successfully, but these errors were encountered: