Skip to content

Support @export_node_path attribute#1620

Open
tuto193 wants to merge 1 commit into
godot-rust:masterfrom
tuto193:implement_export_node_path
Open

Support @export_node_path attribute#1620
tuto193 wants to merge 1 commit into
godot-rust:masterfrom
tuto193:implement_export_node_path

Conversation

@tuto193
Copy link
Copy Markdown
Contributor

@tuto193 tuto193 commented May 27, 2026

Added support for export_node_path annotation (Completes #1128)

Adds the ability to annotate fields with @export_node_path:

#[derive(GodotClass)]
#[class(base=Node2D)]
struct SomeClass {
    /// Equivalent to:
    /// ```gdscript
    /// @export_node_path("Button", "TouchScreenButton") var some_button: NodePath
    /// ```
    #[export(node_path = ("Button", "TouchScreenButton"))]
    some_button: NodePath,

    base: Base<Node2D>
}

Note: I didn't find the exact PR where export_node_path was introduced to GDScript upstream, so if it's needed let me know, and I will dig deeper. Otherwise let me know if I should adjust any of these changes.

Couldn't have done it without other PRs like those of @Swivelgames on #1183. It really made it a lot easier to have that as reference, so thanks to them a lot!

@GodotRust
Copy link
Copy Markdown

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1620

@TitanNano TitanNano added feature Adds functionality to the library c: register Register classes, functions and other symbols to GDScript labels May 27, 2026
Copy link
Copy Markdown
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

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

Thanks a lot, this is a nice addition! 👍

PR looks mostly good, added some comments on smaller parts.

Comment thread itest/rust/build.rs Outdated
Comment thread itest/rust/build.rs
Comment thread itest/rust/build.rs Outdated
Comment on lines +190 to +198
// Detect parenthesized list: node_path = ("Button", "TouchScreenButton")
if tokens.len() == 1
&& let TokenTree::Group(group) = &tokens[0]
&& group.delimiter() == Delimiter::Parenthesis
{
let list_parser = ListParser::new_from_tree(
tokens.into_iter().next().unwrap(),
Delimiter::Parenthesis,
)?;
Copy link
Copy Markdown
Member

@Bromeon Bromeon May 28, 2026

Choose a reason for hiding this comment

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

Is this hand-parsing of tokens really needed before you pass it to ListParser?

How do other godot-rust proc-macro APIs that deal with lists do it?

Copy link
Copy Markdown
Contributor Author

@tuto193 tuto193 May 28, 2026

Choose a reason for hiding this comment

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

I've been breaking my head a bit with this today. I'm not using the handle_list(), since I thought, we would allow
[Option 1]

  // ...
  #[export(node_path = "Class1")] // (not a list)
  // ...

as a valid case.

Otherwise I get the error:

...
error: expected list of items
    --> /Users/carlosfernandez/Git/gdext/target/debug/build/itest-c56514b7f101be8d/out/gen_ffi.rs:2412:30
     |
2412 |         #[export(node_path = "Button")]
     |                              ^^^^^^^^
...

If we were to parse this only as a list, the above wouldn't work, and instead we would need to only allow:
[Option 2]

// ..
  #[export(node_path = ("Class1"))]. // (list with only one entry)
// ...
}

I'm removing the [Option 1] for now though, since it's more in line with what is done in GDScript.

Copy link
Copy Markdown
Member

@Bromeon Bromeon May 28, 2026

Choose a reason for hiding this comment

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

Do we need both? I guess the one with 1 argument is the common one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I left [Option 2] (#[export(node_path = ("Class1", ...))]) in. I think it's indeed more in line with what users could use, plus allows for more freedom/flexibility. Also, I will mark this as resolved unless you (or anyone else) is really against this, although I personally like the freedom plus it's the code is as easy to maintain as the other handle_list() branches :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please don't resolve conversations you still expect me to read, it's rather hard to locate them 🙂

But sounds good for now, we can always add the other syntax later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My bad 😅.

So I will leave it as is :)

Comment thread godot-macros/src/class/data_models/field_export.rs
@tuto193 tuto193 force-pushed the implement_export_node_path branch from e2d03ab to 86b6b08 Compare May 28, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: register Register classes, functions and other symbols to GDScript feature Adds functionality to the library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants