amethyst / amethyst/legion

Systems as "normal functions"

Aperta
#134 12 commenti 8 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Rust
Stelle
1.7k
Fork
140
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

I think it would be useful to be able to define systems as "normal functions":

### Preferred Format

```rust
// borrows resource A and runs once for each entity with the X and Y components
pub fn simple_system(a: Resource, x: Ref, y: RefMut) {
println!("{} {}", x.value, y.value);
}
```
This sheds a large amount of boilerplate, increases clarity, and makes IDEs happy (i already tested Ref completions with rust-analyzer). Currently rust-analyzer is unable to give completions within systems defined using SystemBuilder.

I recently proposed a similar layout for [Shipyard ECS](https://github.com/leudz/shipyard) and they actually just adopted it. Its really cool, but for a variety of reasons I want my current codebase to remain on legion.

### Potential "Easy" Implementation

I also believe something similar is possible in legion without changing the current types / adding a bunch of new code.

```rust
pub struct X { value: usize }

pub struct Y { value: f32 }

pub fn simple_system((x, y): (Ref, Ref)) {
println!("{} {}", x.value, y.value);
}

pub fn main() {
let mut world = World::new();
let mut resources = Resources::default();
let system = into_system("simple_system", simple_system);
system.run(&mut world, &mut resources);
}

pub fn into_system(name: &'static str, system: A) -> Box
where
A: Fn(<::Iter as Iterator>::Item) + Send + Sync + 'static,
V: for<'a> View<'a> + DefaultFilter,
F: EntityFilter + Sync + 'static,
{
SystemBuilder::new(name)
.with_query(V::query())
.build(move |_, world, _, query| {
for x in query.iter_mut(world) {
system(x);
}
})
}
```

This _almost_ compiles, but I haven't been able to take it over the finish line. The example above fails with:
```
error[E0631]: type mismatch in function arguments
--> legion_systems/src/system_fn.rs:98:36
|
53 | pub fn into_system(system: A) -> Box
| -----------
54 | where
55 | A: Fn(<::Iter as Iterator>::Item) + Send + Sync + 'static,
| ----------------------------------------- required by this bound in `system_fn::into_system`
...
98 | let x = super::into_system(test);
| ^^^^ expected signature of `for<'r> fn(<<_ as legion_core::query::View<'r>>::Iter as std::iter::Iterator>::Item) -> _`
...
109 | fn test<'a>(a: (Ref<'a, X>, Ref<'a, Y>)) {
| ---------------------------------------- found signature of `for<'a> fn((legion_core::borrow::Ref<'a, system_fn::tests::X>, legion_core::borrow::Ref<'a, system_fn::tests::Y>)) -> _`
```
I'm curious if someone familiar with the legion types could help me out?

However even if we can make that work there is the big caveat that it wouldn't support Resources. However maybe theres a way to work those in too :smile:

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.