Update docs for FlaggedStorage and minor reformat.
Update the `FlaggedStorage` docs to include mutable iteration over
`FlaggedStorage`. Update formatting to fit 80-col limit.
@@ -8,12 +8,12 @@ To avoid a lot of unnecessary computation when updating components it
would be nice if we could somehow check for only those entities that are updated
and recalculate only those.
-We might also need to keep an external resource in sync with changes
-to components in Specs `World`, and we only want to propagate actual changes, not
+We might also need to keep an external resource in sync with changes to
+components in Specs `World`, and we only want to propagate actual changes, not
do a full sync every frame.
-This is where `FlaggedStorage` comes into play. By wrapping a component's
-actual storage in a `FlaggedStorage`, we can subscribe to modification events, and
+This is where `FlaggedStorage` comes into play. By wrapping a component's actual
+storage in a `FlaggedStorage`, we can subscribe to modification events, and
easily populate bitsets with only the entities that have actually changed.
Let's look at some code:
@@ -66,7 +66,9 @@ impl<'a> System<'a> for Sys {
fn setup(&mut self, res: &mut Resources) {
Self::SystemData::setup(res);
- self.reader_id = Some(WriteStorage::<Data>::fetch(&res).register_reader());
+ self.reader_id = Some(
+ WriteStorage::<Data>::fetch(&res).register_reader()
+ );
}
}
```
@@ -80,6 +82,47 @@ There are three different event types that we can receive:
* `ComponentEvent::Removed` - will be sent when a component is removed from the
storage
-Note that because of how `ComponentEvent` works, if you iterate mutably over a
+## Gotcha: Iterating `FlaggedStorage` Mutably
+
+Because of how `ComponentEvent` works, if you iterate mutably over a
component storage using `Join`, all entities that are fetched by the `Join` will
be flagged as modified even if nothing was updated in them.
+
+For example, this will cause all `comps` components to be flagged as modified:
+
+```rust,ignore
+// **Never do this** if `comps` uses `FlaggedStorage`.
+//
+// This will flag all components as modified regardless of whether the inner
+// loop actually modified the component.
+for comp in (&mut comps).join() {
+ // ...
+}
+```
+
+Instead, you will want to either:
+
+* Restrict the components mutably iterated over, for example by joining with a
+ `BitSet` or another component storage.
+* Iterating over the components use a `RestrictedStorage` and only fetch the
+ component as mutable if/when needed.
+
+## `RestrictedStorage`
+
+If you need to iterate over a `FlaggedStorage` mutably and don't want every
+component to be marked as modified, you can use a `RestrictedStorage` and only
+fetch the component as mutable if/when needed.
+
+```rust,ignore
+for (entity, mut comps) in (&entities, &mut comps.restrict_mut()).join() {
+ // Check whether this component should be modified.
+ if condition {
+ let mut comp = comps.get_mut_unchecked();
+ // ...
+ }
+}
+```
+
+_See
+[FlaggedStorage Doc](https://docs.rs/specs/latest/specs/struct.FlaggedStorage.html)
+for more into._
