Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,985 changes: 2,985 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ pub type Mat4 = vek::mat::repr_c::Mat4<f32>;

pub type Ray = vek::Ray<f32>;

#[derive(Copy, Clone, Debug)]
#[derive(Debug, Copy, Clone, Default)]
pub struct Transform {
pub position: Vec3,
pub rotation: Quaternion,
pub scale: Vec3,
}

impl Transform {
pub fn at(position: Vec3) -> Self {
Transform {
position,
..Default::default()
}
}
}
21 changes: 18 additions & 3 deletions ecs/src/commands/command.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use std::{alloc::Layout, any::TypeId, borrow::Cow, mem, ptr};
use std::{
alloc::{self, Layout},
any::TypeId,
borrow::Cow,
mem, ptr,
};

use crate::{Entity, World};

Expand Down Expand Up @@ -41,7 +46,13 @@ impl Command {
.register_raw(*type_id, name, *layout, *drop)
},
};
unsafe { world.add_raw(*entity, *component, comp_id) };
unsafe {
world.add_raw(*entity, *component, comp_id);
// NOTE: the world takes ownership of the value of component, so we don't run
// its destructor here, but we still own the allocation so we need to free it
// here
alloc::dealloc(*component, *layout);
};
*component = ptr::null_mut();
}
}
Expand All @@ -52,9 +63,13 @@ impl Drop for Command {
fn drop(&mut self) {
match self {
&mut Command::AddComponent {
component, drop, ..
component,
drop,
layout,
..
} if !component.is_null() => unsafe {
drop(component);
alloc::dealloc(component, layout);
},
_ => {}
}
Expand Down
3 changes: 3 additions & 0 deletions ecs/src/commands/command_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use crate::World;

use super::Command;

// TODO: optimize this by not making `Command` an enum and so that these can be packed with less
// padding. This would also allow us to keep components with a size only known at runtime directly
// in here instead of having a pointer to an extra allocation.
#[derive(Debug, Default)]
pub struct CommandBuffer {
commands: Vec<Command>,
Expand Down
19 changes: 12 additions & 7 deletions ecs/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{
alloc::Layout,
alloc::{self, Layout},
any::{self, TypeId},
borrow::Cow,
ptr,
};

mod command;
Expand Down Expand Up @@ -29,7 +30,8 @@ use crate::{Entities, Entity};
/// commands.despawn(e1);
///
/// assert!(world.entities().exists(e2)); // NOTE: some commands, like spawning entities happen immediately
/// assert!(world.entities().exists(e1)); // but others happen when the command buffer is applied
/// assert!(world.entities().exists(e1)); // but others, like despawning happen when the command
/// // buffer is applied
/// assert!(world.get::<Position>(e2).is_none());
///
/// command_buffer.apply(&mut world);
Expand All @@ -50,7 +52,7 @@ impl<'b, 'e> Commands<'b, 'e> {
}

/// Creates a new `entity`. See `Entities::spawn` for more information.
pub fn spawn(&mut self) -> Entity {
pub fn spawn(&self) -> Entity {
self.entities.spawn()
}

Expand All @@ -67,15 +69,18 @@ impl<'b, 'e> Commands<'b, 'e> {
unsafe fn drop<T: 'static>(ptr: *mut u8) {
ptr.cast::<T>().drop_in_place();
}
let component = Box::new(component);
let component = Box::into_raw(component);
let component = component as *mut u8;
let layout = Layout::new::<T>();
let component = unsafe {
let p = alloc::alloc(layout);
ptr::write(p as *mut T, component);
p
};
self.buffer.add(Command::AddComponent {
entity,
type_id: TypeId::of::<T>(),
name: Cow::Borrowed(any::type_name::<T>()),
component,
layout: Layout::new::<T>(),
layout,
drop: drop::<T>,
});
}
Expand Down
4 changes: 2 additions & 2 deletions ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ mod tests {
let pos_id = world.component_registry_mut().register::<Position>();
let vel_id = world.component_registry_mut().register::<Velocity>();

for i in 0..1000 {
for i in 0..100 {
let entity = world.spawn();
world.add(entity, Position(i as f32));
world.add(entity, Velocity(1.5));
Expand Down Expand Up @@ -896,7 +896,7 @@ mod tests {
let mut commands = Commands::new(&mut command_buffer, world.entities());

let e1 = commands.spawn();
commands.add(e1, Counter::named(counter.clone(), "a"));
commands.add(e1, Counter::new(counter.clone()));
assert_eq!(counter.get(), 1);
}

Expand Down
14 changes: 14 additions & 0 deletions ecs/src/query/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ macro_rules! _query_defvars_combs {
( $comps1:expr, $comps2:expr, $lt:expr, $entity:expr, ($name:tt: Entity) ) => {
let $name = $entity;
};
// opt
( $comps1:expr, $comps2:expr, $lt:expr, $entity:expr, ($name:tt: Option<$type:ty>) ) => {
let $name = unsafe { (
$crate::query::_as_opt_ref_lt($lt, $comps1[0].cast::<$type>()),
$crate::query::_as_opt_ref_lt($lt, $comps2[0].cast::<$type>()),
) };
};
// opt mut
( $comps1:expr, $comps2:expr, $lt:expr, $entity:expr, ($name:tt: mut Option<$type:ty>) ) => {
let $name = unsafe { (
$crate::query::_as_opt_mut_lt($lt, $comps1[0].cast::<$type>()),
$crate::query::_as_opt_mut_lt($lt, $comps2[0].cast::<$type>()),
) };
};
// comp
( $comps1:expr, $comps2:expr, $lt:expr, $entity:expr, ($name:tt: $type:ty) ) => {
let $name = unsafe { (
Expand Down
12 changes: 7 additions & 5 deletions ecs/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,13 @@ impl<'a, 'r, 'q> Iterator for Iter<'a, 'r, 'q> {
type Item = (Entity, Vec<*mut u8>);

fn next(&mut self) -> Option<Self::Item> {
self.entity_iter.next().and_then(|e| unsafe {
self.res
.try_get_by_index(self.entity_iter.entities().id(e).unwrap())
.map(|comps| (e, comps))
})
loop {
let entity = self.entity_iter.next()?;
let id = self.entity_iter.entities().id(entity).unwrap();
if let Some(comps) = unsafe { self.res.try_get_by_index(id) } {
return Some((entity, comps));
}
}
}
}

Expand Down
69 changes: 40 additions & 29 deletions examples/runtime/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ use winit::{
event_loop::EventLoop,
};

use common::{Vec2, Vec3};
use common::{Transform, Vec2, Vec3};
use game_engine::{
ecs::query_iter,
physics,
rendering::{Line, Renderer},
rendering::{Camera, Light, Line, Renderer, WorldId},
Engine,
};

use crate::{
camera_controller::CameraController,
physics_context::PhysicsScene,
physics_context::setup_scene,
window::{Window, WindowMode},
};

Expand All @@ -27,7 +28,7 @@ pub struct Editor {
state: EguiWinitState,
egui_context: EguiContext,
camera_controller: CameraController,
scene: PhysicsScene,
camera: Camera,
last_frame: Instant,
}

Expand Down Expand Up @@ -64,7 +65,16 @@ impl Editor {
Vec2::new(-0.3, 135f32.to_radians()),
);

let scene = PhysicsScene::new(&mut engine).with_context(|| "failed to create the scene")?;
let camera = Camera {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: Vec3::unit_y(),
fovy: 45f32.to_radians(),
znear: 0.1,
zfar: 2000.0,
};

setup_scene(&mut engine).with_context(|| "failed to set up scene")?;
let state = EguiWinitState::new(4096, window.winit_window());
let egui_context = EguiContext::default();
{
Expand All @@ -80,7 +90,7 @@ impl Editor {
state,
egui_context,
camera_controller,
scene,
camera,
last_frame: Instant::now(),
},
))
Expand Down Expand Up @@ -163,11 +173,11 @@ impl Editor {
self.last_frame = now;

self.engine.update();
self.scene.update(&mut self.engine);

self.camera_controller
.update_camera(dt, &mut self.engine.renderer.camera);
self.engine.renderer.update_camera();
let world_id = *self.engine.world.resource::<WorldId>().unwrap();

self.camera_controller.update_camera(dt, &mut self.camera);
self.engine.renderer.set_camera(world_id, self.camera);

let pos_r = || -100.0..=100.0;
let k_r = || 0.0..=1.0;
Expand All @@ -177,23 +187,25 @@ impl Editor {
egui::Window::new("The Stuff®")
.auto_sized()
.show(ctx, |ui| {
ui.label("Light position");
ui.spacing_mut().slider_width *= 2.0;
ui.add(Slider::new(&mut self.scene.light.pos.x, pos_r()).text("x"));
ui.add(Slider::new(&mut self.scene.light.pos.y, pos_r()).text("y"));
ui.add(Slider::new(&mut self.scene.light.pos.z, pos_r()).text("z"));

ui.label("scene.Light attenuation factors");
ui.add(Slider::new(&mut self.scene.light.k_constant, k_r()).text("k_c"));
ui.add(Slider::new(&mut self.scene.light.k_linear, k_r()).text("k_l"));
ui.add(Slider::new(&mut self.scene.light.k_quadratic, k_r()).text("k_q"));

ui.label("Light color");
egui::widgets::color_picker::color_edit_button_rgb(
ui,
&mut self.scene.light.color,
);

let mut deferred = self.engine.renderer.get_deferred(world_id);
ui.checkbox(&mut deferred, "Use deferred rendering");
self.engine.renderer.set_deferred(world_id, deferred);
query_iter!(self.engine.world, (transform: mut Transform, light: mut Light) => {
ui.label("Light position");
ui.spacing_mut().slider_width *= 2.0;
ui.add(Slider::new(&mut transform.position.x, pos_r()).text("x"));
ui.add(Slider::new(&mut transform.position.y, pos_r()).text("y"));
ui.add(Slider::new(&mut transform.position.z, pos_r()).text("z"));

ui.label("scene.Light attenuation factors");
ui.add(Slider::new(&mut light.k_constant, k_r()).text("k_c"));
ui.add(Slider::new(&mut light.k_linear, k_r()).text("k_l"));
ui.add(Slider::new(&mut light.k_quadratic, k_r()).text("k_q"));

ui.label("Light color");
egui::widgets::color_picker::color_edit_button_rgb(ui, &mut light.color);

});
if let Some(gravity) = self.engine.world.resource_mut::<physics::Gravity>() {
ui.label("Gravity");
ui.add(Slider::new(&mut gravity.0.y, -20.0..=20.0).text("k_q"));
Expand All @@ -210,12 +222,11 @@ impl Editor {

if self.window.inner_size() != (0, 0) {
match self.engine.renderer.render(
world_id,
lines,
&[self.scene.light],
&self.egui_context,
full_output,
self.egui_context.pixels_per_point(),
false,
) {
Ok(_) => (),
Err(e) => log::error!("Failed to render: {}", e),
Expand Down
Loading