Skip to content

Commit

Permalink
[docs] Update README & examples page
Browse files Browse the repository at this point in the history
  • Loading branch information
jkb0o committed Feb 17, 2023
1 parent 492752a commit 33e3ae3
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 36 deletions.
63 changes: 35 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## About
`pecs` is a plugin for [Bevy](https://bevyengine.org) that allows you
to execute code asynchronously by chaining multple promises as part of Bevy's `ecs` enviroment.
`pecs` is a plugin for [Bevy](https://bevyengine.org) that allows you to execute code asynchronously
by chaining multiple promises as part of Bevy's `ecs` environment.

`pecs`stands for `Promise Entity Component System`.
`pecs` stands for `Promise Entity Component System`.

Resources:
- [Docs](https://docs.rs/pecs/)
Expand All @@ -11,18 +11,19 @@ Resources:
- [Provide an idea](https://github.com/jkb0o/pecs/issues/new)

### Features
- promise chaining with `then()`
- state passing (`state` for promises is like `self` for items)
- complete type inference (the next promise knows the type of the previous result)
- out-of-the-box timer and http promises via `asyn` mod and stateful `state.asyn()`
- custom promise registretion (add any asyn function you want!)
- `system params` fetching (promise `asyn!` funcs accepts the same params
the bevy systems does)
- nested promises (with chaining, obviously)
- combining promises with any/all for tuple/vec of promises via stateles
`Promise::any()`/`Promise::all()` or stateful `state.any()`/`state.all()`
- state mapping via `with(value)`/`map(func)` (change state type/value over chain calls)
- result mapping via `with_ok(value)`/`map_ok(func)` (change result type/value over chain calls)
- Promise chaining with `then()`/`then_repeat()`
- State passing (`state` for promises is like `self` for items).
- Complete type inference (the next promise knows the type of the previous result).
- Out-of-the-box timer, UI and HTTP promises via stateless `asyn` mod and
stateful `state.asyn()` method.
- Custom promise registration (add any asynchronous function you want!).
- [System parameters](https://docs.rs/bevy/latest/bevy/ecs/system/trait.SystemParam.html) fetching
(promise `asyn!` functions accept the same parameters as Bevy systems do).
- Nested promises (with chaining, obviously).
- Combining promises with `any/all` for tuple/vec of promises via stateless `Promise::any()`
/`Promise::all()` methods or stateful `state.any()`/`state.all()` methods.
- State mapping via `with(value)`/`map(func)` (changes state type/value over chain calls).
- Result mapping via `with_result(value)`/`map_result(func)` (changes result type/value over chain calls).

## Example
```rust
Expand All @@ -36,31 +37,37 @@ fn main() {
.run();
}

fn setup(mut commands: Commands) {
commands.add(
Promise::start(asyn!(state, time: Res<Time> => {
fn setup(mut commands: Commands, time: Res<Time>) {
let start = time.elapsed_seconds();
commands
// create PromiseLike chainable commands
// with the current time as state
.promise(|| start)
// will be executed right after current stage
.then(asyn!(state => {
info!("Wait a second..");
let started_at = time.elapsed_seconds();
state.with(started_at).asyn().timeout(1.0)
state.asyn().timeout(1.0)
}))
.then(asyn!(state, _ => {
// will be executed after in a second after previous call
.then(asyn!(state => {
info!("How large is is the Bevy main web page?");
state.asyn().http().get("https://bevyengine.org")
}))
// will be executed after request completes
.then(asyn!(state, result => {
match result {
Ok(response) => info!("It is {} bytes!", response.bytes.len()),
Err(err) => info!("Ahhh... something goes wrong: {err}")
}
state.pass()
}))
.then(asyn!(state, _, time: Res<Time> => {
// will be executed right after the previous one
.then(asyn!(state, time: Res<Time> => {
let duration = time.elapsed_seconds() - state.value;
info!("It tooks {duration:0.2}s to do this job.");
info!("Exiting now");
asyn::app::exit()
}))
);
}));
}
```
There is otput of the above example, pay some attention to time stamps:
Expand All @@ -74,11 +81,11 @@ There is otput of the above example, pay some attention to time stamps:
```

## Work in Progress
This crate is pretty young. API could and will change. App may crash. Some
promises could silently drop. Documentation is incomplete.

But. But. Examples works like a charm. And this fact gives us a lot of hope.

This repo is more like an experimental-proof-of-concept than a production-ready library.
API could and will change. App will crash (there are some untested unsafe blocks), some
promises will silently drop (there are stil no unit tests), documentation is incomplete
and so on. But. But. Examples works like a charm. And this fact gives us a lot of hope.

## License

Expand Down
Binary file added docs/confirmation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 51 additions & 6 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,54 @@ This is the page with the described examples.
> https://github.com/jkb0o/pecs/tree/stable/examples

| Example | How to run | Description |
|------------------------------------|----------------------------------------|--------------------------------------------------|
| [simple](simple.rs) | `cargo run --example simple` | Chain promises, defer some call using `asyn::timeout(sec)`, make http requests with `asyn::http::get()`.
| [custom_timer](custom_timer.rs) | `cargo run --example custom_timer` | Create custom promises, resolve them, promise <-> ecs relations workout.
| [combind_vecs](combine_vecs.rs) | `cargo run --example combine_vecs` | Combine promises: wait all/any of `Vec<Promise>` to resolve, iterator extension, state passing.
| [complex](complex.rs) | `cargo run --example complex` | Every new feature added to this example. It contains almost everything what `pecs` provides.
### `simple`
```bash
cargo run --example simple
```
This example shows how to sequentially call promises by chaining them with `then` method.
It will wait for second, make http request, wait for an response and exit the app.

### `repeat`
```bash
cargo run --example repeat
```
This example demonstrates how to use `Promise::repeat()`
to create async loops.

### `custom_timer`
```bash
cargo run --example custom_timer
```
This Example shows how you can create custom promises
with `Promise::register()` method and resolve them from
you system with `commands.promise(id).resolve(result)`

### `combind_vecs`
```bash
cargo run --example combind_vecs
```
This example demonstrates how to use `any()`/`all()`
in different ways for combining vector of promises
and react to result when all/any of the passed
promises got resolved.

### `confirmation`
```bash
cargo run --example confirmation
```
This example shows how to use `pecs` for organizing UI logic
with async operations. We create `exit` button that shows
confirmation popup on press and exit app if confirmed.

The promise-based loop works like this:
```
- create exit button
- loop: <-------------------------.
- wait for exit button pressed |
- create popup with yes/no buttons |
- wait for yes or no pressed |
- repeat if no pressed -------------`
- break loop if yes pressed --------.
- exit app <-------------------------`
```
![Confirmation](../docs/confirmation.gif)
4 changes: 4 additions & 0 deletions examples/combine_vecs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! This example demonstrates how to use `any()`/`all()`
//! in different ways for combining vector of promises
//! and react to result when all/any of the passed
//! promises got resolved.
use bevy::prelude::*;
use pecs::prelude::*;
fn main() {
Expand Down
7 changes: 5 additions & 2 deletions examples/confirmation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! This example shows how to implemnt exit confirmation
//! popup with promises. The promise-based loop works like this:
//! This example shows how to use `pecs` for organizing UI logic
//! with async operations. We create `exit` button that shows
//! confirmation popup on press and exit app if confirmed.
//!
//! The promise-based loop works like this:
//! - create exit button
//! - loop: <-------------------------.
//! - wait for exit button pressed |
Expand Down
2 changes: 2 additions & 0 deletions examples/custom_timer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! This Example shows how you can create custom promises
//! with `Promise::register()` method and resolve them from
//! you system with `commands.promise(id).resolve(result)`
use bevy::prelude::*;
use pecs::prelude::*;
fn main() {
Expand Down
3 changes: 3 additions & 0 deletions examples/repeat.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! This example demonstrates how to use `Promise::repeat()`
//! to create async loops.
use bevy::prelude::*;
use pecs::prelude::*;
fn main() {
Expand Down

0 comments on commit 33e3ae3

Please sign in to comment.