-
-
Notifications
You must be signed in to change notification settings - Fork 198
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
Grouping Exported Properties in the Editor #226
Comments
Personally I'd prefer the structs deriving ExportGroup approach, if they could additionally be used for making non-grouped it would also give us a way to reuse exports between different classes that have the same exported variables but dont necessarily want to group them. i think allowing you to override the name at the usage site would also be good. |
Another thing to consider is subgroups. A group can have subgroups, but subgroups can't have subgroups. |
Not exactly sure if this would work syntactically, but I did subconciously end up trying this while i was trying to blindly figure out whenever #[export_group("Settings")] {
#[export] volume: f32,
#[export] pitch: f32
} I'm not sure whenever this could work inside a struct declaration (I seem to get syntax errors trying it out) but I have used this type of syntax before inside function bodies (i've used it with |
What about doing it as a trait? The macro-based APIs could also be provided, but a trait-based API could be a little nicer for more complex applications. Here's a back-of-the-napkin design for what it could look like. impl EditorRepr for MyClass {
fn repr(&self, editor_stuff: EditorStuff) -> EditorStuff {
editor_stuff
.default(self.float) // do nothing fancy for .default()
.group( // provide a label and a chain of parameters
"Several things"
|ed_stuff| {
ed_stuff
.different_repr(self.happiness)
.default(self.position)
.done()
})
.done()
}
} |
I was thinking that it'd be nice if the |
This is anyway planned as part of #4, but it would need the whole builder API infrastructure, which is not yet in place. Eventually the idea is that the proc-macro is just a frontend that uses the builders in the backend. Currently the development is quite usage-driven (building the proc-macro API first). |
For a workaround, see also Discord. |
Hey, thanks for the information that there is a workaround! Is it possible to copy-paste the relevant content into this GitHub thread if the content is in a form where it could easily be reproduced here? If so, that would be greatly appreciated as we cannot access Discord from within company networks and on company devices due to a network blocklist. As a positive side-effect, that would also help searchability of the relevant topics here on the site :) |
I don't want to copy the original picture without the author's consent, but to sum up: You can emulate the workaround using dummy properties (whose value, here // Properties outside a group.
#[export]
level_name: GString,
// First group.
#[var(usage_flags = [GROUP, EDITOR, READ_ONLY])
configurations: u32,
#[export(file = "*.toml")]
map_config_file: GString,
#[export(file = "*.toml")]
enemy_config_file: GString,
// Second group.
#[var(usage_flags = [GROUP, EDITOR, READ_ONLY])
world_parameters: u32,
#[export]
world_size: Vector2i,
#[export]
gravity: f32,
#[export]
particles: Option<Gd<GpuParticles2D>>, It's worth noting that this relies on the order of fields being registered in the order of declaration, which isn't something we guarantee (while I don't plan on changing it, there may be reasons in the future). And probably some other implementation details... So use at your own risk 🙂 |
Out of curiosity, are you using godot-rust at work? Are you allowed to say more about it (can also be non-publicly)? |
Motivation
For quality of life, it is sometimes advisable to group related properties in the editor. This is already possible with GDScript, and used extensively by the built-in node types in Godot.
Examples, and a first flawed attempt at introducing this to gdext can be seen in #214.
On Syntax
There are different proposals for syntax, each of which have their unique pros and cons. Some of these originate from the same issue in gdnative, godot-rust/gdnative#855.
Goals
#[export_group]
This was originally proposed in #214, but fails to achieve the first goal, as field naming and field ordering are mandated by group membership.
Marker Fields
Originally proposed in godot-rust/gdnative#855 (comment), this has the same downside as the above, but with a different syntax.
Separate Structs Deriving
ExportGroup
This would introduce a new derivable trait
ExportGroup
which would allow use as a property type. The exported fields of the struct deriving this trait would be available as grouped properties.A question arising here is whether to allow overriding the name and prefix at the site of usage, which would enable uses such as
which enables structs to be re-used as custom (domain specific) property types which are reusable over many structs.
Use Marker Structs
Similar to the previous approach, but require fields to be kept on the struct deriving
GodotClass
.Loses the reusability option of the previous approach, but more close to how the data would be laid out in GDScript.
String Based Groups
Like the previous approach, but instead of marker structs it uses string-based group identifiers which do not actually exist as Rust items.
Explicit Property Paths
I do not know much about gdnative, but this seems to be a way to achieve property groups there:
#[property(path = "foo/bar")]
creates a property available as
bar
in a groupfoo
. This has the advantage of decoupling the notion of groups from Rust entirely, and making it purely aesthetic, but when reusability of domain-specific editor-editable types is a concern, this may actually be a downside.The text was updated successfully, but these errors were encountered: