use bevy::ecs::{entity::Entity, world::World};
use pyo3::{prelude::*, types::PyAny};
use crate::ecs::{component::PyComponent, helpers::validity_guard::ValidityFlagWithMode};
struct CustomComponentStorage {
ptr: *mut pyo3::ffi::PyObject,
validity: ValidityFlagWithMode,
component_id: bevy::ecs::component::ComponentId,
entity: Entity,
world_ptr: *mut World,
}
unsafe impl Send for CustomComponentStorage {}
unsafe impl Sync for CustomComponentStorage {}
#[pyclass(name = "CustomComponent", extends = PyComponent)]
pub struct PyCustomComponent {
storage: CustomComponentStorage,
}
#[pymethods]
impl PyCustomComponent {
fn __getattribute__<'py>(
slf: PyRef<'py, Self>,
py: Python<'py>,
name: &str,
) -> PyResult<Bound<'py, PyAny>> {
slf.check_valid()?;
let py_obj = slf.get_py_object(py);
py_obj.getattr(name)
}
fn __setattr__(
slf: PyRefMut<'_, Self>,
py: Python<'_>,
name: &str,
value: Bound<'_, PyAny>,
) -> PyResult<()> {
slf.check_valid()?;
slf.storage.validity.check_write()?;
let py_obj = slf.get_py_object(py);
py_obj.setattr(name, value)?;
crate::ecs::change_tracking::mark_component_changed_explicit(
slf.storage.entity,
slf.storage.world_ptr,
slf.storage.component_id,
);
Ok(())
}
}
impl PyCustomComponent {
pub fn from_borrowed(
py_obj_ptr: *mut pyo3::ffi::PyObject,
validity: ValidityFlagWithMode,
component_id: bevy::ecs::component::ComponentId,
entity: Entity,
world_ptr: *mut World,
) -> Self {
PyCustomComponent {
storage: CustomComponentStorage {
ptr: py_obj_ptr,
validity,
component_id,
entity,
world_ptr,
},
}
}
fn check_valid(&self) -> PyResult<()> {
Ok(self.storage.validity.check()?)
}
fn get_py_object<'py>(&self, py: Python<'py>) -> Bound<'py, PyAny> {
unsafe { Bound::from_borrowed_ptr(py, self.storage.ptr) }
}
}