docs/bevy/release-content/migration-guides/bsn_syntax_improvements.md 4 K · 183 lines · raw · history

1 ---
2 title: BSN Syntax Improvements.
3 pull_requests: [25318]
4 ---
5
6 BSN landed with a few idiosyncrasies that caused friction in practice. We made some changes to BSN's syntax this cycle in the interest of improving its ergonomics and clarity.
7
8 All scene references now require `@` prefixes:
9
10 ```rust
11 // Before
12 bsn! {
13 scene_variable
14 scene_function()
15 {scene_expression}
16 }
17
18 // After
19 bsn! {
20 @scene_variable
21 @scene_function()
22 @{scene_expression}
23 }
24 ```
25
26 This freed us up to make component values _much_ easier to work with.
27
28 ```rust
29 // Before
30 bsn! {
31 template_value(component_variable)
32 template_value(component_function())
33 }
34
35 // After
36 bsn! {
37 component_variable
38 component_function()
39 }
40 ```
41
42 Enums no longer require `VariantDefaults` or `FromTemplate`, provided they implement `Default` and `Clone`:
43
44 ```rust
45 // Before
46 #[derive(Component, Default, Clone, VariantDefaults)]
47 enum Foo {
48 A { x: u32, y: u32 },
49 #[default]
50 B,
51 }
52
53 bsn! {
54 Foo::B
55 }
56
57 // After
58 #[derive(Component, Default, Clone)]
59 enum Foo {
60 A { x: u32, y: u32 },
61 #[default]
62 B,
63 }
64
65 bsn! {
66 Foo::B
67 }
68 ```
69
70 If you were using an enum that didn't support `VariantDefaults`, you can remove the `template_value` wrapper:
71
72 ```rust
73 // Before
74 bsn! {
75 template_value(Foo::A)
76 }
77 // After
78 bsn! {
79 Foo::A
80 }
81 ```
82
83 The "variant defaults" pattern, which relied on defining individual "default" constructors for each variant is what allowed "individual enum field value patching" (ex: `VariantDefaults` and `FromTemplate` would define `Foo::a_default()` and `Foo::b_default()` in the example above). This is no longer supported, as the weirdness factor (and Rust ecosystem compatibility challenges) were too costly. When working with enums in BSN, you must now specify each field in the enum, just like you would in normal Rust (which doesn't have support for individual enum variant defaults).
84
85 ```rust
86 // Before (y field is initialized to its default value)
87 bsn! {
88 Foo::A { x: 1 }
89 }
90
91 // After (y field must be manually specified)
92 bsn! {
93 Foo::A { x: 1, y: 0 }
94 }
95 ```
96
97 The "builder pattern" previously required a `template_value` wrapper. This can now be removed:
98
99 ```rust
100 // Before
101 bsn! {
102 template_value(Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y))
103 }
104 // After
105 bsn! {
106 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y)
107 }
108 ```
109
110 Additionally, you can now remove the `template_value` wrapper in cases like this:
111
112 ```rust
113 // Before
114 bsn! {
115 template_value(node.clone())
116 }
117 // After
118 bsn! {
119 node.clone()
120 }
121 ```
122
123 In general, you should now be able to remove all `template_value` instances from your BSN declarations!
124
125 List syntax in BSN has also been improved. BSN used to use commas to separate entities, with optional `()` around entities to make the boundaries clearer. This resulted in a lot of syntax noise, line noise, and over-indentation:
126
127 ```rust
128 bsn! {
129 Node
130 Children [
131 (
132 #OkButton
133 @button("Ok")
134 ),
135 (
136 #CancelButton
137 @button("Cancel")
138 ),
139 ]
140 }
141 ```
142
143 To avoid this, many developers opted for this syntax instead, which made it very hard to visually distinguish entities:
144
145 ```rust
146 bsn! {
147 Node
148 Children [
149 #OkButton
150 @button("Ok"),
151 #CancelButton
152 @button("Cancel"),
153 ]
154 }
155 ```
156
157 BSN now uses `--` to separate entities:
158
159 ```rust
160 bsn! {
161 Node
162 Children [
163 #OkButton
164 @button("Ok")
165 --
166 #CancelButton
167 @button("Cancel")
168 ]
169 }
170 ```
171
172 This gives us the best of all worlds: entities are visually distinct, and there is no over-indentation, line noise, or syntax noise. Both `()` and `,` have been deprecated in this context.
173
174 Using `[]` and `()` for `bsn_list!` (and `bsn!`) is now discouraged / warned against (ex: `bsn_list! []`), as it can result in poor rustfmt autoformatting. Instead, use `bsn_list! {}`, which is the only syntax that `rustfmt` won't touch. Don't worry, we
175 plan to build a BSN auto-formatter!
176
177 ```rust
178 bsn_list! {
179 #Ok @button("Ok")
180 --
181 #Cancel @button("Cancel")
182 }
183 ```