Skip to content

blocks: Add groups option block extension #240

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

Merged
merged 2 commits into from
Oct 3, 2024
Merged

Conversation

dbnicholson
Copy link
Member

Several blocks work with node groups. Rather than having the user enter the group, offer the current groups as options. This is trickier than expected since Godot offers no API to get the current groups. Finding them involves 2 parts:

  • Get scene local groups by calling get_groups() on each node in the scene.

  • Get project global groups (starting in 4.3) by getting the global_group values in the project settings.

Monitoring for changes to the global groups is possible by listening for project settings changes. Monitoring for local group changes is not possible since the only events that occur are internal to Godot and not available in GDScript.

https://phabricator.endlessm.com/T35647

This is a naive implementation. The groups are specific to the scene and project. Rather than have each Block maintain its own list, it should be gathered in the BlockCode node or even the BlockCodePlugin. I spent far too long trying to make that work well, but I decided to just put up this simple implementation now.

As noted above, the biggest problem is that the scene local groups are not monitored. So, if you add a node to a group, the Blocks won't be updated with the new group. Also, since the add_to_group blocks only offer existing groups, it takes away the means of creating scene local groups dynamically. That may not be that bad, though, since that would only happen at runtime and you wouldn't be able to query for the presence of the group.

Copy link
Contributor

@starnight starnight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

However, global_group is supported since Godot 4.3, should we set the supported Godot to 4.3?

@dbnicholson
Copy link
Member Author

I now noticed that if I change the edited scene, the groups shown in the picker block won't change until I start dragging it out of the picker. I think I have to watch for the context node changing and emit BlockExtension.changed.

@dylanmccall
Copy link
Contributor

LGTM!

However, global_group is supported since Godot 4.3, should we set the supported Godot to 4.3?

I think we're okay there. I tested with Godot 4.2.2 to be sure, and it still works as expected except for an unrelated issue with simple_spawner.gd. Groups defined in the scene file still appear in the block, although global groups are pretty helpful in this case.

@dbnicholson
Copy link
Member Author

LGTM!
However, global_group is supported since Godot 4.3, should we set the supported Godot to 4.3?

I think we're okay there. I tested with Godot 4.2.2 to be sure, and it still works as expected except for an unrelated issue with simple_spawner.gd. Groups defined in the scene file still appear in the block, although global groups are pretty helpful in this case.

Indeed. Since the implementation is just to scrape them out of the ProjectSettings properties, all that will happen on 4.2 is that there are never global groups.

@dbnicholson
Copy link
Member Author

I now noticed that if I change the edited scene, the groups shown in the picker block won't change until I start dragging it out of the picker. I think I have to watch for the context node changing and emit BlockExtension.changed.

Actually, this is an existing problem in the picker. When the context has changed and blocks are being reused, the context node change needs to be passed down to the block extension. I think I have something working.

In the category display, blocks reused when switching the current
BlockCode node. When that happens, the BlockExtension needs to have its
context update so that it can provide options for the current BlockCode
node.

https://phabricator.endlessm.com/T35647
Several blocks work with node groups. Rather than having the user enter
the group, offer the current groups as options. This is trickier than
expected since Godot offers no API to get the current groups. Finding
them involves 2 parts:

* Get scene local groups by calling get_groups() on each node in the
  scene.

* Get project global groups (starting in 4.3) by getting the
  `global_group` values in the project settings.

Monitoring for changes to the global groups is possible by listening for
project settings changes. Monitoring for local group changes is not
possible since the only events that occur are internal to Godot and not
available in GDScript.

https://phabricator.endlessm.com/T35647
@dbnicholson
Copy link
Member Author

I changed a few things:

  • Groups from all children of the edited scene root are included. Previously only nodes in the scene were considered, but that doesn't match the Groups Editor, which shows groups from child scenes.
  • When the extension's context node changes, its changed signal is emitted so that consumers will refresh the defaults based on the node's scene.
  • I added a commit that updates the extension's context node from the picker since it reuses blocks and the options wouldn't be updated.

Comment on lines +92 to +94
func refresh_context():
if _context and _block_extension:
_block_extension.context_node = _context.parent_node
Copy link
Contributor

@dylanmccall dylanmccall Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a signal handler for _context.changed, instead, or does that do something weird? (Oh noo so many changed signals!). Alternatively I don't mind if we move this stuff over to BlockExtension itself. For BlockExtension I didn't want to add anything more than that one context_node property until it was needed, but as long as individual extensions aren't poking at BlockEditorContext it's fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial instinct, but that's not what we want. If the BlockExtension watched for context changes, then the options would change every time you changed the block code node. We only want to do this in the picker where the blocks are reused for all contexts. I presume that's why you passed in the context node to BlockExtension instead of having it just grab the current context.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yeah, I see where you're coming from there. Thanks for the explanation!

@dylanmccall
Copy link
Contributor

This looks good to me! I'll merge it now :)

@dylanmccall dylanmccall merged commit 3d86f47 into main Oct 3, 2024
3 checks passed
@dylanmccall dylanmccall deleted the T35647-group-option branch October 3, 2024 04:00
Comment on lines +20 to +24
display_template = "is in group {group: NIL}"
code_template = "is_in_group(\\\"{group}\\\")"
defaults = {
"group": SubResource("Resource_d0v0d")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, I completely missed this change! We shouldn't have needed to change group to a NIL :( I'll make a PR fixing this in a moment.

Copy link
Contributor

@dylanmccall dylanmccall Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To explain what's going on, previously we needed to do that for options lists because the value was reproduced verbatim in this case, but now it can be treated as a string and auto-quoted just like any other string parameter. The old behaviour was used in places, and that can be achieved by using something like {{param}} in the code template to substitute just the raw value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the change that made that different? I've been basing my work on 41afa00 where several string types changed to NIL.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see what happened there! Some crossed wires :) I think I switched them to NIL to keep the previous behaviour of not being able to snap weird things to options lists, but then #219 happened around the same time so it was kind of moot, and the parameter type is indeed pretty irrelevant to anything. The only thing that's important is we don't need to do anything special to quote the strings here.

The thing that caused the behaviour change in that commit is where we remove the special case for TYPE_OBJECT in raw_input_to_code_string (seeing as option values are no longer OptionData objects).

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

Successfully merging this pull request may close these issues.

3 participants