pybevy 0.2.1

PyBevy: A Python Real-Time Engine Built on Bevy
use std::time::Duration;

use bevy::app::{RunMode, ScheduleRunnerPlugin};
use pybevy_core::PyPlugin;
use pyo3::prelude::*;

use crate::prelude::PyApp;

#[pyclass(name = "ScheduleRunnerPlugin", extends = PyPlugin)]
#[derive(Clone)]
pub struct PyScheduleRunnerPlugin {
    run_mode: PyRunMode,
}

#[pyclass(name = "RunMode", frozen, eq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PyRunMode {
    Loop { wait: Option<u64> },
    Once(),
}

impl From<PyRunMode> for RunMode {
    fn from(py_run_mode: PyRunMode) -> Self {
        match py_run_mode {
            PyRunMode::Loop { wait } => RunMode::Loop {
                wait: wait.map(Duration::from_millis),
            },
            PyRunMode::Once() => RunMode::Once,
        }
    }
}

impl PyScheduleRunnerPlugin {
    fn with_mode(run_mode: PyRunMode) -> Self {
        PyScheduleRunnerPlugin { run_mode }
    }
}

#[pymethods]
impl PyScheduleRunnerPlugin {
    #[new]
    #[pyo3(signature = (run_mode = PyRunMode::Loop { wait: None }))]
    pub fn new(run_mode: PyRunMode) -> (Self, PyPlugin) {
        (PyScheduleRunnerPlugin { run_mode }, PyPlugin)
    }

    #[staticmethod]
    pub fn run_once(py: Python) -> PyResult<Py<Self>> {
        Py::new(py, (Self::with_mode(PyRunMode::Once()), PyPlugin))
    }

    #[staticmethod]
    pub fn run_loop(py: Python, wait_duration: Option<u64>) -> PyResult<Py<Self>> {
        Py::new(
            py,
            (
                Self::with_mode(PyRunMode::Loop {
                    wait: wait_duration,
                }),
                PyPlugin,
            ),
        )
    }

    pub fn build(&self, app: Bound<'_, PyApp>) -> PyResult<()> {
        let run_mode: RunMode = self.run_mode.into();

        app.borrow().with_bevy_app(|bevy_app| {
            bevy_app.add_plugins(ScheduleRunnerPlugin { run_mode });
            Ok(())
        })
    }
}