Skip to content

Commit

Permalink
Add simple Bevy integration
Browse files Browse the repository at this point in the history
  • Loading branch information
nxsaken committed Jan 3, 2024
1 parent 02f1fa2 commit be2f685
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 205 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ categories = ["simulation", "game-development", "science"]
[dependencies]
bevy_ecs = { version = "0.12", default-features = false }
bevy_app = { version = "0.12" }
bevy_utils = { version = "0.12" }
petnat_derive = { path = "petnat_derive" }

[dev-dependencies]
bevy = { version = "0.12" }

[features]
75 changes: 75 additions & 0 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! A simple Petri net being manipulated via systems.
use bevy::input::common_conditions::input_just_pressed;
use bevy::prelude::*;
use petnat::{NetId, Nn, PetriNet, PetriNetPlugin, Place, Pn, Tn, Token, W};
use std::any::type_name;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(PetriNetPlugin::<Nn<0>> {
build: |builder| {
builder
.add_place::<Pn<0>>()
.add_place::<Pn<1>>()
.add_place::<Pn<2>>()
// T0 requires 1 token in P0 and 2 tokens in P1 to be enabled
// and it will produce 1 token in P2 when fired
.add_trans::<Tn<0>, ((Pn<0>, W<1>), (Pn<1>, W<2>)), (Pn<2>, W<1>)>()
},
})
.add_systems(Startup, spawn_token::<Nn<0>>)
.add_systems(
Update,
(
// press 1 and 2 to mark `P0` and `P1`
mark::<Nn<0>, Pn<0>>.run_if(input_just_pressed(KeyCode::Key1)),
mark::<Nn<0>, Pn<1>>.run_if(input_just_pressed(KeyCode::Key2)),
// press T to fire `T0`
trans_t0::<Nn<0>>.run_if(input_just_pressed(KeyCode::T)),
print_net::<Nn<0>>,
),
)
.run();
}

fn spawn_token<Net: NetId>(mut commands: Commands, net: Res<PetriNet<Net>>) {
commands.spawn(net.spawn_token());
info!("Spawning a token...");
}

fn mark<Net: NetId, P: Place<Net>>(net: Res<PetriNet<Net>>, mut tokens: Query<&mut Token<Net>>) {
for mut token in &mut tokens {
net.mark::<P>(&mut token, 1);
let (_, name) = type_name::<P>()
.rsplit_once(':')
.unwrap_or(("", type_name::<P>()));
info!("{} marked!", name);
}
}

fn trans_t0<Net: NetId>(net: Res<PetriNet<Net>>, mut tokens: Query<&mut Token<Net>>) {
for mut token in &mut tokens {
if let Some(()) = net.fire::<Tn<0>>(token.bypass_change_detection()) {
info!("T0 fired!");
token.set_changed();
} else {
info!("T0 cannot fire! (Need: 1 in P0 + 2 in P1)");
}
}
}

fn print_net<Net: NetId>(
net: Res<PetriNet<Net>>,
tokens: Query<(Entity, &Token<Net>), Changed<Token<Net>>>,
) {
for (id, token) in &tokens {
info!("== TOKEN {:?} STATE ==", id);
info!("P0: {}", token.marks::<Pn<0>>());
info!("P1: {}", token.marks::<Pn<1>>());
info!("T0 enabled: {}", net.enabled::<Tn<0>>(token));
info!("P2: {}", token.marks::<Pn<2>>());
info!("=====================");
}
}
5 changes: 1 addition & 4 deletions petnat_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
[package]
name = "petnat_derive"
version = "0.1.0"
version = "0.0.1"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
syn = { version = "2.0.44" }
quote = { version = "1.0.34" }
deluxe = { version = "0.5.0" }
36 changes: 0 additions & 36 deletions petnat_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1 @@
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(Place)]
pub fn place_derive(input: TokenStream) -> TokenStream {
// Parse the input tokens into a syntax tree
let input = parse_macro_input!(input as DeriveInput);

// Extract the name of the struct or enum
let ident = &input.ident;

let expanded = quote! {
impl<Net: NetId> Place<Net> for #ident {}
};

// Convert the generated code into a TokenStream
TokenStream::from(expanded)
}

#[proc_macro_derive(Trans)]
pub fn trans_derive(input: TokenStream) -> TokenStream {
// Parse the input tokens into a syntax tree
let input = parse_macro_input!(input as DeriveInput);

// Extract the name of the struct or enum
let ident = &input.ident;

let expanded = quote! {
impl<Net: NetId> Trans<Net> for #ident {}
};

// Convert the generated code into a TokenStream
TokenStream::from(expanded)
}
12 changes: 9 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
#![deny(missing_docs)]
#![deny(clippy::all)]

pub mod net;
pub mod plugin;
pub mod token;
pub use crate::net::place::{Place, PlaceId, Pn};
pub use crate::net::trans::{Arcs, Tn, Trans, TransId, W};
pub use crate::net::{NetId, Nn, PetriNet, PetriNetBuilder};
pub use crate::plugin::PetriNetPlugin;
pub use crate::token::Token;

mod net;
mod plugin;
mod token;

// todo:
// - petri net resource / component
Expand Down
Loading

0 comments on commit be2f685

Please sign in to comment.