Write tests for scene hot reloading.
This commit is contained in:
parent
f630a11a6f
commit
0c953880b3
@ -114,3 +114,299 @@ impl Plugin for ScenePlugin {
|
||||
impl Plugin for ScenePlugin {
|
||||
fn build(&self, _: &mut App) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bevy_app::App;
|
||||
use bevy_asset::{AssetPlugin, Assets};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
hierarchy::{ChildOf, Children},
|
||||
reflect::{AppTypeRegistry, ReflectComponent},
|
||||
world::World,
|
||||
};
|
||||
use bevy_reflect::Reflect;
|
||||
|
||||
use crate::{
|
||||
DynamicScene, DynamicSceneBuilder, DynamicSceneRoot, Scene, ScenePlugin, SceneRoot,
|
||||
};
|
||||
|
||||
#[derive(Component, Reflect, PartialEq, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct Circle {
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, PartialEq, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct Rectangle {
|
||||
width: f32,
|
||||
height: f32,
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, PartialEq, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct Triangle {
|
||||
base: f32,
|
||||
height: f32,
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
struct FinishLine;
|
||||
|
||||
#[test]
|
||||
fn scene_spawns_and_respawns_after_change() {
|
||||
let mut app = App::new();
|
||||
|
||||
app.add_plugins((AssetPlugin::default(), ScenePlugin))
|
||||
.register_type::<Circle>()
|
||||
.register_type::<Rectangle>()
|
||||
.register_type::<Triangle>()
|
||||
.register_type::<FinishLine>();
|
||||
|
||||
let scene_handle = app
|
||||
.world_mut()
|
||||
.resource_mut::<Assets<Scene>>()
|
||||
.reserve_handle();
|
||||
|
||||
let scene_entity = app.world_mut().spawn(SceneRoot(scene_handle.clone())).id();
|
||||
app.update();
|
||||
|
||||
assert!(app.world().entity(scene_entity).get::<Children>().is_none());
|
||||
|
||||
let mut scene_1 = Scene {
|
||||
world: World::new(),
|
||||
};
|
||||
let root = scene_1.world.spawn_empty().id();
|
||||
scene_1.world.spawn((
|
||||
Rectangle {
|
||||
width: 10.0,
|
||||
height: 5.0,
|
||||
},
|
||||
FinishLine,
|
||||
ChildOf(root),
|
||||
));
|
||||
scene_1.world.spawn((Circle { radius: 7.0 }, ChildOf(root)));
|
||||
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<Scene>>()
|
||||
.insert(&scene_handle, scene_1);
|
||||
|
||||
app.update();
|
||||
|
||||
let child_root = app
|
||||
.world()
|
||||
.entity(scene_entity)
|
||||
.get::<Children>()
|
||||
.and_then(|children| children.first().cloned())
|
||||
.expect("There should be exactly one child on the scene root");
|
||||
let children = app
|
||||
.world()
|
||||
.entity(child_root)
|
||||
.get::<Children>()
|
||||
.expect("The child of the scene root should itself have 2 children");
|
||||
assert_eq!(children.len(), 2);
|
||||
|
||||
let finish_line = app.world().entity(children[0]);
|
||||
assert_eq!(finish_line.archetype().component_count(), 3);
|
||||
let (rectangle, _, child_of) =
|
||||
finish_line.components::<(&Rectangle, &FinishLine, &ChildOf)>();
|
||||
assert_eq!(
|
||||
rectangle,
|
||||
&Rectangle {
|
||||
width: 10.0,
|
||||
height: 5.0,
|
||||
}
|
||||
);
|
||||
assert_eq!(child_of.0, child_root);
|
||||
|
||||
let circle = app.world().entity(children[1]);
|
||||
assert_eq!(circle.archetype().component_count(), 2);
|
||||
let (circle, child_of) = circle.components::<(&Circle, &ChildOf)>();
|
||||
assert_eq!(circle, &Circle { radius: 7.0 });
|
||||
assert_eq!(child_of.0, child_root);
|
||||
|
||||
// Now that we know our scene contains exactly what we expect, we will change the scene
|
||||
// asset and ensure it contains the new scene results.
|
||||
|
||||
let mut scene_2 = Scene {
|
||||
world: World::new(),
|
||||
};
|
||||
let root = scene_2.world.spawn_empty().id();
|
||||
scene_2.world.spawn((
|
||||
Triangle {
|
||||
base: 1.0,
|
||||
height: 2.0,
|
||||
},
|
||||
ChildOf(root),
|
||||
));
|
||||
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<Scene>>()
|
||||
.insert(&scene_handle, scene_2);
|
||||
|
||||
app.update();
|
||||
app.update();
|
||||
|
||||
let child_root = app
|
||||
.world()
|
||||
.entity(scene_entity)
|
||||
.get::<Children>()
|
||||
.and_then(|children| children.first().cloned())
|
||||
.expect("There should be exactly one child on the scene root");
|
||||
let children = app
|
||||
.world()
|
||||
.entity(child_root)
|
||||
.get::<Children>()
|
||||
.expect("The child of the scene root should itself have 2 children");
|
||||
assert_eq!(children.len(), 1);
|
||||
|
||||
let triangle = app.world().entity(children[0]);
|
||||
assert_eq!(triangle.archetype().component_count(), 2);
|
||||
let (triangle, child_of) = triangle.components::<(&Triangle, &ChildOf)>();
|
||||
assert_eq!(
|
||||
triangle,
|
||||
&Triangle {
|
||||
base: 1.0,
|
||||
height: 2.0,
|
||||
}
|
||||
);
|
||||
assert_eq!(child_of.0, child_root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_scene_spawns_and_respawns_after_change() {
|
||||
let mut app = App::new();
|
||||
|
||||
app.add_plugins((AssetPlugin::default(), ScenePlugin))
|
||||
.register_type::<Circle>()
|
||||
.register_type::<Rectangle>()
|
||||
.register_type::<Triangle>()
|
||||
.register_type::<FinishLine>();
|
||||
|
||||
let scene_handle = app
|
||||
.world_mut()
|
||||
.resource_mut::<Assets<DynamicScene>>()
|
||||
.reserve_handle();
|
||||
|
||||
let scene_entity = app
|
||||
.world_mut()
|
||||
.spawn(DynamicSceneRoot(scene_handle.clone()))
|
||||
.id();
|
||||
app.update();
|
||||
|
||||
assert!(app.world().entity(scene_entity).get::<Children>().is_none());
|
||||
|
||||
let create_dynamic_scene = |mut scene: Scene, world: &World| {
|
||||
scene
|
||||
.world
|
||||
.insert_resource(world.resource::<AppTypeRegistry>().clone());
|
||||
DynamicSceneBuilder::from_world(&scene.world)
|
||||
.extract_entities(scene.world.iter_entities().map(|entity| entity.id()))
|
||||
.build()
|
||||
};
|
||||
|
||||
let mut scene_1 = Scene {
|
||||
world: World::new(),
|
||||
};
|
||||
let root = scene_1.world.spawn_empty().id();
|
||||
scene_1.world.spawn((
|
||||
Rectangle {
|
||||
width: 10.0,
|
||||
height: 5.0,
|
||||
},
|
||||
FinishLine,
|
||||
ChildOf(root),
|
||||
));
|
||||
scene_1.world.spawn((Circle { radius: 7.0 }, ChildOf(root)));
|
||||
|
||||
let scene_1 = create_dynamic_scene(scene_1, app.world());
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<DynamicScene>>()
|
||||
.insert(&scene_handle, scene_1);
|
||||
|
||||
app.update();
|
||||
|
||||
let child_root = app
|
||||
.world()
|
||||
.entity(scene_entity)
|
||||
.get::<Children>()
|
||||
.and_then(|children| children.first().cloned())
|
||||
.expect("There should be exactly one child on the scene root");
|
||||
let children = app
|
||||
.world()
|
||||
.entity(child_root)
|
||||
.get::<Children>()
|
||||
.expect("The child of the scene root should itself have 2 children");
|
||||
assert_eq!(children.len(), 2);
|
||||
|
||||
let finish_line = app.world().entity(children[0]);
|
||||
assert_eq!(finish_line.archetype().component_count(), 3);
|
||||
let (rectangle, _, child_of) =
|
||||
finish_line.components::<(&Rectangle, &FinishLine, &ChildOf)>();
|
||||
assert_eq!(
|
||||
rectangle,
|
||||
&Rectangle {
|
||||
width: 10.0,
|
||||
height: 5.0,
|
||||
}
|
||||
);
|
||||
assert_eq!(child_of.0, child_root);
|
||||
|
||||
let circle = app.world().entity(children[1]);
|
||||
assert_eq!(circle.archetype().component_count(), 2);
|
||||
let (circle, child_of) = circle.components::<(&Circle, &ChildOf)>();
|
||||
assert_eq!(circle, &Circle { radius: 7.0 });
|
||||
assert_eq!(child_of.0, child_root);
|
||||
|
||||
// Now that we know our scene contains exactly what we expect, we will change the scene
|
||||
// asset and ensure it contains the new scene results.
|
||||
|
||||
let mut scene_2 = Scene {
|
||||
world: World::new(),
|
||||
};
|
||||
let root = scene_2.world.spawn_empty().id();
|
||||
scene_2.world.spawn((
|
||||
Triangle {
|
||||
base: 1.0,
|
||||
height: 2.0,
|
||||
},
|
||||
ChildOf(root),
|
||||
));
|
||||
|
||||
let scene_2 = create_dynamic_scene(scene_2, app.world());
|
||||
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<DynamicScene>>()
|
||||
.insert(&scene_handle, scene_2);
|
||||
|
||||
app.update();
|
||||
app.update();
|
||||
|
||||
let child_root = app
|
||||
.world()
|
||||
.entity(scene_entity)
|
||||
.get::<Children>()
|
||||
.and_then(|children| children.first().cloned())
|
||||
.expect("There should be exactly one child on the scene root");
|
||||
let children = app
|
||||
.world()
|
||||
.entity(child_root)
|
||||
.get::<Children>()
|
||||
.expect("The child of the scene root should itself have 2 children");
|
||||
assert_eq!(children.len(), 1);
|
||||
|
||||
let triangle = app.world().entity(children[0]);
|
||||
assert_eq!(triangle.archetype().component_count(), 2);
|
||||
let (triangle, child_of) = triangle.components::<(&Triangle, &ChildOf)>();
|
||||
assert_eq!(
|
||||
triangle,
|
||||
&Triangle {
|
||||
base: 1.0,
|
||||
height: 2.0,
|
||||
}
|
||||
);
|
||||
assert_eq!(child_of.0, child_root);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user