Skip to content
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

Add a group_connect() method to monitor signals from any nodes within a group #5466

Open
skysphr opened this issue Sep 21, 2022 · 3 comments

Comments

@skysphr
Copy link

skysphr commented Sep 21, 2022

Describe the project you are working on

A project with several nodes instanced at runtime.

Describe the problem or limitation you are having in your project

Often times, the following situation occurs: A controller node creates child nodes, and connects some of their signals to itself, so that it reacts to their behaviour. However some other entity might also create the same class of child nodes, which need to be connected to the controller node. Besides the duplication of connect calls, if said entity does not have a direct reference to the controller node, it needs to somehow find it, resulting in potentially hackish and unclean solutions.

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

By leveraging the functionality of groups, a function such as group_connect(group, signal, target, method, binds, flags) could be created, which allows target to monitor the emission of signal by any node within group. This way, the circumstances of nodes' creation are irrelevant, as by being part of the group, they will be automatically connected to the appropriate listener.

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

Workflow would be almost identical to connect(), except it would be necessary to pass a reference to the node that is emitting the signal:

# Controller
var stats_bullets_ricochet: int = 0
func _ready():
    group_connect("bullets", "ricochet", self, "bullet_ricochet")
func bullet_ricochet(_bullet):
    stats_bullets_ricochet += 1

# no additional code needs to be added to nodes belonging to group "bullets", since they should not be aware of the overall stats system.

This will not allow checking for the existence of a signal when connecting, as groups may contain diverse nodes, each with its own set of signals. On a technical note, this means that the hook which implements this (most likely within scene/main/scene_tree.cpp) will have to check whether a specific signal exists or not prior to connecting it.

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

Workarounds are feasible, but inelegant:

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

It seems like a functionality that complements SceneTree's call_group() - using groups as an abstraction layer towards interacting with individual nodes.

@Calinou Calinou changed the title Add a group_connect() function to monitor signals from any nodes within a group. Add a group_connect() method to monitor signals from any nodes within a group Sep 21, 2022
@n-gram-hub

This comment was marked as off-topic.

@rambda
Copy link

rambda commented Sep 21, 2023

related:
#766
#627

Also, according to
godotengine/godot#57541 (comment)

  • This use case can be addressed using the SceneTree.node_added signal, but this signal is emitted for every single node added to the scene tree - it has a huge performance cost and is only really relevant for debugging / editor tools (that performance cost is only paid once a callback is connected to the signal - but that's what would be needed here).

@CyberSkull
Copy link
Contributor

I'd like to expand on this proposal a bit with the other signal methods.

group_disconnect(group, signal)

If we can listen to a group, we should also be able to disconnect.

group_get_connections(group)

Get all the connections in the group element.

group_is_connected(group, signal)

This is is_connected applied to the group level. Returns TRUE if a given signal is applied to the group, FALSE if not.

group_get_connected(group, signal)

This is is_connected applied to the member level. Returns a list of members of the group that are connected to the given signal, or if no signal is provided, then just list of all members that are connected to anything. This could be done by the user by iterating through all members of a group and testing with is_connected(signal), but could be much faster if instead the group keeps a list of all members with connections.

group_get_disconnected(group, signal)

The inverse of group_get_connected. This returns members of the group not connected to the signal, or without the signal argument returns all members not connected to anything. This could be done by the user by iterating through all members of a group and testing with is_connected(signal), but could be much faster if instead the group keeps a list of all members without connections.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants