Skip to content

Instantly share code, notes, and snippets.

@allsey87
Last active April 20, 2024 00:12
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save allsey87/5b0db1a218604394c5deaf2b31ddbe1e to your computer and use it in GitHub Desktop.
Save allsey87/5b0db1a218604394c5deaf2b31ddbe1e to your computer and use it in GitHub Desktop.
Integrating RustPython into a Bevy App
use bevy::prelude::{AppBuilder, Entity, With, World};
use bevy::ecs::system::IntoExclusiveSystem;
use rustpython_vm::{self as vm, builtins::PyCode, PyRef, scope::Scope};
pub(crate) struct PythonPlugin;
pub(crate) struct Script(pub String);
fn compile(world: &mut World) {
let interpreter = world
.remove_non_send::<vm::Interpreter>()
.expect("Python interpreter missing");
let entities = world
.query_filtered::<Entity, With<Script>>()
.iter(&world)
.collect::<Vec<Entity>>();
for entity in entities {
if let Some(script) = world.entity_mut(entity).remove::<Script>() {
let (scope, code) = interpreter.enter(|vm| {
(vm.new_scope_with_builtins(),
vm.compile(&script.0, vm::compile::Mode::Exec, "<embedded>".to_owned())
.expect("Could not compile script"))
});
world.entity_mut(entity).insert_bundle((scope, code));
}
}
world.insert_non_send(interpreter);
}
fn run(world: &mut World) {
let interpreter = world
.remove_non_send::<vm::Interpreter>()
.expect("Python interpreter missing");
let mut query = world.query::<(&Scope, &PyRef<PyCode>)>();
for (scope, code) in query.iter_mut(world) {
interpreter.enter(|vm| {
vm.run_code_obj(code.clone(), scope.clone())
.expect("Could not run code");
})
}
world.insert_non_send(interpreter);
}
impl bevy::app::Plugin for PythonPlugin {
fn build(&self, simulation: &mut AppBuilder) {
simulation.insert_non_send_resource(vm::Interpreter::default());
simulation.add_system(compile.exclusive_system());
simulation.add_system(run.exclusive_system());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment