use crate::{
ResolveContext, ResolveSceneError, ResolvedScene, Scene, SceneDependencies, SceneScope,
};
use variadics_please::all_tuples;
pub trait SceneList: SceneListBox {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError>;
fn register_dependencies(&self, dependencies: &mut SceneDependencies);
}
pub trait SceneListBox: Send + Sync + 'static {
fn resolve_list_box(
self: Box<Self>,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError>;
fn register_dependencies_box(&self, dependencies: &mut SceneDependencies);
}
impl<L: SceneList> SceneListBox for L {
#[inline]
fn resolve_list_box(
self: Box<Self>,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
(*self).resolve_list(context, scenes)
}
#[inline]
fn register_dependencies_box(&self, dependencies: &mut SceneDependencies) {
self.register_dependencies(dependencies);
}
}
impl<T: ?Sized + SceneListBox> SceneList for Box<T> {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
self.resolve_list_box(context, scenes)
}
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
(**self).register_dependencies_box(dependencies);
}
}
pub struct EntityScene<S>(pub S);
impl<S: Scene> SceneList for EntityScene<S> {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
let mut resolved_scene = ResolvedScene::default();
self.0.resolve(context, &mut resolved_scene)?;
scenes.push(resolved_scene);
Ok(())
}
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
self.0.register_dependencies(dependencies);
}
}
macro_rules! scene_list_impl {
($($list: ident),*) => {
impl<$($list: SceneList),*> SceneList for ($($list,)*) {
fn resolve_list(self, _context: &mut ResolveContext, _scenes: &mut Vec<ResolvedScene>) -> Result<(), ResolveSceneError> {
#[expect(
clippy::allow_attributes,
reason = "This is inside a macro, and as such, may not trigger in all cases."
)]
#[allow(
non_snake_case,
reason = "The names of these variables are provided by the caller, not by us."
)]
let ($($list,)*) = self;
$($list.resolve_list(_context, _scenes)?;)*
Ok(())
}
fn register_dependencies(&self, _dependencies: &mut SceneDependencies) {
#[expect(
clippy::allow_attributes,
reason = "This is inside a macro, and as such, may not trigger in all cases."
)]
#[allow(
non_snake_case,
reason = "The names of these variables are provided by the caller, not by us."
)]
let ($($list,)*) = self;
$($list.register_dependencies(_dependencies);)*
}
}
}
}
all_tuples!(scene_list_impl, 0, 12, P);
impl<S: Scene> SceneList for Vec<S> {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
for scene in self {
let mut resolved_scene = ResolvedScene::default();
scene.resolve(context, &mut resolved_scene)?;
scenes.push(resolved_scene);
}
Ok(())
}
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
for scene in self {
scene.register_dependencies(dependencies);
}
}
}
impl SceneList for Vec<Box<dyn SceneList>> {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
for scene_list in self {
scene_list.resolve_list(context, scenes)?;
}
Ok(())
}
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
for scene_list in self {
scene_list.register_dependencies(dependencies);
}
}
}
impl<S: Scene> SceneList for SceneScope<S> {
fn resolve_list(
self,
context: &mut ResolveContext,
scenes: &mut Vec<ResolvedScene>,
) -> Result<(), ResolveSceneError> {
let mut resolved_scene = ResolvedScene::default();
self.resolve(context, &mut resolved_scene)?;
scenes.push(resolved_scene);
Ok(())
}
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
Scene::register_dependencies(self, dependencies);
}
}