Skip to content

bsn: Allow passing EntityTemplate into scene functions and Scene Component @props#24174

Open
laundmo wants to merge 11 commits into
bevyengine:mainfrom
laundmo:bsn-entity-template-props
Open

bsn: Allow passing EntityTemplate into scene functions and Scene Component @props#24174
laundmo wants to merge 11 commits into
bevyengine:mainfrom
laundmo:bsn-entity-template-props

Conversation

@laundmo
Copy link
Copy Markdown
Contributor

@laundmo laundmo commented May 7, 2026

Objective

Prior PR, see for somewhat outdated description regarding global entity indices:

Currently, its not possible to pass an entity name reference to a scene function (-> impl Scene) or a Scene Component @props

This PR enables this, based on #24173 by allowing easy passing on EntityTemplate:

 #[derive(Component, FromTemplate)]
struct Reference(Entity);
fn widget(entity: EntityTemplate) -> impl Scene {
    bsn! {
        Reference(entity)
    }
}
bsn! {
    #Name
    Children [
        :widget(#Name)
    ]
};

Solution

I tried this before in main...laundmo:bevy:bsn-hacky-name-passing but had to compromise so it was obvious it wasn't going to ever be merged. After talking with @cart on discord about this around here i went with attempting the global entitiy indices, which resulted in #24173 (all of those changes also being part of this PR)

Testing

  • cargo test -p bevy_scene --lib with new tests for this feature
  • cargo run --example feathers_gallery --features=bevy_feathers still works the same
  • new basic benchmark for name resolution doesn't show any major regression

Showcase

In a bsn! macro, its now possible to pass a #Name entity reference into another Scene as an EntityTemplate.

To use this, write a scene function (or scene component prop) which takes EntityTemplate. Components which contain an Entity and implement FromTemplate can directly take in EntityTemplate

#[derive(Component, FromTemplate)]
struct FooBar(Entity);
        
fn foo(entity: EntityTemplate) -> impl Scene {
    bsn! {
        Reference(entity)
    }
}

Now, theres multiple ways to pass in an EntityTemplate like this, heres some examples:

bsn! {
	#SomeName
    Children [
        :foo(#SomeName),
		foo(#SomeName)
		foo(#{some_entity_value}) // some_entity_value: any expression evaluating to Entity, most likely a variable
		:Bar {
		  @myprop: #SomeName
		}
    ]
}

BsnEntry::SceneFn(BsnSceneFn { path, args })
} else {
BsnEntry::SceneExpression(quote! {#path})
if forked.peek(Paren) {
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.

This is "broken", as it will leave the input tokens in an unparsed state. input is the source of truth, forked should only be for "explorations" that are later repeated in input.

The if let Ok(args) = input.parse() pattern results in input's state being "unrecoverable", as we have no clue where it failed / what tokens remain.

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 dont think avoiding fork altogether is reasonably possible.

What i'm doing is pretty close to what syn documentation on speculative parsing recommends, but not quite. In my latest commit, i've swapped which branch uses the fork so that its used first to try and parse BsnSceneArgs, and used input.advance_to(&forked); to "catch up" input to the state of the forked stream.
This should now keep it in sync.

I dont think it would have been an issue either way, but this is definitely nicer.

Comment thread crates/bevy_ecs/src/template.rs Outdated
local: usize,
}
impl SceneEntityIndex {
pub fn new((file, line, column): (&'static str, usize, usize), local: usize) -> Self {
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.

Even if prehashing does cut out work, it would be even better if we could do this prehashing once at compile time from inside the macro invocation, via something like https://github.com/HindrikStegenga/const-fnv1a-hash

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 that as a future optimisation, the way its built makes it easy enough to change it to be at compile time, and i suspect it largely already will be, when looking at how Hashed and foldhash work.

Copy link
Copy Markdown
Contributor Author

@laundmo laundmo May 8, 2026

Choose a reason for hiding this comment

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

I want to elaborate on this a bit more:

My hope was that by prehashing here the compiler could notice at compile time that this fixed hasher is called multiple times with the same input, and optimize it to a single call - or potentially even apply constant-folding (not rust const, but at the llvm optimizer level) at least partially.

It also makes implementing compile-time hashing way easier when we have a fully const/compile-time hash function.

Personally, i think i'd prefer switching the repo fully from foldhash to https://github.com/hoxxep/rapidhash which compared to foldhash is just as, if not even more, performant. But something like switching the default hash function used is something which can be done between releases imo.

Comment thread crates/bevy_ecs/src/template.rs Outdated
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Scenes Composing and serializing ECS objects D-Complex Quite challenging from either a design or technical perspective. Ask for help! X-Contentious There are nontrivial implications that should be thought through S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels May 7, 2026
@laundmo laundmo marked this pull request as ready for review May 8, 2026 00:54
@cart cart modified the milestone: 0.19 May 8, 2026
@cart
Copy link
Copy Markdown
Member

cart commented May 8, 2026

Eh I'll leave this out of the milestone for now and we can add it back after the first RC if we think its ready.

@laundmo
Copy link
Copy Markdown
Contributor Author

laundmo commented May 8, 2026

Whats left except reviews for this to be ready?
CI is passing, i think i sufficiently resolved the macro parsing issue, and fully compile-time hashing was never a goal. Tho ofc it depends on how soon the rc will happen - if its literally in a few hours then yeah, duh

@laundmo
Copy link
Copy Markdown
Contributor Author

laundmo commented May 13, 2026

friendly reminder now that the rc is out that this is still waiting

Copy link
Copy Markdown
Member

@cart cart left a comment

Choose a reason for hiding this comment

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

Just pushed some terminology changes, perf improvements (shaved off about 0.3 microseconds on the benchmark) , and minor tweaks. I think this is ready, other than one last question (see below)!

Comment thread crates/bevy_scene/macros/src/bsn/parse.rs Outdated
@cart cart enabled auto-merge May 14, 2026 01:22
@laundmo
Copy link
Copy Markdown
Contributor Author

laundmo commented May 14, 2026

I have no clue how to proceed here, since it seems like a spurious CI failure and i think pushing anything will cancel the merge.

@cart cart added this pull request to the merge queue May 15, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 15, 2026
@cart cart added this pull request to the merge queue May 15, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 15, 2026
@laundmo
Copy link
Copy Markdown
Contributor Author

laundmo commented May 15, 2026

Since merge queue CI is still failing on this, could it be added to the milestone so it isn't left behind?

@laundmo laundmo mentioned this pull request May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Scenes Composing and serializing ECS objects C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged X-Contentious There are nontrivial implications that should be thought through

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants