#Next Generation Scenes

1 messages Β· Page 8 of 1

split harness
#

Picking up the BackgroundColor({palette::Z_AXIS}) bugfix

split harness
#

PathType is inherently a bit janky because it relies on Rust module / type naming conventions to determine the PathType

#

Easy fix for this case

#

I'm aware of one true ambiguity in the Rust naming rules (foo::Z). You can't know if this is PathType::Const or PathType::Type

#

Because we need at least two characters to disambiguate. ex: foo::ZZ is a Const and foo::Zz is a Type

#

I resolve the ambiguity by interpreting it as PathType::Type and requiring {foo::Z} if it happens to be a Const

#

Having type info in macros would be so dang nice :/

split harness
frosty sapphire
#

totally a nitpick but you could use is_none_or(..) instead of map<bool>(...).unwrap_or(false) which i usually find clearer

#

wait

#

is_some_and

split harness
#

Pretty sure it has a rule for this case

split harness
#

If it wasn't the default clippy rule I'd definitely just leave it as-is. I think we maybe have too many tools for handling these cases

frosty sapphire
#

I like to handle to none case as soon as possible, reading that made me have to double back and rethink which makes sense since it's basically like having an else statement below everything

#

That being said in practice I do think I end up doing the same thing as you...

split harness
exotic panther
split harness
fallow cloak
#

or are associated consts unaffected?

split harness
# fallow cloak Could this default to const instead? Things like `Vec3::Y` are fairly common

It could be flipped (and associated consts are affected, as they are ambiguous with Enum::Variant). And yeah one-letter const names are likely more common in this case. The rationale behind flipping them is that {foo::X} syntax is a natural disambiguator in BSN if the default "type patch" behavior isn't correct (ex: default to "type patch" and if that isn't right use {}), but there is currently no syntax in bsn to do the reverse (go from a const to a "type patch")

split harness
#

All that is left at this point is quality / prep work:

thick slate
vast relic
#

not just docs and tests, docs! and tests!

white lichen
#

this just in, bsn! {} macro is blocked on docs! {} and tests! {} macros

thick slate
lime veldt
#

it is hard to believe, but the amount of days until BSN is 4!

white lichen
#

4 factorial, got it

split harness
#

Adding one more TODO item:

Look for a way to keep impl Default for Handle for easier piecemeal migrations

#

Removing Default for Handle is what enables us to impl<T: Default + Clone> Template for T and have impl GetTemplate for Handle (as these two impls conflict with each other)

#

The blanket impl is critical for making BSN usable with things that don't have a manual Template impl

#

And the manual GetTemplate impl for Handle is critical for allowing "asset path" templates for handles like Sprite { image: "sprite.png" }

#

Long term that design is compatible with "always strong" handles (aka remove Handle::Uuid), which I think we probably want to move to.

The current BSN branch removes impl Default for Handle and adds a direct Handle::default function.

But that means that anything that is currently:

#[derive(Component, Default, Clone)]
struct MyComponent(Handle<Image>);

Needs to switch to either:

#[derive(Component, Clone)]
struct MyComponent(Handle<Image>);

impl Default for MyComponent {
  fn default() -> Self {
    MyComponent(Handle::default())
  }
}

Or

#[derive(Component, GetTemplate)]
struct MyComponent(Handle<Image>);

Both of which are pretty disruptive. I don't think pushing people to Templates + BSN that aggressively is the right move

#

Especially right out of the gate / while we're still building it out

#

A better option (in the early days) might be something like:

#[derive(Component, GetTemplate)]
struct Sprite {
  #[template(HandleTemplate<Image>)]
  image: Handle<Image>
}

And remove the impl GetTemplate for Handle impl

#

Aka it makes bsn / templates more opt-in, at the price of ergonomics / UX for bsn / template users

split harness
split harness
#

Today I added a bunch of bsn! tests, renamed Template::build to Template::build_template, and pushed those here

#

I did the rename because Template is implemented for a lot of types (anything with Default + Clone), which meant that Template::build would be ambiguous with any other build() function. Given that 99.9% of people won't be manually called Template::build, I figured giving it the longer name was the move

round totem
#

Ugh. Zed doesn't highlight the @"scene://base.bsn" syntax correctly. The @ throws off the string highlighting. :"string" too apparently

#

VS Code highlights it correctly. Just a minor issue in Zed. Might file a bug for it in Zed if/when BSN is merged into main

golden notch
#

did just test in rustrover and everything in the macro works great, including go to definition inside expressions

split harness
round totem
#

It highlights string literals correctly in notepad++ and vim too. Seems to just be Zed having issues so far.

thick slate
round totem
#

I know i said id do it after the merge but I should probably do it sooner rather than later. It theoretically breaks all proc macros one could make, not just bsn

split harness
rigid adder
#

I use Zed. It has some really cool features πŸ™‚

steel oak
#

Is the intention that a dynamic .bsn file have the same format as bsn! { ... } So you can just copy-paste the guts of a bsn! { ... } macro into a standalone file, and vice versa?

#

I guess that dynamic .bsn won't be able to do some things that bsn! { ... } can, like embedding Rust code

#

TBH it's tempting to just build what I need on top of cart's BSN branch because BSN has correct solutions for things like assets and prefabs already

#

Biggest immediate question to me is how to use the parser given that it's tied to syn

thick slate
split harness
#

However to enable versioning and migration, the .bsn file format will have versioned imports

#

So at the very least, you will also need to include the versioned Bevy prelude import

#

And if you have inline Rust, that obviously won't work

split harness
steel oak
#

Might use lalrpop for that sweet parsing speed

rare whale
round totem
#

@thick slate @split harness ^ as requested

#

Hope I filled out their issue correctly

rare whale
#

It was GvR who got me into peg parsers when we worked on the match statement PEP, since then they have been my parser of choice

steel oak
#

LALR(1) is sooooo fast though πŸ™‚

#

I think I was the one who inspired niko to write lalrpop way back when since I was talking about how great LR parsers were

rare whale
#

Also, as long as you aren't using recursive descent for your arithmetic operator precedence tower, parsing speed shouldn't normally be an issue

round totem
#

Their (Zed's) syntax highlight parser understands &"foo" correctly

#

I wonder if that'll make it easier to fix somehow

steel oak
#

Is the intention to slap #[derive(GetTemplate)] on most reflectable components shortly after BSN lands (possibly behind a feature flag)?

#

And I assume that PatchGetTemplate and friends will have their own ReflectPatchGetTemplate and such?

split harness
split harness
#

We only need to port things that need "real" Template logic (aka feed on the spawn context or the World)

steel oak
#

Ohh, I see, nice

split harness
#

In practice, thats generally Handles

#

But if something is currently Option<Entity> / populated post-spawn, thats a good candidate to be ported to Entity with the EntityReference Template

#

Ditto for anything that has custom ids managed by a resource

steel oak
#

Yeah so I assume there will be heavy use of Reflect, including to potentially call functions

steel oak
#

Makes sense, it's maximally flexible so you don't run into arbitrary limits. Don't use BSN for untrusted content for sure πŸ™‚

split harness
#

We'll want to populate some sort of dynamic "patch" structure, largely driven by Reflect

steel oak
#

Probably could just treat ReflectPatchGetTemplate like any other reflectable trait?

split harness
#

Ex: The reflect field_index -> a Reflect value that can be applied to that field

split harness
#

But yeah thats the general idea

split harness
#

Some Value::U32(u32), Value::Reflect(Box<dyn Reflect>), etc

split harness
#

But for large scenes, we still want that optimized. And in a world where we have parameterized scene assets, that will likely involve per-spawn patch resolving. And thats when speed starts to be super critical

#

Also a reminder that spawning is way slower than it should be right now because we are inserting components individually

steel oak
#

Trying to think about the minimal amount I could implement to switch our studio over to BSN. I think it'd probably be transforms, children, handles to arbitrary assets, and including other BSN files. I don't think we need to call any functions right now

#

Is your feeling that you would spawn a dynamic BSN by something like adding a DynamicBsn(Handle<Bsn>) component to an entity that a spawner system will pick up, like scene spawning does today?

near warren
steel oak
#

As much as I like Jackdaw, its scene format requires quite a bit of work to make usable, and BSN has been designed properly from the start, so it strikes me as best to just focus on BSN

#

Followup would be to make an all-in-one VFX template. We have our own in-house declarative VFX serialization format with tons of bells and whistles that gets converted to a Hanabi graph when you load it. It would be trivial to make it a BSN template and then we could inline it, allowing each VFX prefab to be one BSN file plus whatever textures and models are needed. Templates are neat!

#

As much as I've complained I really appreciate all the work that's gone into BSN. There have been so many attempts at scene formats in the past in Bevy and BSN is the only one that doesn't immediately fall over with some serious deficiency when you try to use it in production.

round totem
#

Still imo other text editors that don't do a thorough parse (like Vim and Notepad++) still render @"foo" strings properly so I'd still call it a bug even when semantic tokens is disabled

split harness
steel oak
#

Current plan: do a spike on a "micro-BSN" which is just enough dynamic BSN to migrate our studio over. Don't do anything that will prevent enlarging this micro-BSN to full BSN later. Fully migrate when 0.19 is released, basing on top of whatever BSN is merged at that time.

cerulean mango
#

FYI: the proto BSN asset format that's in the bevy_editor_prototypes repo has been quite serviceable for our team, while waiting for non-proto BSN. I hacked a crude version of inheritance into it, and we've extended it in some other hacky ways, but it's still quite close to the structure of the original. Just in case you need some reference material or a starting point @steel oak

thick slate
#

Yay thanks Zed team πŸ˜„

round totem
#

I just hope they see the greater picture outside of bevy. Lotta syntax possibilities with rust procmacros. syntax highlighting like <"foo" is broken too in zed but works in every other editor

#

but it's nice that this was caught before Zed 1.0 which allegedly is around the corner

steel oak
#

@split harness Here's my initial experiment using lalrpop. No rush in looking at this at all! https://github.com/pcwalton/bevy/commit/dba0de5a1e37ad2dd79c25587be0570588f1f633

The biggest problems are:

  • Can't do multiple patches yet, just one. I think I need to switch to impl SceneList? This one I'm not worried about.
  • The Wrapper hack is more of an issue. It arises because templates typically bootstrap themselves by calling T::default() with no arguments. This isn't sufficient for reflection-based templates because we don't know the type we're supposed to make a Default of! My solution was to make a sort of "neutral" component for bootstrapping, Wrapper::Default, which gets replaced with the actual T::default value once T is known. This is a total hack and I was wondering if you had a better idea.
#

Anyway, the next thing will be to add multiple patches. Once that's done, we'll need handles via @ paths, struct support for transforms, children, and BSN assets that can reference other BSN assets. Then it should be dogfoodable!

#

I don't like that Wrapper hack though and I feel I'm probably missing something.

#

If all goes well and I implement the above, we should be able to start immediately dogfooding dynamic BSN at my studio by backporting this branch onto 0.19. I intend to do that because we honestly need a working scene format more than we need an editor at this point.

steel oak
#

I do have to say that, unfortunately, this effort has reinforced rather than reduced my belief that the editor is fundamentally blocked on BSN. Manipulating BSN ASTs is so radically different from manipulating the ECS that trying to make a non-BSN-based editor will involve such a huge rewrite to migrate to BSN that it's not worth it IMO. Better to focus effort on my dynamic BSN spike.

That doesn't mean that editor UI can't be worked on in the meantime, but an editor framework... yeah, the data model is just too fundamentally different.

#

Basically the editor is going to be maintaining a bidirectional relationship between an entity (and each component) in the preview scene and the corresponding BSN AST node. This has huge advantages, because it sidesteps the whole "how do you prevent gameplay logic from running in edit mode?" question by simply saying "because you're manipulating proxies of AST nodes, not components themselves". But it's a fundamentally different model from every existing Bevy editor (except maybe Blenvy/Skein, in a weird way).

#

Existing editors have to deal with the whole "how do you instantiate app-specific components in a generic editor?" problem which fundamentally just isn't an issue with BSN except insofar as you might want app-specific editor UI. But that's a much less thorny problem because people are much more understanding of "your custom editor components must go in a separate crate from your game" than "your entire game must be thrown into a library so the editor can import it, and when you recompile the editor has to be restarted".

#

I almost feel like the first step toward the Bevy editor would be a generic AST-based BSN viewer that watches the .bsn file for live reload. That would be immensely useful today, wouldn't be very hard to implement on top of my dynamic BSN experiment, and could form the guts of a later Bevy editor without changes.

rare whale
karmic rock
#

(this surprises me too)

#

Does that mean that you can't use an editor for projects that use the ECS directly vs. going through BSN?

#

Since that would seem counter productive

rare whale
karmic rock
#

That model is inherently incomplete though, since for the runtime state of a game the source of truth will always be the ECS

buoyant venture
dapper sky
rare whale
rare whale
karmic rock
rare whale
#

This AST is different from ECS in that it maintains attributes that are not part of entities and components - things like comments and import statements

karmic rock
#

Does that mean that editor extensions have to be written as mutations on a BSN AST?

#

I think that would be a major turn off for devs

rare whale
rare whale
dapper sky
rare whale
#

For example, you may want to keep unresolved asset references - relative paths stay relative and so on.

karmic rock
karmic rock
#

I want to see parser-specific context if I'm explicitly running BSN. If I'm moving things around in the scene or updating component values, I don't need that

rare whale
#

TBH I don't really want to have this argument. Let's just agree to disagree for now. Eventually the editor will get written, and we'll know for sure.

karmic rock
#

I think these are reasonable points that'd have to be addressed/considered no? πŸ€”

#

Changing the scope of the editor to operate on a BSN AST vs. the ECS sounds like a change with a massive impact crater

dapper sky
#

One pitfall I've had when turning the architecture for potential editors around in my head has been thinking of the patching mechanism as a potential compression tool rather than a dependency management tool. That did lead me down to ast absolutism of a kind. But I think that's different from "editor world runs a limited ECS architecture and syncs changes to an ast"

#

Anyway, this isn't #editor-dev

#

And once the format exists it can be 1. Interpreted and designed around as people like 2. Iterated upon in breaking ways if needed, as long as some kind of migration transform is possible

rare whale
#

Right now I want to save my debating energy for the upcoming "what does an abstract template represent" discussion

#

In any case, the short answer is that I don't think BSN to ECS is round-trippable.

karmic rock
#

If this is just about retaining comments I don't think it justifies such a large architectural change. There are solutions to that problem which are orders of magnitude easier to solve

rare whale
dapper sky
rare whale
#

I mean, I suppose you could make an editor for a subset of BSN that used ECS as the source of truth, and that might be good enough for some people

karmic rock
#

I don't think templates are needed to actually represent the scene content (aside from assets), unless you are hand-authoring BSN

#

If you do it like that, it's roundtrippable, your editor treats ECS as the source of truth, and BSN is the format for assets & storing scenes

dapper sky
#

In a world where a bsn editor exists, 99.99% of .bsn files will never be read directly by a person outside of git diffs.

#

Where they will be scrolled past as noise

#

(I speak from Godot experience)

rare whale
#

Let's say I'm using the editor to edit a UI. If I add a button to the scene, should the resulting .bsn file contain:

:button()

Or should it be written as:

Node { ... },
Button,
ButtonVariant::Default,
Hovered,
EntityCursor,
TabIndex,
ThemeBackgroundColor,
ThemeFontColor,
InheritableFont {...},
#

(These latter are all the components that button adds to the entity)

dapper sky
#

Probably 2, unless 1 is a link to an existing button scene (either hardcoded or on disk) in which case it'd be a dependency.

#

Dependencies won't want to be resolved into bsn files like that so an update (i.e. change in feathers styling between bevy versions or change to the button asset) propagates properly

#

Whole point of it really

karmic rock
wooden vine
karmic rock
wooden vine
#

As Talin said, templates are the big thing, because they're not a constraint imposed by just BSN being the way it is, but one of the goals of an asset format for entities it to be able to build and compose hiearchies and templates of them.

#

But then there's plenty of other things.

dapper sky
#

This is, ultimately, editor design more than bsn design.

wooden vine
#

I do personally think BSN is maybe too complex for the good of the editor, but I don't consider trying to wrangle around the one-directionality of scene -> ECS instantiation a good solution.

dapper sky
#

The rubber will hit the road, eventually.

steel oak
dapper sky
#

We'll see (and some are seeing already, hi pcwalton)

karmic rock
steel oak
#

That’s what BRP is for πŸ™‚

dapper sky
#

I'm off to sleep πŸ‘‹

steel oak
#

(That’s why I said β€œpersistently”, to anticipate that objection)

karmic rock
#

Right, I was operating under the assumption that you'd want to have a single inspector/entity view/... widget that can do both

south lagoon
steel oak
#

Personally the Bevy approach is a breath of fresh air. In Unity all sorts of evil comes from trying to pretend that edit mode and play mode are the same thing. I much prefer just making it front and center and saying no, they aren’t

karmic rock
#

Also, if you use BRP what does that mean for Rust-authored editor extensions?

#

Just sounds like such a lot of entirely avoidable complexity, if you just don't make the entire editor go through BSN πŸ˜…

leaden dew
karmic rock
#

The behavior of Unity's inspector and treeview are exactly the same in editor/play mode. The only difference is that changes during play mode aren't persistent

leaden dew
#

right, think i lost track of your broader point questioning whether the editor should operate on the BSN AST

karmic rock
#

Yeah TL;DR it makes more sense to me to have

Editor <-> ECS <- BSN

than to have

Editor <-> BSN -> ECS
steel oak
#

As an example of this, consider prefab unpacking. In edit mode, there is an enormous difference between a packed prefab and an unpacked prefab, whereas in play mode there is no such difference. If you change a packed prefab, all non-overridden components are immediately changed in edit mode. Deleting a prefab entity is something you can't do in edit mode (without unpacking it). An unpacked prefab on the other hand is a standalone object; changing the components of the prefab doesn't affect the unpacked prefab.

Now if you had a model where you edit components and you want to make prefab editing sensible, now you're in a pickle, because there is no difference between packed and unpacked prefabs at the component level, and the ECS has no notion of "an overridden component" vs. "a non-overridden component". You need a ton of complexity layered on top of the ECS, or you need to build prefabs and overriding directly into your ECS, or something like that. It is far, far simpler to just separate concerns and say "the edit mode representation is different from the play mode representation". Which is what BSN does.

#

In my mind, failure to separate concerns like this is exactly why every other scene format in Bevy has failed.

karmic rock
steel oak
#

I knew you would say this

#

and I'm just saying, your solution is ultimately much more complex

#

By trying to force a unified model on two data models that are fundamentally different, you just add more complexity

#

The genius of BSN is that it makes front and center that there is a difference

karmic rock
#

I mean idk about that, I've had this for years, built it as a sole developer, and have people use it, build editors for it (including myself). The API is easy, the concepts are easy (because there's only one representation to reason about), and it addresses pretty much all of the above issues

steel oak
#

I assume flecs must have some sort of thing built in where you can say "this component is a mirror of that one except that components X, Y, and Z are different"?

#

Because otherwise I don't see how it works with prefabs

karmic rock
#

It supports overriding on the component level

steel oak
#

That's the difference, Bevy ECS has no such concept

karmic rock
#

Right, I know that. But since this is a solution that really simplifies all of this, and since Bevy has full control over the ECS, BSN and the editor, it's worth considering

steel oak
#

Well, honestly, if we were to do that then that is a complete redesign of BSN

karmic rock
#

(that said I think that train has left the station a long time ago)

steel oak
#

which we just don't have time to do right now

#

Fundamentally I think this just comes down to the fact that flecs and Bevy ECS are different. flecs has overriding as a concept and Bevy does not. My argument is that, if you don't have overriding as a concept in the ECS, and we don't, then the BSN approach is the only one that makes sense. Because otherwise I don't see how you make prefabs work.

karmic rock
#

I wasn't trying to say that Bevy should adopt Flecs's model (I'd rather have it not do that, it's a differentiator :P). I was just pointing out that the complexity you highlighted was somewhat self inflicted (by Unity)

steel oak
#

I thought about that, but I don't like the idea of losing the concept of an overridden property during a round trip

#

Even if you can reconstruct it again

#

For example, Unity colors the widgets for overridden properties with a different color iirc

karmic rock
#

Yeah it does

#

But IMO that's state that the editor can keep track of, just like how it would track in this design that an entity is an instance of an asset

#

That way at least all of the BSN complexity is only present at load time and at save time

#

And you can start development on an editor today

steel oak
#

You view it as complexity, I view it as simplicity πŸ™‚ I think it's easier to have the data model that you edit have the explicit notion of overriding

steel oak
#

I'm not far from having the infrastructure necessary to start on an editor

karmic rock
#

Not if the data model is a complex AST that you have to mutate. Unless things changed, Bevy does want the Bevy editor to "just be another Bevy app". That changes significantly if that means "go through the BSN AST first".

steel oak
#

I see it as "Every computer science problem can be solved with another layer of indirection"

#

It's still just another Bevy app. It's just that what you edit isn't the components themselves, but rather an AST.

#

Speaking of which, I wanted to mention that I think the AST should be a petgraph, at least to start with. Eventually we could have AST nodes as entities, but that has implications that I don't want to think through right now

karmic rock
#

Idk, I look at the flecs script AST and I wouldn't want to make that the primary interface for people to interact with anything. But maybe BSN will turn out to be much simpler, and this is the first AST that's easy enough to use as front-end API πŸ˜›

#

I guess I'll have to wait and be proven wrong

steel oak
#

I'll definitely have to put a lot of effort into usability

#

this conversation has been helpful BTW

steel oak
#

Oh, something else I thought of:

  • There should be some kind of opt-in marker on templates like SyncInEditMode (name bikeshedding welcome). If this marker is present, then the component will be instantiated from the BSN in the editor and visible in the preview if the component has been linked with the editor.
  • Things like Mesh3d, MeshMaterial3d, PointLight, etc. are SyncInEditMode, so you get WYSIWYG in the editor. Some third-party components like Hanabi particle systems can be SyncInEditMode as well, so that they show up.
  • Most gameplay-related components will not be SyncInEditMode. This is important because you don't want to have to recompile and reload anything in the editor whenever you change a gameplay-related component. If you add an elemental_weakness field to the Monster component, that has no visual appearance in the editor beyond a generic drop-down, so you don't want to have to recompile anything. In fact, a lot of games can be created without linking anything beyond the built-ins to the editor at all.
  • Some components appear in the editor as gizmos, and those also may not be SyncInEditMode. Those gizmos can simply operate off the BSN AST. For example, a gizmo that shows a light cone, or that displays a collider as a box, could simply operate off the BSN AST. Or it could operate off a SyncInEditMode component, whichever is more convenient. The advantage of using SyncInEditMode and operating on the component is that you could have the same gizmos appear in play mode; the disadvantage is that you have to have the component linked in to the editor.
rare whale
steel oak
#

Without having to recompile the editor and link it against my game.

#

There might need to be a way to export a declarative "components schema" -- basically, some file format that the Reflect metadata exports to -- for this to really work.

#

IIRC Skein has some tool for exactly this, so that Blender can load in the schema corresponding to your game's components.

rare whale
karmic rock
#

in flecs script you can do stuff like

struct Position { // creates Position entity
  x = f32 // creates x, y entities
  y = f32
}

e {
  Position: {10, 20}
}
#

the first part is mostly syntactic sugar, the desugared version boils down to plain entity/component statements

rare whale
# steel oak How does it work?

Well, one approach I have experimented with is making sure that all the game's asset loaders are smart with respect to file watching - so that if an asset file gets touched on disk we can reload the asset without having to restart the game. Then the editor just modifies files.

But I have other approaches, not sure they are relevant to discuss.

#

I will say that the fun part is all the component-specific gizmos πŸ™‚

steel oak
#

Hmm, I think it'd be fairly easy for an editor to have a plugin ABI that lets you pull in &mut World systems at runtime without having to reload anything. fn(&mut World) should be a stable ABI as long as your Bevy versions match up

rare whale
#

We really should move this to #editor-dev

steel oak
rare whale
slender lion
lusty epoch
#

I think bsn AST should be expressed as entity-components, and loaded directly as ECS components. Then you can use a ECS editor for BSN. You just need to progressively make the BSN AST editor easier to use (because the default reflect based editor for the AST is NOT easy to use). (And also you can edit the result of prefab unpacking and mirror them back to the BSN, like what Figma does)

If yo view BSN/prefabs just a tool for data compression, then ECS is a more fundemental concept compared to BSN/prefabs. You can have other compressions, so there are no reason bsn should be the single one. And all these are just data and computations, they should all be represented as ECS.

The only serialization format for ECS should be the current Scene format.

split harness
#

Just pushed some BSN changes:

  1. Scene patching and spawning now have proper error handling (returns Result, queued / deferred spawn failures now log errors instead of panicking)
  2. Refactored ScenePatch and SceneListPatch spawn logic to be less redundant. Much cleaner now.
  3. Renamed scene spawning functions on World. They are now spawn_scene / spawn_scene_list (runs immediately / returns a Result if an error occurs, such as requiring a dependency) and queue_spawn_scene / queue_spawn_scene_list (queues the scene to be spawned when its dependencies are loaded).
split harness
split harness
split harness
split harness
split harness
split harness
#

Which isn't an immediate priority, but it has come up and I see the value

karmic rock
split harness
karmic rock
split harness
lusty epoch
karmic rock
#

TL;DR, keep BSN at the gates (loading/saving), let the ECS be the source of truth for scene introspection/editing (both in edit mode and play mode), and store assets as BSN

#

(and keep track of which entities instantiate which assets, which properties are overridden etc)

split harness
#

Aka the "prefab" vs "flecs script" distinction in flecs

#

I believe there might be a middle ground that gives us the best of both worlds

karmic rock
#

Right, that's why I kept assets separate in my description. My thesis is that you do not need that kind of expressiveness when it comes to the contents of a scene (basically just positioning), you only need that for assets where you want to do inheritance etc.

#

It makes a lot of sense IMO to have an asset editor that speaks BSN

#

Not saying that you'd never want that expressiveness, but if you do you're much more likely to hand-edit BSN

split harness
#

I see where your head is at. I'm not (yet) in a place where I'm going to strongly push for any of the options discussed here. I would personally start from a "selective syncback" model as I think a unified system is cool and useful

#

That also happens to be easiest in the early days, as we can start with the "BSN as flecs script" mindset

karmic rock
#

Yeah fwiw I'm not at all advocating for an approach where you have two separate formats for assets/scene. The output of an editor can still be a bunch of BSN files. I'm just advocating for a solution where the editor accesses the ECS directly for scene contents, since that has lots of advantages

split harness
#

Then wire up syncback where it works

split harness
white lichen
#

my take here fwiw is that bevy has always advertised "the engine code is just like game code", and putting bsn between the editor and ecs is going to depart from that majorly. imo if theres an expressivity loss with the ecs, that just means we need to embellish the ecs with more ways to express what it cant, i think bsn assets are "just data" and so whatever they have that the ecs doesnt can just be stuck into components. at the very least, the BSN AST should be entities and relations itself

karmic rock
#

if theres an expressivity loss with the ecs, that just means we need to embellish the ecs with more ways to express what it cant
this is very much the approach I took with flecs, but not sure if that's compatible with bevy's current direction

white lichen
#

i am very very worried about this "use petgraph for the BSN AST manipulation" take ive been seeing. this is very not good and a red flag imo

split harness
#

I'm on team "World to BSN". The question in my mind is what the "scope" and implementation of that is

#

And BSN AST manipulation is unequivocally easier to build in the short term. And its a feature we know we want

white lichen
#

BSN is a bit overloaded in that theres the assets variant and the macro variant, i do think that we cannot realistically turn function pointers back into code, but id be happy to be proved wrong. barring that, its just data, which means entities and components

split harness
#

(even in a world where we embrace "BSN limited to what is bi-directional" as our primary editor paradigm, leaving the full BSN featureset to text file or AST editors)

white lichen
#

i actually had a conversation with alice ages ago where she asked what game studios needed from a scene format, and i mostly talked about text diffs and merges, and how it should be stable across ser/de. one thing ive thought about a few times is adding span components to entities essentially, which lets them be reassembled in the exact order they were pulled out of the original text

split harness
#

But yeah I'm not in a "dictate these parameters" place yet

silk lava
split harness
#

Everyone should experiment and make their case

split harness
white lichen
#

what is the goal of the editor exactly? i thought there was some agreement about MVP being "transform gizmo lets you move things around in a scene and save/load it"

#

if its just a glorified text editor where you still have to type in the coordinates manually, what exactly is it getting us that we dont already have

split harness
#

I'm largely saying that applying BSN changes to the current World is a necessary first step, and provides significant value on its own

#

necessary first step
"reasonable first step" is a better way to say this

#

BSN hot reloading is not inherently necessary to a workflow like "load initial BSN file" -> "make changes in ECS" -> "Convert ECS back to BSN" -> "Save BSN file"

karmic rock
steel oak
#

@split harness Just implemented multiple patches, wasn't hard. I'm now refactoring to make it possible to have random access into the AST, which is important for an editor. After that, will work on having child nodes in the AST.

steel oak
# white lichen if its just a glorified text editor where you still have to type in the coordina...

Depends on what that question means. If it's:
(1) What is the viewer getting us that the glXF viewer in my glXF crates doesn't have?

  • Proper support for overrides.

(2) What is the viewer getting us that Skein doesn't already have?

  • Same answer as (1), except also:
  • The ability to modify a scene file storing a complex Hanabi effect that was generated from an external tool that doesn't understand Blender and have it live reload.

(3) What is the viewer getting us that .scn.ron or glTF doesn't have?

  • Same answer as (1), except also:
  • The ability to embed nested scenes.
  • The ability to set arbitrary components.
  • Proper asset references.
#

Dammit Discord, you ruined my formatting

steel oak
white lichen
#

that doesnt sound any better, why not use the ECS

steel oak
#

For all the reasons discussed above: lack of support for overrides in the ECS, having to recompile the editor all the time, etc.

white lichen
#

and slotmap has overrides? slotmap doesnt have to recompile the editor?

steel oak
#

Correct

#

I would very highly recommend that people actually try using .scn.ron for an actual game. The issues that you run into are not obvious until you actually try to use it and slam headfirst into showstopping issues

white lichen
#

we should replace bevy_ecs with slotmap, cus it sounds like its more expressive and powerful (being slightly snarky with this)

steel oak
#

I think we're talking past each other.

white lichen
#

all im saying is that you can use the ECS in the same way that slotmap can be used

#

ill go look at the api again just to be sure

#

yeah this just looks like World

steel oak
#

There are two issues here that I are think are being conflated:

  1. Do you edit components directly and serialize them, or do you edit a higher-level representation that has the notion of overrides and prefabs, etc.?
  2. Does this higher-level representation live in the ECS or is it separate (e.g. in a slotmap)?
#

I feel much stronger about (1) than I do about (2).

#

I'm open to "AST nodes as Entities"

#

Slotmap is easier for me to get started with. I'm happy to switch it over to the ECS if people want to go that route.

white lichen
#

i am not against higher level representations. I am against not dogfooding the ecs when its right there

#

we used the bespoke render graph thing for ages before switching to the ecs

#

id like to avoid that if possible

steel oak
#

Yeah, I had similar thoughts. This is just a prototype and if folks feel strongly I will move it over to the ECS before making a PR.

white lichen
#

okay sure

#

slotmap is an ecs-lite imo

lusty epoch
#

Do you edit components directly and serialize them, or do you edit a higher-level representation that has the notion of overrides and prefabs, etc.?

You actually want both, editing a instanced object is non-direct, but you have "clear overrides" which is direct

white lichen
#

having two ecs' in tree sounds silly and like a failure

#

i guess its just EC not ECS

steel oak
#

I think y'all might be more sympathetic if you saw how difficult the type tetris I'm having to deal with is πŸ™‚ The patch infrastructure is powerful but it is extremely type-heavy and then you add the fact that I'm integrating it with Reflect on top and it requires a lot of experimentation.

#

I just didn't want to deal with ECS-ifying it yet.

#

I'm happy to do that once everything is working.

white lichen
#

im dealing with my own struggles, currently figuring out render recovery

#

the RenderAssetUsage Render World is kind of horrible in that when the device has to be recreated, none of the meshes it had in it are in the main world anymore, so i have to reload them

steel oak
#

For example I have to do all of this inside an AssetLoader. Uh, how do I access the World inside an AssetLoader again? Do I have to make a sub-World or something? I don't remember and don't want to figure it out when I'm just struggling to get anything working πŸ™‚

white lichen
#

yeah you can just create worlds, theres some code showing how to do this in the render world setup

#

theres also a scratch world

steel oak
#

I'll migrate it over

#

just want to get things prototyped first

white lichen
#

sure thing

#
let mut world = World::new();
#

lol

#

what i dont know about is world merging ergonomics, but i dont imagine slotmap has a thing for that either

steel oak
#

You can't make dynamic components at runtime, can you?

white lichen
#

i think you can

#

i am not very in touch with the dynamic ecs apis though

steel oak
#

(This is not an argument for slotmap, btw, this is an argument against "just edit the ECS")

steel oak
#

Can you unregister components and edit them?

frosty shell
#

not atm i dont think

karmic rock
steel oak
#

That seems like a deal-breaker, because you should be able to modify the component definitions and reload without recompiling your game in such a way that it can be linked against the editor, and without restarting the editor

split harness
#

@karmic rock @white lichen @steel oak

An issue I remember encountering when considering ECS -> BSN writeback is that when spawning things in the ECS, they will go through the "init lifecycle". This could easily change values to something other than what is set at the beginning, and override the intiial user intent.

Additionally, serializing everything isn't on the table, as that doesn't play nicely when patching scenes. We should only serialize what the user has set. This is not inherently the same as "what is not currently default values".

#

@karmic rock I am curious how you handle this in the context of prefabs and inheritance

steel oak
#

The beauty of BSN, to me, is that it says "this is the edit mode data model" and "this is the play mode data model" and they are related, but separate

white lichen
#

we have to be using the ecs!! we are an ecs engine! thats what its all about lmao its just data!

karmic rock
# split harness <@260273550726922240> <@796226530485076008> <@451476504879169546> An issue I r...

Those are good points, but I think they're somewhat orthogonal. The editor has to track metadata (which asset is an entity, overridden properties). It could do the same to track what the user has explicitly set- essentially the minimum viable amount of data to reproduce the scene

This is also somewhat of an argument in favor not not using BSN as the source of truth: if instantiating an entity means going through the init lifecycle which creates another entity, I should be able to edit that entity in the editor, and make sure that this edit persists. So that argues in favor of an editor that at least looks a the actual ECS world, not the BSN AST.

split harness
#

if instantiating an entity means going through the init lifecycle which creates another entity, I should be able to edit that entity in the editor, and make sure that this edit persists
I personally don't think this type of "editing future entities" should be valid here

steel oak
split harness
#

Agreed. I'm certain we can come up with cases where that is quite bad

steel oak
#

Often times when I have an entity that instantiates another, it's because that second entity encapsulates play-mode-only logic

karmic rock
#

I think it would be highly counterintuitive to not be able to edit an entity that I can see in the scene, but I could be wrong

steel oak
#

For example, when spawning the Player I add a CameraTarget entity which is the entity that the camera looks at. By default that is the player but it can move to focus on other things. I don't want see that CameraTarget in the editor because it's a play-mode-only thing.

karmic rock
lusty epoch
white lichen
steel oak
#

One argument in favor of @white lichen's position of AST-nodes-as-entities is that the bidirectional relationship between AST node and instantiated entity could be an actual Relationship

white lichen
#

yes! yes!

#

this is what im saying

#

we can do whatever semantics in the ecs

karmic rock
#

I might at some point implement it natively, we'll see

split harness
white lichen
#

we need to be dogfooding the ecs. we can have "engine code is game code" if the engine is still ecs, just dealing with components and entities as usual. they dont have to be literally The Camera3d or Mesh3d or etc, just entities and components of whatever semantics to encode whatever behavior you want

steel oak
#

One thing to note is that editing handwritten BSN will probably not roundtrip.

split harness
steel oak
#

Just because there's a finite number of patterns that we can handle at the UI level. I don't think this is necessarily a problem. Just something to be aware of.

split harness
steel oak
#

Oh, something I didn't consider, pretty printing the resulting BSN will be load-bearing, as we want merge conflicts to be resolvable by hand (holy shit this will be such an advantage over Unity)

white lichen
#

i have said this already too

karmic rock
#

I'm not saying that field-level overriding isn't useful, but it is not as useful as in Unity, where components can have many fields. In ECS it's much more common for the fields to be updated together. E.g. it's unlikely that you only want to update the x field of a component, but still want to receive propagated values for the y field.

split harness
white lichen
#

i actually said this exact take to alice in DMs 2 years ago

karmic rock
steel oak
#

If you've ever had to use Unity's ScriptableObject API... ohhhh boy. I have seen worse APIs but not many.

white lichen
split harness
#

But to be clear, I'd still very much like to enable ECS syncback scenarios in the editor

karmic rock
#

I also think (but this is more contentious) that we can think outside of the box a bit, and not necessarily reimplement what existing engines have already done. Granular overrides are a must-have for Unity, but like I just said, components are already much more granular in ECS. So maybe component-level overriding is good enough

steel oak
#

Anyway, for the most part I'm having a very pleasant experience writing the AST for BSN and any problems I've run into so far have been surmountable

split harness
steel oak
#

So yeah, πŸ‘ from me on BSN's design

split harness
#

Not the most important scenario, but one we are interested in

karmic rock
#

Because you want to be able to only set the r field of a color? πŸ€” Why is that?

steel oak
#

Thought: Oh man, I just realized how much nicer templates can make Hanabi's Module API

split harness
rare whale
split harness
#

You could make every patchable property its own component. But I don't think that constraint is enforceable or desirable

rare whale
#

But that means that the editor can't flatten mixins and serialize the merged result

#

Or to be precise: an editor which did flatten mixins would be useful for a small subset of users. It's why sites like amazon.com killed off dreamweaver: in the dot-com era DW was a big deal, but it was only useful for editing the surface representation of an HTML page, but soon the web evolved and most sites were dynamic, so what you really wanted to edit was the deep structure, of which the surface was only a derivation.

karmic rock
# split harness Think about CSS, its more complicated than that

Yeah ok that's fair. I've implemented a CSS-like styling module on top of Flecs once, and that's definitely a different way to model things. I don't think I would want to make that the foundation of my game assets though. Basically what you're saying is that you want to build the entire engine around a model that operates on field-level granularity. That's going to have consequences for performance

#

(and maybe ECS isn't the right fit for that)

steel oak
#

Well, you need to be able to cache entire resolved scenes, otherwise it'll be slow no matter what

silk lava
#

Field level granularity would probably like Field Projections from Rust, hopefully they cook

karmic rock
#

Could be wrong though

rare whale
#

Since it kind of relates to the current conversation, I might as well open up this can of worms I have been saving, which is my objection to this statement from last month:

My assertion is that abstract "things" should (generally) not exist without a runtime representation.
To me this is a very odd constraint to adopt, both from a philosophical and from a practical standpoint. Philosophically, "abstract" and "concrete" are antonyms, and there's nothing that says that they have to share the same structure or shape. Practically, I think this decision weakens the power of abstraction. I can think of a number of examples in which an abstract template in, say, React, produces a DOM which is structured nothing like it; prime examples are <ThemeProvider/>, <ReduxContext/> and so on.

#

It relates to the editor discussion because I want to be able to preserve in the edited artifact these abstract template invocations

#

Part of the expressive power of BSN that I've been able to use, even with the limited functionality of the branch, is the ability to "go meta" in the template.

karmic rock
rare whale
#

In the react world you often see code like this:

<ThemeProvider>
  <FooProvider>
    <BarProvider>
      <div etc...>
    </BarProvider>
  </FooProvider>
</ThemeProvider>

Where the output of all this is just <div...>, but a div rendered with contextual knowledge of the various providers - the point is that none of the providers actually render a dom node of their own, there's no concrete representation. This works because there are two hierarchies: a creation hierarchy and a runtime hierarchy. They have similar shapes but not the same shape.

frozen bramble
frozen bramble
#

Also, not to make this more complicated than it needs to be but:

bsn being so heavily reflection based means that sooner or later there will be a path to execute arbitrary code through the bsn files (intentionally or unintentionally). This being unexpected behaviour from the player and maybe even the game developer opens it up as an attack surface. It might be worth considering (probably in the future) to implement signing of the bsn files for release builds so they cant easily be manipulated. The attack surface is certainly not big and there is room for discussion im just throwing my 2 cents in as someone working in cybersec

wooden vine
#

(Yes, Unity has done that to me on multiple occasions)

coarse patrol
round totem
#

Looks like Zed devs confirmed my fear and they only fixed the highlighting issue specifically for bsn 🫀

#

The real issue affects all rust proc macros. The real issue is that a punct before a string literal breaks syntax highlighting. Rust allows macros with punct next to string literals with no space

copper dragon
slender lion
# round totem Looks like Zed devs confirmed my fear and they only fixed the highlighting issue...

heya, I was involved in this fix. The context here is that zed is basically re-parsing macro contents as regular rust code, but has carve-outs for specific macros to not do that, such as view!, etc. bsn!, being similar to rust but not actually rust (and more like view! in that way), invalidates those assumptions. So the short-term fix is to not parse bsn! as regular rust code which fixes the broken string issue, the specific long-term is for bsn! to have its own tree-sitter that is aware of its special name constructs (like :variable, :"string", etc), and a general long-term fix for all macros would be like you say and require rewriting the support for highlighting inside of macros as far as I can tell.

The token stream for Rust also does not seem to allow differentiating : "something" from :"something", and the tree-sitter cst is the same for both scenarios.

For the general case, it would be very helpful to have more examples of macros that use string prefixes and a different issue filed for the general case. The team doesn't seem to have a list of relevant, real-world macros to test this against at the moment. In the meantime, a fix for bsn was merged since it looks like bsn is landing in 0.19 and wouldn't want to wait for more general reworks to be done.

round totem
# slender lion heya, I was involved in this fix. The context here is that zed is basically re-p...

That's fine for bsn! to be special cased, especially with future plans to specialize the highlighting, but I'm not fond of the idea that Zed would need real world macro usage cases to fix general case highlighting, especially when creating any macro highlighting works in every other editor I used.

I think short/long term Zed should treat all non-special-cased generic macro invocations as Rust code just like it does now, but 1) make all (non-{[() punct characters the same color 2) do not break string literals when a punct is next to it and 3) drop the match requirement for <> inside macros

slender lion
round totem
#

(Because in a macro < does not need a match, only ([{ do)

#

Not sure if I should leave a comment about my 3 bullet point list suggestion, or open it as a new issue that can be fixed later on

slender lion
# round totem Not sure if I should leave a comment about my 3 bullet point list suggestion, or...

IMO a new issue makes more sense. The original issue filed was for bsn's issues with it, but a more general case is a different fix. The reason I suggested more real-world examples of where this is failing is that this would help motivate getting it actually worked on. If it's not clear that it appears in code people are actually writing, it will be easy to prioritize other work over it. Currently it seems the only macro that the team is aware of that does this is bsn.

I'm not sure the bullet point list will be applicable as a fix, but feel free to include it since it shows what you expect the result to be.

round totem
slender lion
#

like: its a bug IMO, the question is really "how important is the bug to fix compared to all other bugs?"

round totem
#

I genuinely think at least having punct next to strings break them might genuinely put some people off from the editor when making custom macros

#

Admittedly that number might be small, but it works in other text editors fwiw

slender lion
#

yep, agreed. I think its worth fixing.

steel oak
#

Just added support for defining children to my dynamic-bsn branch. Only lightly tested.

#

Next up will be adding support for the full range of Rust data types you can use to define components.

#

I was worried that the fact that you don't need commas to separate components in BSN was going to lead to its not being LALR(1), but so far it's been fine, no shift/reduce conflicts

#

I would mildly advocate for continuing to use LALRPOP here as we care about perf and you can't really beat LR parsers for this (unlike LL parsers they "know what to do" immediately). I don't feel strongly though.

#

I believe once I have these data types working I'll be able to migrate all of our use of glXF over to BSN. We don't need inheritance at the moment as glXF never supported it (of course it should be added eventually, but I'm focused on getting something useful first)

split harness
#

Today I'm working on fleshing out the BSN docs. As part of that, I've convinced myself that we should reframe the "scene patching" process as the "scene resolving" process. For example Scene::patch, SceneList::patch_list, PatchContext, and ScenePatchError would become Scene::resolve, SceneList::resolve_list, ResolveContext, and ResolveSceneError.

The rationale is that the "output" of the process in question is a ResolvedScene (which should definitely not be renamed to PatchedScene). Patching is a part of the "scene resolution process" (aka some "things" are patches), but it isn't the whole truth of it.

The reframe allows us to be very tight in our definitions and lifecycles (ex: "step 1: resolve the scene, step 2: apply the resolved scene to an entity") in our types, errors, and docs.

#

This diff largely encapsulates the change from a types perspective:

thick slate
steel oak
split harness
#

Same rationale as the bsn! vs bsn_list! distinction

#

I am reasonably certain we could gloss over that distinction if we really wanted to (aka let bsn! be either a list or a single entity). But that shifts some pretty important semantics to runtime / conventions

#

Godot gets away with this by saying "scenes always have a root entity" (aka they only have a Scene equivalent)

steel oak
#

It doesn't matter to me, I just wanted to understand

split harness
#

But given that we have things like:

fn widget(children: impl SceneList) -> impl Scene {
  bsn! {
    Node
    Children [
      {children}
    ]
  }
}

I think the list semantics are valuable

steel oak
#

@split harness How did you want to maintain the bookkeeping necessary to establish the bidirectional relation between an AST node and the spawned entity? Put some kind of current_ast_node: Option<Entity> in the PatchContext or something?

split harness
steel oak
#

Right, that's what I was planning

split harness
#

Although cleanup gets expensive that way

#

Despawning an entity should be O(1)

steel oak
#

But I was wondering about the bookkeeping

#

Should I add it to the patch context?

split harness
#

(aka until after the BSN PR is out)

steel oak
#

Ok, in the meantime I'll just do something

#

This is why it's good that I've done this spike, it's the kind of thing you won't think about until you slam into it

split harness
#

Yeah come up with your own opinions about how it should work πŸ™‚

steel oak
#

TBH I may not need it right now

#

Since for the BSN viewer I can just blow away all the spawned nodes in the entire world and recreate them when I detect an edit to the file

#

No fine grained bookkeeping needed

#

Obviously for the editor that won't be sufficient though

steel oak
#

I was thinking the BSN viewer will probably start out of tree, because I need to be able to link third party things (Hanabi in particular, but also probably Avian) into it

#

Which means it needs to wait until 0.19 to be useful since we'll need Hanabi and Avian to be updated, though I can start on it now

rare whale
#

For my mini-scripting-language AST, I used bumpalo, it's nice because you can just scatter rust references everywhere in your structs without worrying about lifetimes

steel oak
#

Yeah, I'm going to have AST nodes as entities in the ECS

#

@white lichen felt strongly about this and I see no good reason not to do it

rare whale
#

Arenas only make sense if you are going to dispose things all at once instead of editing incrementally

steel oak
#

Right, and we want to edit incrementally eventually

rare whale
#

But for cases where you aren't editing, only constructing, they are way less hassle than entities

steel oak
#

For now we'll just blow everything away and regenerate. Most inefficient editor ever πŸ™‚

#

But have to walk before we can run and an inefficient editor is leagues better than no editor

rare whale
#

None of this try_get accessor nonsense πŸ™‚

steel oak
#

I intend that the live updating BSN viewer could evolve into the editor eventually

rare whale
#

I think that naming will be critical - the "AST ECS" is not the same as the "target ECS", and people may get confused

steel oak
#

The editor could start as literally just an AST syntax editor sidebar with a live updating preview pane with camera controls/an infinite grid

#

Picking won't work in that case but again, have to walk before we can run

rare whale
steel oak
#

Right, you need the bidirectional map in that case tho

rare whale
#

SourceLocation { start_line, start_col, end_line, end_col } component

steel oak
#

Oh, I was thinking more of an AST node and by "AST syntax editor" I mean something AST based rather than text based. Reflecting over the AST to generate a UI

#

Kinda like Scratch

#

I don't think the specifics of the UI matter too much as long as undo is supported from the beginning (not supporting that from the start would be a major blunder)

rare whale
#

I'd like to avoid having two separate undo libraries (one for the editor and one for people who just want to use the text input widget in their games and apps)

#

There's no technical reason why these can't be unified, it's pretty easy to generalize without risk of overfactoring

split harness
#

I'm also on the market for better ScenePatch / SceneListPatch names. What they really are is owned assets holding an owned Box<dyn Scene> / Box<dyn SceneList> (respectively), which also holds a list of their dependencies (to allow the asset system to manage the load state) and (currently) also potentially holds the final resolved scene (although with assets-as-entities I'd like to move that to a separate component inserted on the asset after it is fully resolved)

#

I consider that naming lower priority at the moment though, as those asset types are abstracted away for the majority of users

steel oak
#

Yeah, it's similar to Reflect, the guts are complicated but thankfully few have to interact with it

split harness
rare whale
#

Not really sure I understand what is being described

steel oak
#

I think we're missing a few Reflect traits that are necessary for proper dynamic BSN. We need ReflectRelationship (or maybe more features on ReflectComponent) and also ReflectFrom (or whatever) to handle the "asset://foo.png".into::<Handle<Image>>() magic.

#

For now I'm just hardcoding the Children relationship and adding magic logic that autoconverts a string to a Handle<T>.

round totem
#

^ @slender lion fresh issue

#

(though admittedly this is becoming only tangentially related to bevy at this point)

slender lion
split harness
#

We should discuss how to handle the bevy_scene vs bevy_scene2 situation.

  1. Having two "scene" things in-tree together is extremely confusing (multiple scene crates, multiple Scene types, etc). This will make things like Rust Analyzer / IDE suggestions way worse. But also docs / learnability!
  2. We cannot yet deprecate bevy_scene in its current form, as bevy_scene2 is not yet usable for "whole world serialization" scenarios.
  3. The current bevy_scene is more like bevy_ecs_serialize, especially when compared to bevy_scene2.

I propose the following renames (to happen after the initial BSN pr, but before 0.19, in the interest of review clarity):

bevy_scene -> bevy_ecs_serialize
bevy_scene2 -> bevy_scene

Additionally, all of the existing "scene" terminology in bevy_ecs_serialize (ex: bevy_scene::Scene) should be renamed in favor of "serialization" terminology. Given that bevy_scene::Scene is literally just a World wrapper type, we could probably just frame this as operations directly on World.

#

This would be a discrete, breaking change. But I believe it is far better than trying to have overlapping type names in tree for an unknown number of releases (there is no telling if/when bevy_scene2 will be suitable to replace every bevy_scene scenario)

#

Given how underused bevy_scene is currently (given the lack of official editor workflows), I think this is acceptable

steel oak
#

I can't figure out how to proceed without eliminating use of downcast-rs in ErasedTemplate. The problem is that I have to wrap a Box<dyn PartialReflect> in a Box<dyn ErasedTemplate> but PartialReflect doesn't impl Downcast.

#

IOW I think the problem is downcast-rs has one notion of downcasting while bevy_reflect has another. BSN is using the former but I have to hook it up to the latter.

#

Also I'm currently hardwiring the only supported templates to be clonable defaultable things. We need a ReflectTemplate to go beyond that. I'll definitely support Handles somehow though.

silk lava
steel oak
#

Again, I'm really glad that I'm doing this stuff as it would be bad to have shipped BSN with choices that prevent the dynamic implementation from working (unless I'm missing something)

split harness
split harness
silk lava
#

Hmm I see serde as more of a verb then a noun, but I could see the confusion.

thick slate
steel oak
#

OK, my dynamic-bsn branch now has support for struct and enum components, as well as arbitrary hierarchies of templates (i.e. children). Next up is support for handles.

steel oak
exotic pecan
#

Or since the old Scene contains a World, how about something like bevy_snowglobe or bevy_microcosm

copper dragon
steel oak
#

Actually adding support for handles is quite complicated because I realized I need to implement a ReflectGetTemplate to do this properly. I'm putting this all aside for now until BSN gets a bit more mature.

split harness
#

Ex: we will likely have a binary format that is not the BSN format

#

We could theoretically have a jsn format that also implements the "bevy scene system" / some third party might do that

#

In my old branch, bevy_bsn was a separate crate that just had the AST

steel oak
#

I mean it's just an AST, you can have binary encodings of that

split harness
steel oak
#

My branch isn't too far from having usable dynamic BSN. I think I'm going to leave it aside because I don't really have time to add a whole bunch of reflection infrastructure right now. I could add a hack for Handle but there's no point in adding more hacks if glXF already works.

split harness
#

I strongly believe that bevy_scene needs to go (as-in change to a different name). Its the first place people will look for "bevy scene stuff" and it is not where the vast majority of people should be looking

steel oak
#

.scn.ron should maybe be deprecated. People keep trying to use it and then discovering assets/handles don't work, which makes it functionally useless

split harness
steel oak
#

I mean .scn in general πŸ™‚

split harness
#

Gotcha. I do think that it should be removed ultimately, but its filling a role that is valuable to some people iirc

steel oak
#

Component serialization is useful for things like the BRP but serializing an entire scene at once to disk in .scn/.scn.ron format in the hopes of loading it later is rarely useful, because it only really works if you have no assets in the scene, which is ~never true for real games

split harness
#

"world dumping and reloading" (with configurable filters)

split harness
#

But yeah I think bevy_scene in its current form is a niche that most people shouldn't care about

steel oak
#

If you throw a ReflectSerializerProcessor/ReflectDeserializerProcessor on top of it to process Handles properly, then it is useful and I think most useful community scene formats are built on top of it

#

It still doesn't have any solution for prefabs/overrides, but it's fine for what it is

split harness
steel oak
#

Incidentally, maybe you've already changed this in your branch but one of the things I found really confusing was the name Scene to mean (AFAICT) "a fragment of the tree"

#

The word "scene" implies something big and broad

#

but single entities are Scenes, the way it is now

#

Maybe Collection or something would be less confusing, IDK

#

I know it's not a tree which is why "subtree" would be inaccurate, but it would give a clearer mental picture

lusty epoch
steel oak
#

The other relatively-minor-but-still-annoying issue is that anything based on component de/serialization works well on POD components and works much less well on non-POD components (e.g. Avian colliders). My app has tons of bespoke components with names like ColliderProxy that exist only to provide a POD interface that can be deserialized to the real un-serializable components like Collider

#

There are a lot of Bevy crates, both first- and third-party, that have components with comments like // #[derive(Serialize, Deserialize)] FIXME make serializable after figuring out some way to serialize field 'wibble'

lusty epoch
#

what's a Pod component?

steel oak
#

Plain Old Data

lusty epoch
steel oak
#

Templates formalize the notion of a "proxy" and allow you to create them in a principled way instead of sprinkling a million add hooks everywhere.

#

I don't have time to hack on BSN right now so I'm going back to shepherding my rendering patches. It's not like this stuff will realistically be usable before 0.19 so I've got plenty of time.

@split harness I would recommend checking what I did with ErasedTemplate to switch from downcast-rs to core::any::Any and PartialReflect because I can't think of any way to implement dynamic BSN the way you wrote it. It's not a big change.

#

I'd say I've done a nice PoC of dynamic BSN with the noticeable exception of the fact that I assume the template of an object is the object itself, which is not true for Handles and requires a ReflectGetTemplate to fix, but should be doable without rewriting too much.

lime veldt
topaz ginkgo
dapper sky
#

Been going through the tests to see the breadth of what's initially possible and I'm really, really excited for the way name references can be used within a scene.

#

specifically across hierarchies.

dusk aurora
#

I've been looking at BSN and some of the recent experiments, as well as the chats and am wondering if BSN (and the macro) is primarily intended for composition/UI.

It does seem to me that way, if so I think a fitting name would be bevy_compose.

I am also a bit worried that serialization isn't a priority. Isn't the core of a scene system like this loading/changing/saving scenes?

In theory it sounds great, don't get me wrong, but I think using a macro for composition is already quite controversial and light years away from something like tsx when it comes to the actual dev-ex imo. Declaring full scene hierarchies + "effects" + observers with it seems a bit scary and like it would require recompilation for changes, not to mention numerous known issues/bugs when working with macros.

Am I missing something? I would love to understand but right now I am struggling to get the value other than for the mentioned composition. As others have pointed out I also think the "true" AST is the ECS World itself... that is the final representation of the scene. BSN feels like a layer of indirection that moves us away from that core.

I think with the reflection ground work that has been done and BRP, using the ecs as core makes total sense and honestly you could make a pretty strong argument for how the macro bsn approach conflicts with the ecs philosophy but that's not my goal here, I'm looking at this from a usage and architectural perspective and both feel off to me personally.

If it is mainly about composition (from rust), I might've just misunderstood and I appreciate the work either way just to be perfectly clear. I would think of it then more like rust macro dsl for mainly composition and UI.

dapper sky
#

I can't answer much of this authoritatively but scene/prefab is the language used in other game engines, and while this is currently a macro its development is laying the groundwork for the .bsn on-disk asset format (which pcwalton and others are building prototypes of for their own teams now the semantics and mechanics are pretty solidly nailed down)

dusk aurora
#

Yea I don't see how that connects then, as others mentioned I think that's putting another layer between the "core" and format/transformation (e.g. a mapper) for no reason but maybe I am missing something.

#

I don't think that the prefabs do that in the other engines but I would have to check what exactly they do. From what I understand they are snapshots.

dapper sky
#

Not quite. They're more like dependency graphs, especially in something like Godot.

#

I think I'm struggling to see exactly where the conflict you're observing is?

dusk aurora
#

I'm trying to clarify my understanding mostly while suggesting a name that seems more accurate to me (currently)

#

I don't think that it's a bad thing or anything

dapper sky
#

Right ^^

dusk aurora
#

I just don't see how it would help me other than for composition in a few places in practice

#

that's mainly it

#

and from an architectural standpoint, I think it has been explained before. To me the ecs is the core, so it's the only "dependency" that is touched by all layers, it's the domain language and protocol essentially for anything that happens, so it's the source of truth or at least the model that holds it.

#

does that make sense?

#

Others have explained it before as well I think

#

I'm pretty much talking about the same thing more or less

dapper sky
#

Are you reckoning about source of truth in an eventual editor or in the context of bsn being deployed within an ecs in an editorless world?

dusk aurora
#

Well you're kinda making my point for me, none of these have to know about each other in an ideal world.

#

just the ecs

#

but yea in this context especially

dapper sky
#

I mean, the ECS is something bsn happens to more than anything.

dusk aurora
#

bsn is like a blueprint to create ecs stuff

dapper sky
#

yeah

dusk aurora
#

exactly

#

it is one way though (afaik), which is why I suggested compose

dapper sky
#

I think my understanding of the knowledge graph here is that The Editor knows about BSN, and BSN knows about Component Types + specific named functions registered for the purpose of being used in bsn (like px). But the ECS doesn't know about BSN, or the Editor. and BSN doesn't know about The Editor either.

#

I think compose makes plenty of sense, but it doesn't line up with artist's and game developer's expectations.

dusk aurora
#

but bsn doesn't either with mine (as a game dev and artist)

#

for a scene format that is

dapper sky
#

(I don't intend to come off condescending I think we're all trying to ingest what's going on now it's all coming together :') but I apologise if I have been )

dusk aurora
#

yea no worries, likewise πŸ’š

#

I'm trying to understand the details

dapper sky
dusk aurora
#

I think it's probaby mostly about editing scenes imo

#

other stuff is too niche

dapper sky
#

disk assets or hot-reloading in-code ones?

dusk aurora
dusk aurora
#

it does line up with expectations as a pure rust dev πŸ˜›

#

but yea that's besides the point I think

steel oak
#

Honestly I really recommend that you try to build a game or simple demo using .scn/.scn.ron. Like including colliders, VFX, and so forth. You see what the problems are with just using the ECS really quickly

dusk aurora
#

I ran into some of them with avian and have some problems with hybrid procedural assets where I'm a bit hesitant to implement alternatives currently

#

I'm not saying these problems don't exist

dapper sky
# dusk aurora I get the mental model of that but I'm not understanding what bsn does when it s...

My understanding, which could be wrong, is that when you create a scene with a single component Velocity(Vec2) that impls Default and GetTemplate you get a scene file like:

Velocity

and when you adjust the x field of the Velocity in-editor to i.e. 42.0 you get

Velocity { x: 42.0 }

and then you "link a dependency" of another bsn file my_bullet.bsn (I can't find a reference to current import syntax atm)

Velocity { x: 42.0 }
Children [ @"my_bullet.bsn" ]

Then we load that, and our bsn file resolves into an entity with a velocity + a bullet child. We could then have a button in our game that re-serializes that as a bsn file but it might look like:

Velocity { x: 42.0, y: 0.0 }
Transform2d { ... }
Children [
  Transform2d { ... }
  AssetReferenceIdk("Bullet.png")
  BulletMarkerType
  Children [ ParticleEffectTarget(...) ]
  ...
]

Which would not be kosher for the intended editor workflow. But on a technical level would be possible, just messy.

#

that is, bsn isn't a serialize-to format (though it technically could be) but a serialize-from format that is optimised for "patches" on data. Again I'm kinda struggling on what to say cos I'm kinda half asleep and still not entirely sure about what to explain myself.

dusk aurora
dapper sky
#

So "the editor" operates on bsn, but also "the editor" is just a computer program and other functionality can and will be bolted onto it as needed / discussed / etc.

steel oak
#

Like Collider isn't Reflect in Avian so a generic editor can't usefully edit it. Instead you have to use ColliderConstructor which comes with a system that converts ColliderConstructor to Collider. So a hypothetical ECS based editor wouldn't know about the link between ColliderConstructor and Collider.

Templates are just a formalization of the ColliderConstructor pattern, with enough engine-level support that editors can understand it in a generic way. In BSN speak, ColliderConstructor is the template and Collider is the component. With BSN the editor understands the link between ColliderConstructor and Collider and knows "oh, OK, so what I'm editing is the ColliderConstructor and what will actually appear on the entity is the Collider". And it can do that without having to recompile the editor to understand Avian, because that info is all in the reflection metadata which it can slurp from the BRP just like Skein does.

dusk aurora
dapper sky
dusk aurora
#

I'm all for a file format like that, just to be clear again. This is my expectation pretty much from a system like that. The macro is also cool but I think it shines in other areas personally.

steel oak
#

If I were designing BSN I would have started with the file format and done the macro later, but I understand why cart went the other way.

#

Anyway, I'm doing the file format now, so no big deal πŸ™‚

#

The macro is cool but you can make a game without it (constructing Unity GameObjects in code is pretty verbose and people have shipped a million games with it). The file format though is necessary to ship anything that isn't an extremely procedural game since it's the data model of the editor.

#

But this is a minor gripe and I'm solving it, so

dapper sky
#

Yeah, the macro is a superset from which .bsn is easily derived from.

#

(conceptually)

steel oak
#

It is cool that you can just copy paste your scene file into code and vice versa, don't get me wrong.

magic belfry
# steel oak Like `Collider` isn't `Reflect` in Avian so a generic editor can't usefully edit...

(we'll most likely end up changing to having a general reflectable Collider API component that "describes" the collider's shape, and then a separate non-reflectable ComputedCollider or similar that has scale and preprocessing etc. baked in and is used for the actual collision detection stuff, but yeah the point still stands and is accurate to the current state of things πŸ™‚)

steel oak
#

Or well, more accurately, you just make ColliderConstructor a Template and keep it around

magic belfry
#

Hm probably not? But I'll have to look more into templates

steel oak
#

I think basically all you have to do is say impl GetTemplate for Collider { type Template = ColliderConstructor; }

#

and then impl Template for ColliderConstructor { fn apply(...) { ... build the collider ... } }

#

Doing it that way means the editor becomes aware of the link between colliders and collider constructors

lusty epoch
#

not sure if Collider should be assets, I remember in rapier Collider are internally Arc-ed, so performance is better?

magic belfry
# steel oak I think basically all you have to do is say `impl GetTemplate for Collider { typ...

The gist is that right now Collider stores both an unscaled and scaled version of the given collider, and then the reflectable ColliderConstructor is a separate thing that only constructs a collider once, intended for skein-like workflows. You can't change a ColliderConstructor at runtime and have it affect the Collider. So the "unscaled" shape stored in Collider is the actual source of truth, it can just be instantiated with ColliderConstructor

#

The proposed change I've been wanting to experiment with is removing ColliderConstructor, but splitting apart Collider such that the unscaled shape is the new Collider, which is reflectable, and then that is used to construct and update the ComputedCollider, which includes scale and whatever preprocessing needs to be done on top of the raw geometric description in Collider

#

The eventual plan there would be that we can upstream Collider as the general physics engine agnostic collider API, and then each physics engine can implement their own internal collider type that is computed and updated based on the Collider

steel oak
magic belfry
#

Ultimately Collider needs to be the source of truth that you can modify at runtime and have it affect the downstream "computed" colliders; it's somewhat unclear to me if this can also be a Template or if templates are an instantiation-time kind of thing

#

But I think it could be a Template, yeah

magic belfry
#

(Arcs could still be best, but it may be useful trying out other approaches too)

dapper sky
# dapper sky Been going through the tests to see the breadth of what's initially possible and...

Genuinely I am so excited for this though, even if I'm still hand-authoring for the time being. I want to see if you can construct

#A
Ref(#D)
Children [
  #B
  Children [
    #C
    Children [
      #D
      Ref(#A)
    ]
  ]
]

in-tests (it seems to be the version of this that's dodged atm), but that you can just easily express these kinds of connections is incredible.

Edit: yeah this just works fine. Really happy to see.

magic belfry
#

the timeline also obviously wasn't meant to be nearly as long as it has been

#

either way, happy to see you working on the file format, exciting stuff πŸ˜„

exotic panther
#

the asset format would also require versioning which feels very complicated

steel oak
steel oak
wooden vine
steel oak
#

OK, my dynamic-bsn branch now has the ability to reflect templates with ReflectTemplate/ReflectGetTemplate and so you can create templates that aren't identical to the original components and it all works.

#

Next thing will be to add a hack that adds the magic Into behavior for HandleTemplate, so you can write asset paths as strings. The right solution would be something like ReflectConvert but that would be scope creep.

round totem
#

And bevy having an inline bsn! like how Yew has inline html! is incredibly cool and useful for quick inlining without having to load assets.

silk lava
#

I think doing the macro first was the right play, with the only real downside being if a certain feature can't be supported but exists in the macro.

golden notch
split harness
# steel oak The word "scene" implies something big and broad

I still think Scene is the right name. This is still a valid Scene, even though it is "just" a single piece:

fn foo() -> impl Scene {
    bsn! {
        Position { x: 10. }
    }
}

In this case it is a TemplatePatch<Position> which impls Scene.

It interacts with the rest of the scene system in the same way as a more complicated "full" example would (or a "big / broad" scene as you put it), and it can be used in all of the same places

fn level() -> -> impl Scene {
    bsn! {
        :foo
        LevelRoot
        Children [
            /* pretend this has many children */
        ]
    }
}

This type of recursive compositional typing is also just cleaner/simpler for accomplishing this goal. Introducing a second trait for "single" pieces would cause discontinuities in the type system and make it all less usable. We could call the single unified trait SceneFragment or something and defining scenes in code would look like this:

fn foo() -> impl SceneFragment {
    bsn! {
        Position { x: 10. }
    }
}

But from my perspective this is wrong. It is returning valid semanatic BSN (whether it is a single "piece" or multiple). Bevy scenes are conceptually compositional in the same way as the trait. We don't call them .bsnf files (Bevy Scene Fragment files), and I think introducing that naming would be unhelpful / confusing / overly jargon-ey.

split harness
round totem
#

I'm already Godot brained enough to see tscn "scenes" for everything. Having bevy also call them "scenes" is fine as far as I go

split harness
# dusk aurora I've been looking at BSN and some of the recent experiments, as well as the chat...

I am also a bit worried that serialization isn't a priority. Isn't the core of a scene system like this loading/changing/saving scenes?
If it is mainly about composition (from rust), I might've just misunderstood and I appreciate the work either way just to be perfectly clear. I would think of it then more like rust macro dsl for mainly composition and UI.
It is built with scene files / serialization in mind. I encourage you to read the design docs and draft PR: https://github.com/bevyengine/bevy/issues/23030#issue-3955341425.

Most of the groundwork has been laid / the in memory asset system is already present. The only missing piece is the actual serialization / deserialization bit, which is comparatively straightforward.

split harness
# steel oak If I were designing BSN I would have started with the file format and done the m...

FWIW the asset format and the macro were initially designed and implemented in parallel, in the interest of proving out the concepts. During the latest rearchitecture I prioritized the macro / in memory bits as an optimization because that is where most of the unknowns and complexity were, and that is what things like Bevy Feathers will use / what we'll use to build the editor UI

#

As I mentioned, I already have a recursive descent BSN asset format deserializer / AssetLoader for an earlier version of BSN. It has just diverged enough from the latest version that starting over is more productive

steel oak
#

Just pushed support for handles to my dynamic-bsn branch

split harness
# magic belfry Ultimately `Collider` needs to be the source of truth that you can modify at run...

Templates can be rebuilt at runtime (by calling template.build_template(context)). This requires a TemplateContext, which can be constructed from an EntityWorldMut. Currently there isn't a helper to make that easier (ex: let collider = entity_mut.build_template(ColliderTemplate::default())?;), but we can/should add that eventually.

But if the Goal is to ergonomically mutate something at runtime, it is likely best to do that work on the output of the Template (ex: the Collider), unless you benefit from / need the access to World / the current entity context.

near warren
steel oak
#

Should just need a few more types (floats, vectors) and a sprinkling of #[reflect(Template)]/#[reflect(GetTemplate)] and then .bsn assets should be mostly usable

#

and code cleanup, lots of code cleanup, it's a mess

steel oak
steel oak
near warren
#

Thanks

steel oak
#

Warning, super ugly

karmic rock
split harness
#

"Intent to be experienced" can be encoded in other ways:

  1. Storing a scene in an asset file
  2. Assigning the scene to a type (ex: the bsn!{ Button("My Button") } that both @rare whale and I want)
#

But there are also benefits. When "everything is a scene regardless of whether it is intended to be a 'piece' or a 'whole'", then you can use scene assets for "patch / style" scenarios freely. If we arbitrarily limited the scene asset file to being a "whole" , then it wouldn't be usable there.

#

At the end of the day, we could add that type of restriction later if people don't like it in practice. However I suspect that in general, people will appreciate the "everything is a scene and cross compatible across use cases" aspect

heavy valve
#

Getting the perfect label is less important than getting a consistent and specific use for the label

round totem
heavy valve
#

(and I think this division accomplishes that)

round totem
#

As Godot is propping itself up to be a MAJOR indie game engine (slay the spire 2 uses it) I think more indie devs will be used to the idea of everything being a scene

split harness
#

@rare whale I think it is time to start prepping a Feathers BSN port, as I think landing them together is valuable. I've done that once before / I could probably bang it out pretty quickly while the BSN PR is in review, but if you want to do that now you'd have a head start on me.

round totem
#

After all, what is a scene but a collection of items? What is a player but a collection of items like weapons, shields, etc. Why differentiate so arbitrarily?

dusk aurora
# split harness > I am also a bit worried that serialization isn't a priority. Isn't the core of...

Thanks. I have read it and everything I could find before posting.
I was mostly responding to the discussion about the naming and trying to understand the current state. I think the confusion comes from prioritization.
If it is relatively straight forward then it is low hanging fruit imo and it seems that it is high priority to others - myself included. As I said I still appreciate it, I just wanted clarification πŸ‘

rare whale
#

I'm ok with using temporary names for the template functions while we sort things out

split harness
#

Ideally before next release

  • [ ] Feathers BSN Port: Largely already done. Just need to reconcile with current state of main. This will help BSN land well, so landing it alongside BSN is a high priority.
  • [ ] #Name references in more places: The UI eventing scenario really wants #Name to be usable in closures. This would functionally be expressed as a template that returns a closure that accesses a specific entity. This unlocks a lot of value for UI devs, so ideally it lands alongside BSN.
  • [ ] Top-down vs bottom-up spawn order: Currently BSN follows the normal bevy top-down spawn order. I think we should heavily consider spawning bottom-up, in the interest of making scene contents available to "higher level" components in their lifecycle events (ex: a Player component accessing nested entities like "equipment" when inserted). If we decide to keep things as they are, we probably want to introduce additional "scene ready" entity events that trigger "bottom up".
  • [ ] Struct-style inheritance: It would be nice to be able to do something like :Button { prop } instead of :button(prop). I'd really like us to explore this being component-tied (ex: associate a scene with a Button component).
  • [ ] ResolvedScene-as-dynamic-bundle: ResolvedScene should insert all of the components at once as a single bundle, rather than one-by-one, which is really bad from an archetype move perspective.
  • [ ] Inline field value expressions: Support cases such as `px(10).all()
  • [ ] derive(GetTemplate) generics ergonomics
#

Some of those (such as ResolvedScene-as-dynamic-bundle) are reasonable chunks of work / very unlikely to land in time

#

Given that BSN is already barely squeezing in, its very possible that none of these will land πŸ™‚

rare whale
#

Let me go over the issues I am concerned with the non-BSN API for feathers:

  • Originally I had thought to allow users to pass in a bundle of "override" components that would be patched in, allowing them to do things like replace specific components (SliderRange etc.) in the same way that BSN does - turns out that this doesn't work, and I removed the overrides parameter in a later PR but I missed a few places that were on a different branch. Currently there's no good solution, but I have talked about this in ecs-dev.
  • In my own branches, I have several "container" components (menu button, title bar, etc.) which only have BSN APIs, because I'm not sure how the non-BSN API should work. In the case of panel or title bar, it's about the widget being able to decide where the children should go; in the case of menu it's about the children being created lazily (we don't want menu items hanging around, invisible, when the menu isn't open).
rare whale
split harness
split harness
#

But I'm happy to keep the bundle functions around / try to support what we can

rare whale
split harness
cerulean mango
#

re: Top-down vs bottom-up spawn order: the bevy_editor_prototypes proto_bsn version uses bottom-up and it's very intuitive to work with. I do agree that the "scene ready" event is crucial to have there, but it's probably a must have for top-down as well, I'd figure.

split harness
#

In my own branches, I have several "container" components (menu button, title bar, etc.) which only have BSN APIs
Given that these aren't currently on main, we don't need to land them in 0.19

#

Although it would be nice to

rare whale
steel oak
split harness
#

And those are already ported

rare whale
steel oak
#

I posted a proposal for how to develop the editor alongside BSN features in #editor-dev

steel oak
#

I've noticed one common failure mode is forgetting to say #[reflect(GetTemplate)] when you write #[derive(GetTemplate)] on a component that has handles in it. You end up with a confusing error message as the deserializer assumes that, because the type didn't have a custom GetTemplate implementation, that must mean that it implements Default and Clone, which it doesn't because it has handles, and so you get an error message mentioning Default when the error has nothing to do with that. Probably worth thinking about how to improve this error message.

dapper sky
#

Oh my goodness it's really coming together

steel oak
#

Missing features are:

  • bool literals
  • int literals
  • @ (TBH I don't even fully understand what it does)
  • : inheritance is untested, it should work in theory but you know how untested things usually are
  • comments
#

Notice what is supported: #Name, Default, unit variants, unit structs, tuple-like variants, tuple-like structs, Struct { ... }, float literals, Children relations, arbitrary GetTemplate/Templates that don't have to match the type, and a magic hack to allow the string literal -> AssetPath conversion so that handles work (this should become something more principled eventually)

steel oak
#

@split harness Just as a heads up, if you allow putting arbitrary things in {} then I think the grammar might not be LR(1) anymore. Because you can't tell whether Foo . { foo : is supposed to shift or reduce (to a unit struct Foo) without seeing the : and that's 3 tokens of lookahead.

#

And if you allow arbitrary things to be in () it's straight up ambiguous because Foo(Bar) could be an enum variant Foo(Bar) or two unit enum variants, Foo and Bar (the second one needlessly parenthesized)

#

Oh, also if you let things be put in {} that's actually technically straight up ambiguous, not just not LR(1), because {} is mostly a synonym for () in Rust and so Foo{} is ambiguous between a struct Foo {} and a unit enum variant Foo followed by a template which is () (though () isn't a valid Template so you could just rule that out at the grammar level)

#

The LR(1) problem is seriously annoying though. I'm not sure if I can factor the grammar to try to eliminate it. As a worst case I could implement a lexer hack with 3 tokens of lookahead. Not being LL(1) or LR(1) kind of sucks though for tooling...

steel oak
#

@split harness Yeah, I don't know if I can make this LR(1). I hate to suggest this but I would recommend changing the BSN grammar because it's too hard to parse right now.

#

Not being LL(1) means you can't write a handwritten recursive descent parser and that's just bad. You're saved by the fact that macro rules is an Earley parser or something, but that's O(n^3)

#

Actually hmm, it looks like you're LL(1) right now because you have a handwritten parser? I need to study your parser more closely

lusty epoch
#

is there a Rust implementation of TreeSitter or Lezer? Their grammar is very powerful. I am not sure why we must force the grammar to be lr(1) or ll(1). This seems limit the expressiveness of the grammar.

steel oak
#

I'm not interested in debating which parsing algorithm is the best. The point is that people will want to write LL(1) parsers because those are the simplest to write

#

@split harness Oh, I just noticed you're using capitalization as part of your parsing to try to detect whether parts of a path are modules or variants or constants? I really object to this πŸ™‚

#

I mean, maybe if it's absolutely necessary, but there should be some way to override it

fallow cloak
steel oak
#

BsnEntry::Parse has an if input.peek(Brace) { ... }

#

I think bare {...} is for embedding arbitrary Rust expressions that the cover grammar doesn't allow for

fallow cloak
#

ah yeah that's not great

steel oak
#

I think the easiest fix might be to change { ... } to ({ ... })

#

since I think { ... } isn't that commonly used?

#

if I change it to ({ ... }) then LALRPOP reports no more conflicts

fallow cloak
#

I think we can always inherit rust scene variables from outside, or call fn() -> impl Scene

steel oak
#

actually sorry, ({ ... }) doesn't fix it either

steel oak
#

TBH when I saw that BSN had changed to not require any separators between patches my ambiguity spidey sense went off

#

I have battle scars from this stuff

#

ugh, it seems to be load bearing and I don't know why

#

I can't remove the {} in bsn.rs without errors

#

OK, I can remove all of them in the bsn.rs example but one: changing {sprites} to sprites causes an error because I guess it's looking for an impl Scene but it has a Vec<impl Scene>. IMO if the only thing we're using {foo} for is to embed a Vec there are other ways to do it, like ...sprites. But I also don't understand why it couldn't just be sprites, maybe that's a bug?

#

In any case I'm not going to implement {foo} in dynamic BSN pending a decision from @split harness.

#

More broadly, I get why the decision was made to have no separator, because the alternatives are really verbose from what I can see, and except for this {} thing LALRPOP confirms there is no ambiguity, but we're skating on thin ice

lusty epoch
#

I think no seperator so the grammar is not that strict so people can write it easier. But I think maybe consider do it like "js automatic semicolon insertion". So the grammar is a regular & strict one with seperators, then you still allow user write without it

steel oak
#

Oh no, no ASI please πŸ™‚

#

You have no idea how much that constraints the further evolution of the language

#

Listening to TC39 gripes it's like 80% of the language proposals for JS end up getting immediately shot down because they would cause a backwards incompatibility hazard due to ASI

#

It's just a mistake

#

My worry is that if we do need arbitrary expressions we don't have a lot of tasteful options, short of something like $(...) or expr(...)

fallow cloak
#

# all day

steel oak
#

Lua has this problem btw, because they have no separators, f()(x()) is ambiguous between f()(x()); and f(); (x()); In this case they actually are whitespace sensitive to break the ambiguity, but this isn't an option because bsn! is a macro and can't modify the Rust lexer

lusty epoch
#

(at least I prefer it compared to no seperators

steel oak
#

If we have to keep the grammar as is there is a backup lexer hack that I think mostly works. You define two types of {, "struct {" and "other {". When you see { you look ahead 2 tokens. If the next 2 tokens are IDENT ":" or the next 1 token is } it's a struct {. Otherwise it's a other {.

#

You decide for yourself how tasteful that is. πŸ™‚

#

But intellectual honesty requires that I mention it

#

Anyway, none of this is necessary for unblocking the editor (and my project's migration to BSN). I think all I need is a little more work on the lexer, a few more literal types, and updating to cart's current branch, and the editor is unblocked.

split harness
#

But for the few cases where the ambiguity comes into play (edit: or people choose to not follow conventions), its worth having a break-glass option

split harness
split harness
split harness
split harness
#

Its like doing this at the top level:

let transform = bsn! { Transform { position: { x: 10. } }};
bsn! {
  transform
}
#

Or this with children:

let transform = bsn! { Transform { position: { x: 10. } }};
bsn! {
  #Root
  Children [
    transform
  ]
}
#

Definitely a bit weird, because these behave differently:

let transform = bsn! { Transform { position: { x: 10. } }};
bsn! {
  {transform} // Assumed to be a Scene
} 

bsn! {
  #Root
  Children [
    {transform} // Assumed to be a SceneList
  ]
}
split harness
#

Or alternatively, requiring () for all child / related entities

split harness
#

This is what enables:

Children [
  Node { width: px(10) }
]
#

And

Children [
  Node { width: px(10) },
  Node { width: px(10) },
]
exotic pecan
#

Throwing one more name idea in the ring: bevy_clutch

#

Bird jargon concerning groups of eggs

#

Haven’t seen it used for an existing crate

coarse patrol
#

Maybe a more literal name would be nice? Like just something that describes exactly what it does in 1-2 words?

slate pewter
#

i like bevy_scene. it'd be where bevy scene (notation) lives πŸ˜„

exotic pecan
#

It sounds like the name is only a question because both the old and new modules and types will coexist, because the new stuff isn’t yet a total replacement for the old stuff (and might never be)

dapper sky
#

I do think scene is a good name to stick with and fits with how peers (like Godot) use it.

exotic pecan
#

I don’t think scene is a bad name at all, but what do you call the other scene? You’d have bevy_scene::Scene and bevy_scene::Scene

#

But you can’t

#

So one of them has to change

#

Vignette? Tableau?

dapper sky
#

rename the old one to UncoolScene, AdvertisementSceneForBsn, or NaiveScene 😌

#

ScenePoser

#

SceneFromBeforeItWasCool

lime veldt
#

NSFW scenes should be called Obscene

steel oak
#

Oh, wait, I bet @ means "look up the Template with this name rather than the GetTemplate"?

#

Ah yeah, exactly

#

OK, that's the last thing I need to implement then.

#

Here's where I ran into it: There is a component called CascadeShadowConfig. It has a fairly low-level API which specifies the distances as raw values and isn't very user-friendly to use, so there's a user-friendly shim on top called the CascadeShadowConfigBuilder. In the editor you should be editing a CascadeShadowConfigBuilder, not a CascadeShadowConfig. This is precisely the Component/Template distinction that people keep reinventing, just implemented yet again in an ad-hoc way. BSN allows us to express this pattern in a less ad-hoc way, and unlike every other scene format proposed for Bevy actually allows the scene format to embed CascadeShadowConfigBuilders.

#

In fact... maybe most of the examples should be reworked to use dynamic BSN? Because people will want to open them up in the editor!

#

It's also a stress test for dynamic BSN to make sure it's actually useful for dogfooding

#

We'll probably want some convenience templates for things like creating cube meshes and simple StandardMaterials for colored cubes and whatnot

dapper sky
#

Almost definitely yeah, we also now have support for viewing multiple files in bevy examples so even viewing them in-browser is somewhat straightforward.

#

I've been holding off on adding better docs to examples largely because there will be a bsn reckoning to them.

#

(also I've been busy, or tired, or otherwise occupied)

steel oak
#

OK, I've now fully recreated the load_gltf example using this dynamic BSN file: https://github.com/pcwalton/bevy/blob/dynamic-bsn/assets/scenes/example.bsn
Since the last time, I added @ templates, bool/int literals, and comments.
That's basically it except for tuple struct expressions and use. (I don't feel like use is that important though because editors will probably not have much use for it and I suspect .bsn is going to mostly be edited graphically. Editors should probably avoid use in fact as it tends to cause merge conflicts.)

GitHub

A refreshingly simple data-driven game engine built in Rust - pcwalton/bevy

split harness
cobalt stone
steel oak
steel oak
steel oak
steel oak
#

Though, I suppose the BRP could be an alternative.

silk lava
#

Why not have both the example code, which uses bsn! where it makes sense, and then have the .bsn for users to read/use.

viral roost
steel oak
# viral roost Definitely need import syntax πŸ™‚

I'd take a PR to add it but I'm not likely to add it myself. For me dynamic BSN isn't so much about hand editing, as you can do that with the bsn! macro and the experience is better because you get autocomplete. Rather, dynamic BSN is the format I intend to use for machine reading and writing.

Of course I'm not questioning the decision to have use in BSN, just saying I won't be the one to implement it πŸ™‚

rare whale
#

I think there are potentially three different dialects of BSN assets:

  • "ergonomic" BSN - intended to maximize readability and human authorability
  • "normalized" BSN - intended for ease of parsing and machine readability
  • "compressed" BSN - intended for optimum loading speed
    So "use" would be a feature of ergonomic BSN (to conform with DRY). Compressed BSN would have a string table at the front and reference all identifiers by their index in the table.
steel oak
rare whale
steel oak
#

But yes, a "real" format for compressed BSN would be good to have

rare whale
steel oak
#

BTW my dynamic-bsn branch has been revised to use the ECS instead of SlotMap. cc @white lichen

#

All I need to do now is to update to cart's latest branch and I'll be good to start migrating to it in my project in preparation for 0.19.

rare whale
#

Also, self-nit: I'm not sure whether "normalized" or "demormalized" is the right term here. The analogy to "normal form" in the RDMS sense is imperfect.

white lichen
#

ill take a look

steel oak
#

Note that I still throw the temporary World I build away in the AssetLoader because I'm not sure where to put it. Probably needs design input from cart

#

For a "level 1" editor throwing away the World is fine, but levels 2 and above need the BSN World to be persistent.

#

@split harness Have you given thought to how to provide patches to glTF files? For example, "instantiate Player.gltf and attach a particle effect to the node named #Sword". Or "instantiate FlightHelmet.gltf and add iridescence to the material of the object named #Goggles"

#

Having the ability to do that would be such a breath of fresh air compared to the current approach of "have a system that watches the scene for objects with certain names"

#

I guess you'd have a special AssetLoader for glTF that imports them "as though they were BSN" (i.e. to a ScenePatch)?

#

Then you could inherit from glTF, because it'd be just another way to get BSN as far as Bevy is concerned.

#

Anyway I answered my own question. Ugh, I want BSN now πŸ™‚ It's a night and day difference in how Bevy games are constructed

#

At least games that have to work with a lot of art assets

steel oak
#

This is essential functionality for most games BTW.

#

Or maybe I can build this with a custom Template? Because it looks like ResolvedScene::apply builds the inherited scene first before running child templates. So maybe I can poke around the EntityWorldMut I got to find the inherited entities and munge them in my template.

#

Something like a custom struct DescendantOverrides(HashMap<Name, Vec<Box<dyn ErasedTemplate>>);

#

Or I guess struct DescendantOverride(Name, Vec<Box<dyn ErasedTemplate>>). In the guts of DescendantOverride you search your subtree for an entity with the given Name and apply your templates.

This is something that can be prototyped out of tree but I think an editor is going to want to know about things like DescendantOverride because of the workflow whereby you drag a glTF into the scene, then click the dropdown to find some bone or sub-mesh and change a property on it. You'll want the editor to automatically generate DescendantOverride templates on the root entity. Unless the developer right clicks and says "Unpack" or whatever, at which point the templates of the prefab will get copy pasted into the .bsn file.

#

I know at least in Unity this workflow is supported, but with limitations: there is no reordering and no deletion of prefab descendants (I think?). It's only additive. It's important that the additive workflow is supported though because of the common workflow whereby artists create entire model subtrees in Maya/Blender and then import them into the game engine where game-specific components are then added.

steel oak
#

My dynamic-bsn branch is now updated to cart's latest branch.

steel oak
#

I did a spike and I think that I can do something like @DescendantPatch::new("Sword", MyParticleEffect { ... }). This isn't the ideal syntax but I think it works. I'll try it more tomorrow.

sand crag
#

I was talking about something like this a while ago.
Users that prefer to compose big scenes in external tools (and number of such users will grow with USD / glTF references) would want to attach components on asset import.
And even users that work with small glTFs will often encounter this too.
For example when importing a car user may want to insert components on doors, wheels, headlights, trunk.

#

There should be a way to reference assets internal object by name on import and append needed components. And maybe even remove/replace components.

sand crag
# steel oak I did a spike and I *think* that I can do something like `@DescendantPatch::new(...

We should also take into account that user may import a file that references sub files.
For example user imports USD / glTF (with external ref support) file that references a couple of files that all contain internal object with the same name "Sword".
User may want to insert component on "Sword" only in sub file A and not B.
To make this work we probably need to allow referencing a file internal object by full name. Something like "A.gltf/Weapons/Sword".

coarse patrol
steel oak
#

OK, I got this working in a proof of concept branch:

    bsn! {
        :"scene://ui.bsn"
        @DescendantPatch::new("OkButton", Text("Hello world".to_owned()))
    }

Where the DescendantPatch call means "find an entity called OkButton in the subtree and apply the given template". The resulting scene changes the text of the OK button to "Hello world".

#

@split harness I'm curious what you think about the above DescendantPatch when you get a chance. Not sure if I did this in the way you were imagining or not. I imagine you were probably thinking about having some sort of built-in support for this in BSN eventually? In any case it's good that third-party crates seem to be able to do it for now.

magic belfry
# steel oak OK, I got this working in [a proof of concept branch](https://github.com/pcwalto...

If I understand correctly, this would pretty much replace Avian's ad-hoc version of this, which lets you configure collision layers etc. for colliders that are generated for a scene

// Specify configuration for specific meshes by name
commands.spawn((
    SceneRoot(scene.clone()),
    ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh)
        .with_constructor_for_name("Tree", ColliderConstructor::ConvexHullFromMesh)
        .with_layers_for_name("Tree", CollisionLayers::from_bits(0b0010, 0b1111))
        .with_density_for_name("Tree", 2.5),
));
#

If so, this would be very useful for me

steel oak
#

This is pretty essential functionality for most artist workflows.

#

You could even imagine some sort of XPath-like syntax.

magic belfry
#

Cool! Yeah this has been a major pain point with Bevy's scenes IME, so I'd love to see something like this

buoyant venture
#

In this specific case I do think it's something that should probably be built-in but it would be nice if bsn made it easier to do something like that user side

rare whale
steel oak
split harness
split harness
steel oak
split harness
rare whale
# steel oak Yep. Also note that this has a hack that propagates the templates to all childre...

Understood. When it comes to templates that create hierarchies, there are two schools of thought - one team (which I prefer) likes the child hierarchies to be encapsulated black boxes with a well-defined surface API; the other team prefers for the hierarchy to be transparent and manipulable from the outside. Having externally visible names is somewhere in between: the child hierarchy gets to decide where the patches go, but not the details of how the patch is applied.

buoyant venture
thick slate
split harness
split harness
#

Iirc there are pieces that need some changes, but the general patching interface and lifecycle already support this to a degree

#

Right the big missing piece right now is doing this correctly / in a copy-on-write way for :scene. If you do "immediate" scene merging with scene(), we could support descendant patching without issue

#

:scene will require additional "smarts"

steel oak
split harness
steel oak
# rare whale Understood. When it comes to templates that create hierarchies, there are two sc...

The problem is really artist workflows. Suppose that you have a character and you want to put a particle effect on the character's weapon so their sword makes a trail. The sword is going to be a node in the FBX file that the artist made in Maya. But there's no way in Maya or FBX to say "this is where the particle effect goes", since it's just a modeling tool. So the only way is to pull in the FBX file as a prefab and poke at individual objects within it.

The only real alternative I can think of would be to teach the modeling program about Bevy components specifically, which is the Skein approach. But that's a radical departure from the typical artist workflow and requires that the modeling tool be taught about Bevy. Maybe that's OK if all the artists use Blender but lots of artists (incl. my entire studio) use Maya instead. Maya does support plugins but it's very version specific and there's a proprietary API and ugh, it's just a mess.

split harness
steel oak
#

We can throw out a ridiculous amount of gross code in my project

split harness
# steel oak Yep. Also note that this has a hack that propagates the templates to all childre...

This is a "big" issue we'll need to sort out, as #Name is not currently something we record in the ResolvedScene and Name (the component) and the EntityPath that builds on it is a post-spawn result. But patching needs to be resolved pre-spawn. #Name is also "scoped" (the same entity can have multiple #Name, with the "newest" / most specific #Name being the final Name)

Also @rare whale

steel oak
split harness
#

Pretty straightforward to store #Name in Scene, but it will have overhead

steel oak
#

This is not great but it's strictly better than what we do today, which is have an entire system that runs every frame scanning for objects with magic names

split harness
#

Sorry descendant patching πŸ™‚

split harness
steel oak
#

And yeah I think we probably want something XPath-like, because Names aren't globally unique

#

Or maybe like CSS selectors

steel oak
#

Oh also, note that this isn't the first time we will have something XPath-like in Bevy. Animation targets also work the same way (they target bones with things like Hips/Stomach/Spine/Neck/Head)

#

@split harness BTW the problem I ran into is that the inherit field on the context stores a handle which just gets instantiated wholesale, so there's no way to insert hooks. I guess what you would want is some sort of list of map from XPath to patch in the context that gets applied as the patching infrastructure descends in the instantiation process?

slender lion
steel oak
# slender lion that's unfortunate to hear maya's plugin apis are a mess. I was hoping we could ...

I'm not an expert here but my understanding is that the problems are (1) Maya's API is a messy C++ API and (2) the API is extremely unstable from version to version, so studios get all their artists on a single version (Maya 2020, Maya 2021, Maya 2022, etc.) and upgrading the plugins is an ordeal. The upshot being that you'd have to maintain versions of Skein for every recent yearly release of Maya.

slender lion
#

after the asset format shakes out I'm hoping to break ground on a blender->bsn exporter this year

steel oak
slender lion
steel oak
#

But yeah, even having post-spawn DescendantPatch will be an enormous cleanliness win for us.

#

Really maybe it should be something like
@Override("#OkButton > Text", Text("Hello world"))

#

Where you give it a CSS selector with child-of, descendant-of, name (ID), and existing component names, and then supply a list of templates to get applied to everything that matches

#

Oh and @split harness if you had the list of current overrides in the context then you could possibly avoid tracking if there aren't any hooks at the current nesting depth. Thus avoiding the problem of overhead with tracking #Name etc

cobalt stone
#

Btw just wanted to say, I've been super busy with other things, but really, really excited to see the amount of progress with this!

#

I'm really excited to jump into editor stuff once the infra is ready

thick slate
steel oak
#

So my current thought is that after 0.19 releases I'll introduce (1) a dynamic-bsn PR, with a BSN viewer tool to form a level 1 editor; (2) a third-party bevy_overrides crate that introduces an @override template that allows for post-spawn overrides based on a CSS-selector-like syntax.

split harness
# steel oak <@153249376947535872> BTW the problem I ran into is that the `inherit` field on ...

Yeah I'm thinking roughly these steps:

  1. Determine child patches / store on context
  2. Resolve inheritance / spawn inherited scene
    2.5. While spawning descendants, check if there is an active patch, and if so, apply the patch

That will have minor performance implications (as we'll need to compute and store the child patches in a map, then copy the relevant templates and apply the patches on top). I think in general this feature is best used in the context of editor-driven scenes, which can generally be fully resolved ahead of time.

#

But my plan for that is to add a "ResolvedScene::flatten" that operates on the unflattened scene and outputs a final flattened ResolvedScene

#

So might as well implement it in such a way that supports it in the unflattened context

split harness
#

Your proposed strategy would work in cases where we're re-computing the whole scene without a shared/precomputed ResolvedScene (for the inherited scene)

plush pier
#

if we were to also get a solution to https://github.com/bevyengine/bevy/issues/17984 the handles-in-scenes problem would be solved fully
I think it's worth considering as I don't think BSN can provide good workarounds for this, as the asset (e.g. large model file) might not already be loaded when the scene is resolved/spawned

GitHub

What problem does this solve or what need does it fill? Today, every subasset must have exactly one label. While this is unambiguous, there are some cases where it would be much more convenient to ...

split harness
#

Ex: I have plans to expand HandleTemplate to be configurable to require the asset to be loaded before spawning. This can be done viaTemplate::register_data (which hasn't been fully wired up yet and should actually probably be removed in the short term)

split harness
#

Yesterday was a bunch of doc writing. Today I should hopefully be able to wrap that up. Then clippy stuff, then PR

#

After the PR is out I'll investigate what to do about impl Default for Handle to make BSN less invasive in the short term.

#

(which would also cut down on the size of the PR a bit)

split harness
#

There are currently a number of gaps / inconsistencies in the "scene functionality" extension traits for World / EntityWorldMut / Commands / EntityCommands that I've encountered as I've documented them. I'm currently filling in those gaps / refactoring some things

rare whale
#

@split harness I just realized, if we make feathers bsn-only, that screws bevy_immediate, which also uses feathers

#

I suppose I should just bite the bullet and do both BSN and non-BSN versions of everything for consistency

split harness
split harness
#

In fact, they already have on_spawn_apply_commands, which supports this without any changes to bevy_immediate needed:

ui.ch().on_spawn_apply_commands(|commands| {
  commands.apply_scene(bsn! { button(ButtonProps::default()) });
})
split harness
#

Although I'm not opposed enough to "supporting bundles where we can" to advocate strongly for their removal.

rare whale
#

Would it help to have a brief migration period of both bsn and non-bsn versions of feathers? By "brief" I'm talking maybe a few weeks.

slender lion
copper dragon
rare whale
split harness
rare whale
#

It's always harder to do a migration if you have to make all the changes before the code will even compile

split harness
#

/ I think thats what we should do

rare whale
copper dragon
split harness
#

Just pushed the following changes:

  1. Filled in the remaining missing docs.
  2. Added ResolvedSceneRoot and ResolvedSceneListRoot (replacing the (ResolvedScene, EntityScopes) and (Vec<ResolvedScene>, EntityScopes) tuples). This cleaned up a lot of code.
  3. Removed TemplateField / template field syntax, as it isn't currently used and I don't currently think it is the right path.
  4. Added "queued entity" cleanup for removed scenes
  5. Resolved clippy's concerns
#

Just need to write up a PR description now. Once the PR is out I'm going to flesh out Scene docs a bit more and investigate the Handle::default() situation

wooden vine
#

-# oops, sorry that was meant to be a pingless reply

copper dragon
white lichen
#

BSN PR OPEN!!!

lime veldt
#

look how you took away that announcement from cart

#

!

white lichen
#

i waited 2 minutes before posting

split harness
split harness
lime veldt
white lichen
#

lol

lime veldt
#

it will be quite an act to review this before the 0.19 😨

split harness
#

(and docs)

#

Should hopefully be removing Handle::default stuff shortly

magic belfry
#

fyi this is lacking syntax highlighting and has an extra newline

royal python
#

I don't want to pollute the PR thread, but the line Ok(entity.resource::<AssetServer>().load(&self.path)) in the PR description should be Ok(context.resource::<AssetServer>().load(&self.path))

rare whale
#

@split harness So first off, congratulations πŸ™‚ Secondly, there are some issues which were raised in previous discussions / prs which were never really answered, unfortunately these are old enough that I'm having trouble finding links to them. The way in which you use the term Scene is still nails-on-a-chalkboard to me, but I suspect that this is a lost cause.

split harness
#

I am unlikely to change my stance on Scene. I think it is the correct name, for the reasons we have already discussed.

rare whale
magic belfry
#

How inaccurate would it be to rename the current bevy_scene to something like bevy_snapshot for the "world serialization" scenarios? You can use it to serialize the current state of the world into a kind of "snapshot", with optional filtering

#

(also we might want to reserve that name either way maybe, it's currently free on crates.io)

split harness
split harness
#

Ex: this is the "level scene" file, this is the "widget scene" function

rare whale
split harness
magic belfry
#

yes

split harness
#

I think bevy_snapshot (or bevy_ecs_snapshot) would be reasonable. Although I think bevy_ecs_serialization is more descriptive of the problem space

magic belfry
#

bevy_ecs_serialization is alright too but a bit long and unnatural / feels out of place with our other primarily two-word crate names

split harness
#

I think we could also consider merging it into bevy_ecs under a serialization feature

magic belfry
#

yeah, if we're confident that it'll most likely be temporary then I don't really care what the name is

#

so bevy_ecs_serialization is fine in that case

queen oak
#

the syntax is glorious

#

huh wait. i don't understand

:list_widget({bsn_list! [
                Node { width: Px(4.) },
                Node { width: Px(5.) },
            ]})

This is inheritance with a function parameter, but:

Note that because inheritance is cached / pre-resolved, function inheritance does not support function parameters. You can still use parameterized scene functions by defining them directly in the scene (rather than using inheritance):

split harness
#

Fixed

queen oak
#

pog

cursive parrot
#

If we don't need parameters, what is the difference between :button and button()?

steel oak
#

Thank you @split harness!!

split harness
#

Just like :”scene.bsn” currently is

cursive parrot
#
fn player() -> impl Scene {
    bsn! {
        #Body
        Children [
            #Head
        ]
    }
}

fn blue_player() -> impl Scene {
    bsn! {
        :player
        // Can we add components to the #Head here?
    }
}
raw mesa
#

@split harness Did you end up removing scene://? I can't seem to find it

split harness
split harness
raw mesa
#

It makes the test a little more complicated, but I don't think that's a big deal.

#

Let me PR your branch

#

Oh but I guess that allows users to add their own ScenePatchs that are accessible anywhere, but only defined at runtime.

#

What if we made a runtime:// asset source? It would be a source ID hard-coded to avoid all the loading business and only give you access to assets that are explicitly registered to it. That seems useful in general, though having a weird super secret asset source name might be a little too cursed

cobalt stone
#

It is best to think of GetTemplate as an alternative to Default for types that require world/spawn context to instantiate
Isin't this describing FromWorld?

raw mesa
rare whale
#

@split harness I also want to push back on this statement here:

It is generally considered best practice to wrap related entities with more than one entry in () to improve legibility.
I've written a fair amount of code like in this style, and I don't much like it. Given the options that I have available atm, I tend to standardize on no extra parens, but putting the comma on a line by itself:

[
  Foo
  Bar
  Baz
  ,
  Foo
  Bar
  Baz
]

Maybe not the prettiest, but easy to read and maintain

#

More generally, I am on team "separators, not brackets" for delineating between sibling entities.

#

@split harness Also, I don't know if we ever resolved the issue I ran into with dynamic conditional children: I need a way to delete the existing children and insert a new child scene list with no gaps or flickering. This means we can't "delete the children now, but insert the new scene list when it resolves" as seperate operations - both have to happen in the same tick, which means holding back on the delete until resolve completes.

golden notch
white lichen
#

from my reading, its a "stateful/serializable/dynamic" FromWorld, in that you can clone and mutate them and save/load them from disc

#

you can't exactly do that with FromWorld impl because it takes no self

dapper sky
#

Lgtmlgtm

split harness
split harness
#

^ @golden notch

#

^ @white lichen

white lichen
#

yeah that makes sense

#

templates have a notion of self right?

#

or only entity?

#

like i can have a struct with some data in it impl GetTemplate and then that data can be Entity or something else

split harness
split harness
#

Templates have access to &self

#

A struct that impls GetTemplate can have an Entity field, which the Template might represent as an EntityReference template

lime veldt
#

On a sidenote, given that resources are components now, FromWorld could have EntityWorldMut now instead of &mut World

cloud fog
snow wedge
split harness
#

I think they are suitably different to justify separate traits.

split harness
rare whale
#

@split harness One thought for dealing with the "atomic children replacement" problem - which would also make composing relation more flexible - would be a set of "relation combinators":

Children [
    @Prepend([
        child,
        child,
    ])
]

Where the combinators are Prepend, Append, Insert and Replace, with Append being the default if there's no combinator. Note that for my reactive use case, these combinators would need to be supported at the top level within bsn_list! when calling spawn_related.

#

Re-reading the PR, I see that spawn_scene is now immediate - so I guess for my case I can just call despawn_related beforehand and there should be no gap, right?