Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs for FlaggedStorage and minor reformat. #636

Merged
merged 3 commits into from
Sep 11, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 60 additions & 14 deletions docs/tutorials/src/12_tracked.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -66,29 +66,75 @@ 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()
);
}
}
```

There are three different event types that we can receive:

* `ComponentEvent::Inserted` - will be sent when a component is added to the
- `ComponentEvent::Inserted` - will be sent when a component is added to the
storage
* `ComponentEvent::Modified` - will be sent when a component is fetched mutably
- `ComponentEvent::Modified` - will be sent when a component is fetched mutably
from the storage
* `ComponentEvent::Removed` - will be sent when a component is removed from the
- `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 comp) in (&entities, &mut comps.restrict_mut()).join() {
// Check whether this component should be modified, without fetching it as
// mutable.
if comp.get_unchecked().condition < 5 {
let mut comp = comp.get_mut_unchecked();
// ...
}
}
```

## Start and Stop event emission

Sometimes you may want to perform some operations on the storage, but you don't want
that these operations produce any event.
Sometimes you may want to perform some operations on the storage, but you don't
want that these operations produce any event.

You can use the function `storage.set_event_emission(false)` to suppress the
event writing for of any action. When you want to re activate them you can
simply call `storage.set_event_emission(true)`.

---

You can use the function `storage.set_event_emission(false)` to suppress the event writing for
of any action. When you want to re activate them you can simply call
`storage.set_event_emission(true)`.
_See
[FlaggedStorage Doc](https://docs.rs/specs/latest/specs/struct.FlaggedStorage.html)
for more into._