192 lines
5.3 KiB
Rust
192 lines
5.3 KiB
Rust
use legion::Entity;
|
|
|
|
use crate::model;
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
pub struct World {
|
|
pub world: legion::World,
|
|
pub resources: legion::Resources,
|
|
pub root_objects: Vec<Entity>,
|
|
}
|
|
|
|
impl Deref for World {
|
|
type Target = legion::World;
|
|
|
|
fn deref(&self) -> &legion::World {
|
|
&self.world
|
|
}
|
|
}
|
|
|
|
impl DerefMut for World {
|
|
fn deref_mut(&mut self) -> &mut legion::World {
|
|
&mut self.world
|
|
}
|
|
}
|
|
|
|
impl World {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
world: Default::default(),
|
|
resources: Default::default(),
|
|
root_objects: vec![],
|
|
}
|
|
}
|
|
|
|
pub fn execute(&mut self, schedule: &mut legion::Schedule) {
|
|
schedule.execute(&mut self.world, &mut self.resources);
|
|
}
|
|
|
|
pub fn get_component_mut<T: 'static + Send + Sync>(&mut self, entity: Entity) -> &mut T {
|
|
self.entry(entity).unwrap().into_component_mut().unwrap()
|
|
}
|
|
|
|
pub fn spawn_model(&mut self, model: &model::LoadedModel, transform: &glam::Mat4) -> Entity {
|
|
let mut children = Vec::new();
|
|
for object in model.objects.iter() {
|
|
children.push(self.spawn_object(object, transform));
|
|
}
|
|
|
|
let root = self.world.push((Object {
|
|
name: model.name.to_owned(),
|
|
transform: model::Transform::default(),
|
|
entities: Default::default(),
|
|
children,
|
|
dirty: false,
|
|
children_dirty: false,
|
|
},));
|
|
|
|
self.root_objects.push(root);
|
|
root
|
|
}
|
|
|
|
pub fn spawn_object(
|
|
&mut self,
|
|
object: &model::LoadedObject,
|
|
root_transform: &glam::Mat4,
|
|
) -> Entity {
|
|
let transform = cyborg::scene::Transform {
|
|
transform: *root_transform * object.transform.to_mat4(),
|
|
};
|
|
|
|
let mut entities = Vec::new();
|
|
for mesh in object.meshes.iter() {
|
|
let mesh = cyborg::scene::Mesh { mesh: *mesh };
|
|
let entity = self.world.push((mesh, transform.clone()));
|
|
entities.push(entity);
|
|
}
|
|
|
|
let mut children = Vec::new();
|
|
for child in object.children.iter() {
|
|
children.push(self.spawn_object(child, root_transform));
|
|
}
|
|
|
|
self.world.push((Object {
|
|
name: object.name.clone(),
|
|
transform: object.transform.clone(),
|
|
entities,
|
|
children,
|
|
dirty: false,
|
|
children_dirty: false,
|
|
},))
|
|
}
|
|
|
|
pub fn flush_dirty_objects(&mut self) {
|
|
let mut stack = self.root_objects.to_owned();
|
|
while let Some(parent) = stack.pop() {
|
|
let parent: &mut Object = self.get_component_mut(parent);
|
|
|
|
if parent.children_dirty {
|
|
parent.children_dirty = false;
|
|
stack.extend_from_slice(&parent.children);
|
|
}
|
|
|
|
if parent.dirty {
|
|
parent.dirty = false;
|
|
|
|
let mat4 = parent.transform.to_mat4();
|
|
for entity in parent.entities.to_owned().into_iter() {
|
|
let transform: &mut cyborg::scene::Transform = self.get_component_mut(entity);
|
|
transform.transform = mat4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Object {
|
|
pub name: Option<String>,
|
|
pub transform: model::Transform,
|
|
pub entities: Vec<Entity>,
|
|
pub children: Vec<Entity>,
|
|
pub dirty: bool,
|
|
pub children_dirty: bool,
|
|
}
|
|
|
|
impl Object {
|
|
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
|
egui::Grid::new("root_object")
|
|
.num_columns(4)
|
|
.striped(true)
|
|
.show(ui, |ui| {
|
|
ui.label("Position: ");
|
|
self.ui_position(ui);
|
|
ui.end_row();
|
|
|
|
ui.label("Rotation: ");
|
|
self.ui_rotation(ui);
|
|
ui.end_row();
|
|
|
|
ui.label("Scale: ");
|
|
self.ui_scale(ui);
|
|
ui.end_row();
|
|
});
|
|
}
|
|
|
|
pub fn ui_position(&mut self, ui: &mut egui::Ui) {
|
|
let speed = 0.1 * self.transform.scale.min_element();
|
|
if Self::ui_vec3(ui, speed, &mut self.transform.position) {
|
|
self.dirty = true;
|
|
}
|
|
}
|
|
|
|
pub fn ui_rotation(&mut self, ui: &mut egui::Ui) {
|
|
let axes = &mut self.transform.rotation;
|
|
|
|
if ui.drag_angle(&mut axes.x).changed() {
|
|
self.dirty = true;
|
|
}
|
|
|
|
if ui.drag_angle(&mut axes.y).changed() {
|
|
self.dirty = true;
|
|
}
|
|
|
|
if ui.drag_angle(&mut axes.z).changed() {
|
|
self.dirty = true;
|
|
}
|
|
}
|
|
|
|
pub fn ui_vec3(ui: &mut egui::Ui, speed: f32, vec3: &mut glam::Vec3) -> bool {
|
|
let x_drag = egui::DragValue::new(&mut vec3.x).speed(speed);
|
|
let dirty = ui.add(x_drag).changed();
|
|
|
|
let dirty = dirty || {
|
|
// For some reason, Rust complains if this isn't in a block
|
|
let y_drag = egui::DragValue::new(&mut vec3.y).speed(speed);
|
|
ui.add(y_drag).changed()
|
|
};
|
|
|
|
let z_drag = egui::DragValue::new(&mut vec3.z).speed(speed);
|
|
let dirty = dirty || ui.add(z_drag).changed();
|
|
|
|
dirty
|
|
}
|
|
|
|
pub fn ui_scale(&mut self, ui: &mut egui::Ui) {
|
|
let speed = self.transform.scale.min_element() * 0.01;
|
|
if Self::ui_vec3(ui, speed, &mut self.transform.scale) {
|
|
self.dirty = true;
|
|
}
|
|
}
|
|
}
|