diff --git a/crates/editor/src/main.rs b/crates/editor/src/main.rs index c2f13a39..a294db68 100644 --- a/crates/editor/src/main.rs +++ b/crates/editor/src/main.rs @@ -16,7 +16,7 @@ use glam::{Quat, Vec3, Vec4}; use render::{ components::{ camera::{Camera, RenderTarget}, - light::{LighType, Light, SpotLight}, + light::{Light, LightType, SpotLight}, }, plugin::RenderPlugin, }; @@ -79,8 +79,8 @@ fn spawn_scene(mut cmd: CommandQueue, rtt: Res) { Light { color: Vec4::new(1.0, 0.95, 0.85, 1.0), intensity: 15.0, - light_type: LighType::Spot(SpotLight { - cone_angle: 60.0 * PI / 180.0, + light_type: LightType::Spot(SpotLight { + cone_angle: 60.0_f32.to_radians(), }), }, light_transform, diff --git a/crates/essential/src/transform/mod.rs b/crates/essential/src/transform/mod.rs index 0e3048a0..4a092013 100644 --- a/crates/essential/src/transform/mod.rs +++ b/crates/essential/src/transform/mod.rs @@ -19,7 +19,7 @@ impl Component for Transform { fn on_add() -> Option { Some(|mut world, context| { - let global_transform = GlobalTranform::new( + let global_transform = GlobalTransform::new( world .get_component_for_entity::(context.entity) .unwrap() @@ -32,11 +32,17 @@ impl Component for Transform { fn on_remove() -> Option { Some(|mut world, context| { - world.remove_component::(context.entity, false); + world.remove_component::(context.entity, false); }) } } +impl Default for Transform { + fn default() -> Self { + Self::IDENTITY + } +} + impl Transform { pub const IDENTITY: Self = Self { translation: Vec3::ZERO, @@ -64,6 +70,45 @@ impl Transform { } } + pub fn from_translation(translation: Vec3) -> Self { + Self { + translation, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, + } + } + + pub fn from_rotation(rotation: Quat) -> Self { + Self { + translation: Vec3::ZERO, + rotation, + scale: Vec3::ONE, + } + } + + pub fn from_scale(scale: Vec3) -> Self { + Self { + translation: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale, + } + } + + pub fn with_translation(mut self, translation: Vec3) -> Self { + self.translation = translation; + self + } + + pub fn with_rotation(mut self, rotation: Quat) -> Self { + self.rotation = rotation; + self + } + + pub fn with_scale(mut self, scale: Vec3) -> Self { + self.scale = scale; + self + } + pub fn from_matrix(matrix: &[[f32; 4]; 4]) -> Self { let (scale, rotation, translation) = Mat4::from_cols_array_2d(matrix).to_scale_rotation_translation(); @@ -120,9 +165,9 @@ impl Transform { } #[derive(Component)] -pub struct GlobalTranform(Affine3A); +pub struct GlobalTransform(Affine3A); -impl GlobalTranform { +impl GlobalTransform { pub fn new(transform: Mat4) -> Self { Self(Affine3A::from_mat4(transform)) } diff --git a/crates/essential/src/transform/systems.rs b/crates/essential/src/transform/systems.rs index 66a56972..ffd9d58e 100644 --- a/crates/essential/src/transform/systems.rs +++ b/crates/essential/src/transform/systems.rs @@ -9,11 +9,11 @@ use ecs::{ }, }; -use crate::transform::{GlobalTranform, Transform}; +use crate::transform::{GlobalTransform, Transform}; pub fn update_simple_entities( roots: Query< - (&Transform, &mut GlobalTranform), + (&Transform, &mut GlobalTransform), (Changed, Without, Without), >, ) { @@ -23,8 +23,8 @@ pub fn update_simple_entities( } pub fn propagate_global_transforms( - roots: Query<(&Children, &mut GlobalTranform, &Transform), Without>, - transform_query: Query<(Entity, &mut GlobalTranform, &Transform, Option<&Children>)>, + roots: Query<(&Children, &mut GlobalTransform, &Transform), Without>, + transform_query: Query<(Entity, &mut GlobalTransform, &Transform, Option<&Children>)>, ) { for (root_children, mut root_global_transform, root_local_transform) in roots.iter() { root_global_transform.set_matrix(root_local_transform.compute_matrix()); @@ -33,9 +33,9 @@ pub fn propagate_global_transforms( } fn propagate_to_children( - parent_transform: &GlobalTranform, + parent_transform: &GlobalTransform, children: &Children, - transform_query: &Query<(Entity, &mut GlobalTranform, &Transform, Option<&Children>)>, + transform_query: &Query<(Entity, &mut GlobalTransform, &Transform, Option<&Children>)>, ) { for child in children { if let Some((_, mut child_global_transform, child_local_transform, grand_children)) = diff --git a/crates/render/src/components/camera.rs b/crates/render/src/components/camera.rs index 334f857c..415918a3 100644 --- a/crates/render/src/components/camera.rs +++ b/crates/render/src/components/camera.rs @@ -1,7 +1,7 @@ use encase::{ShaderType, UniformBuffer}; use essential::{ assets::{asset_store::AssetStore, handle::AssetHandle}, - transform::GlobalTranform, + transform::GlobalTransform, }; use ecs::{ @@ -58,8 +58,18 @@ pub struct Camera { } impl Camera { + /// Creates a perspective camera with the given field-of-view (radians) and aspect ratio. + /// Uses sensible defaults for near/far planes and clear colour. + pub fn perspective(fovy: f32, aspect: f32) -> Self { + Self { + fovy, + aspect, + ..Default::default() + } + } + pub fn build_projection_matrix(&self) -> Mat4 { - Mat4::perspective_rh(self.fovy.to_radians(), self.aspect, self.znear, self.zfar) + Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar) } } @@ -67,7 +77,7 @@ impl Default for Camera { fn default() -> Self { Self { aspect: 1.0, - fovy: 45.0, + fovy: std::f32::consts::FRAC_PI_4, znear: 0.1, zfar: 100.0, clear_color: wgpu::Color { @@ -96,7 +106,7 @@ impl CameraUniform { } } - pub fn update_view_proj(&mut self, camera: &Camera, transform: &GlobalTranform) { + pub fn update_view_proj(&mut self, camera: &Camera, transform: &GlobalTransform) { self.view_pos = transform.translation(); self.view_proj = OPENGL_TO_WGPU_MATRIX * camera.build_projection_matrix() * transform.matrix().inverse(); @@ -140,7 +150,7 @@ impl RenderCamera { } pub(crate) fn camera_added( - cameras: Query<(Entity, &Camera, &GlobalTranform, Option<&RenderEntity>), Added<(Camera,)>>, + cameras: Query<(Entity, &Camera, &GlobalTransform, Option<&RenderEntity>), Added<(Camera,)>>, mut cmd: CommandQueue, device: Res, context: Res, @@ -260,7 +270,7 @@ pub fn create_rtt( } pub(crate) fn camera_changed( - cameras: Query<(&Camera, &GlobalTranform, &RenderEntity)>, + cameras: Query<(&Camera, &GlobalTransform, &RenderEntity)>, render_cameras: Query<(&mut RenderCamera,)>, queue: Res, ) { diff --git a/crates/render/src/components/light.rs b/crates/render/src/components/light.rs index c0679d63..69e5fe28 100644 --- a/crates/render/src/components/light.rs +++ b/crates/render/src/components/light.rs @@ -7,7 +7,7 @@ use ecs::{ }; use encase::{ShaderType, UniformBuffer}; -use essential::transform::GlobalTranform; +use essential::transform::GlobalTransform; use glam::{Vec3, Vec4}; use wgpu::{util::DeviceExt, BindGroupDescriptor, Buffer}; @@ -19,25 +19,25 @@ const MAX_LIGHTS: usize = 128; pub struct Light { pub color: Vec4, pub intensity: f32, - pub light_type: LighType, + pub light_type: LightType, } pub struct SpotLight { pub cone_angle: f32, } -pub enum LighType { +pub enum LightType { Point, Spot(SpotLight), Directional, } -impl LighType { +impl LightType { pub fn index(&self) -> u32 { match *self { - LighType::Point => 0, - LighType::Spot(_) => 1, - LighType::Directional => 2, + LightType::Point => 0, + LightType::Spot(_) => 1, + LightType::Directional => 2, } } } @@ -139,7 +139,7 @@ pub(crate) fn prepare_lights_buffer( } pub(crate) fn light_added( - lights: Query<(Entity, &Light, &GlobalTranform, Option<&RenderEntity>), Added>, + lights: Query<(Entity, &Light, &GlobalTransform, Option<&RenderEntity>), Added>, mut cmd: CommandQueue, ) { for (entity, light, light_transform, render_entity) in lights.iter() { @@ -151,7 +151,7 @@ pub(crate) fn light_added( direction: -local_z, light_type: light.light_type.index(), cos_cone_angle: match &light.light_type { - LighType::Spot(spot_light) => f32::cos(spot_light.cone_angle), + LightType::Spot(spot_light) => f32::cos(spot_light.cone_angle), _ => 0.0, }, }; @@ -168,7 +168,7 @@ pub(crate) fn light_added( } pub(crate) fn light_changed( - lights: Query<(&Light, &GlobalTranform, &RenderEntity)>, + lights: Query<(&Light, &GlobalTransform, &RenderEntity)>, render_lights: Query<&mut RenderLight>, ) { for (light, transform, render_entity) in lights.iter() { @@ -180,7 +180,7 @@ pub(crate) fn light_changed( render_light.intensity = light.intensity; render_light.light_type = light.light_type.index(); render_light.cos_cone_angle = match &light.light_type { - LighType::Spot(spot_light) => f32::cos(spot_light.cone_angle), + LightType::Spot(spot_light) => f32::cos(spot_light.cone_angle), _ => 0.0, }; } diff --git a/crates/render/src/components/mesh_component.rs b/crates/render/src/components/mesh_component.rs index b268aa93..14db6667 100644 --- a/crates/render/src/components/mesh_component.rs +++ b/crates/render/src/components/mesh_component.rs @@ -6,7 +6,7 @@ use ecs::{ }; use essential::{ assets::{handle::AssetHandle, AssetId}, - transform::{GlobalTranform, Transform}, + transform::{GlobalTransform, Transform}, }; use wgpu::util::DeviceExt; @@ -31,7 +31,7 @@ pub(crate) fn mesh_added( ( Entity, &MeshComponent, - &GlobalTranform, + &GlobalTransform, Option<&RenderEntity>, ), Added<(MeshComponent,)>, @@ -64,7 +64,7 @@ pub(crate) fn mesh_added( } pub(crate) fn mesh_changed( - meshes: Query<(&MeshComponent, &GlobalTranform, &RenderEntity), Changed<(Transform,)>>, + meshes: Query<(&MeshComponent, &GlobalTransform, &RenderEntity), Changed<(Transform,)>>, render_meshes: Query<(&mut RenderMeshInstance,)>, queue: Res, ) { diff --git a/crates/render/src/components/skeleton_component.rs b/crates/render/src/components/skeleton_component.rs index e5b78997..45bb987e 100644 --- a/crates/render/src/components/skeleton_component.rs +++ b/crates/render/src/components/skeleton_component.rs @@ -14,7 +14,7 @@ use ecs::{ use encase::UniformBuffer; use essential::{ assets::{asset_store::AssetStore, handle::AssetHandle}, - transform::GlobalTranform, + transform::GlobalTransform, }; use glam::Mat4; use wgpu::{util::DeviceExt, BindGroupDescriptor, BufferDescriptor, Device}; @@ -115,7 +115,7 @@ pub(crate) fn skeleton_added( pub(crate) fn update_skeletons( skeletons: Query<(&SkeletonComponent, &RenderEntity)>, render_skeletons: Query<&RenderSkeletonComponent>, - transforms: Query<&GlobalTranform>, + transforms: Query<&GlobalTransform>, skeleton_assets: Res>, queue: Res, ) { diff --git a/crates/window/src/input/mod.rs b/crates/window/src/input/mod.rs index a5bc3163..1c4bd6f5 100644 --- a/crates/window/src/input/mod.rs +++ b/crates/window/src/input/mod.rs @@ -46,6 +46,21 @@ impl Input { } } + pub fn is_just_pressed(&self, key: PhysicalKey) -> bool { + self.get_key_state(key) == InputState::Pressed + } + + pub fn is_held(&self, key: PhysicalKey) -> bool { + matches!( + self.get_key_state(key), + InputState::Pressed | InputState::Down + ) + } + + pub fn is_just_released(&self, key: PhysicalKey) -> bool { + self.get_key_state(key) == InputState::Released + } + pub fn mouse_delta(&self) -> Vec2 { self.mouse_delta } @@ -61,6 +76,21 @@ impl Input { } } + pub fn is_mouse_button_just_pressed(&self, button: MouseButton) -> bool { + self.get_mouse_button_state(button) == InputState::Pressed + } + + pub fn is_mouse_button_held(&self, button: MouseButton) -> bool { + matches!( + self.get_mouse_button_state(button), + InputState::Pressed | InputState::Down + ) + } + + pub fn is_mouse_button_just_released(&self, button: MouseButton) -> bool { + self.get_mouse_button_state(button) == InputState::Released + } + /// Characters typed this frame (text input, after modifier keys are applied). /// Cleared at the start of each frame by the `update_input` system. pub fn typed_chars(&self) -> &[char] { diff --git a/examples/game/src/main.rs b/examples/game/src/main.rs index ae324689..1710dde0 100644 --- a/examples/game/src/main.rs +++ b/examples/game/src/main.rs @@ -12,7 +12,7 @@ use game_engine::{ }, essential::{ assets::asset_server::AssetServer, - transform::{GlobalTranform, Transform}, + transform::{GlobalTransform, Transform}, }, obj_loader::obj_loader::{OBJAsset, OBJSpawnerComponent}, physics::{physics_state::PhysicsState, rigid_body::RigidBody}, @@ -20,7 +20,7 @@ use game_engine::{ assets::{material::StandardMaterial, texture::TextureUsageSettings}, components::{ camera::Camera, - light::{LighType, Light, SpotLight}, + light::{Light, LightType, SpotLight}, material_component::MaterialComponent, mesh_component::MeshComponent, }, @@ -126,8 +126,8 @@ fn spawn_player( let light = Light { color: Vec4::new(1.0, 0.0, 1.0, 1.0), intensity: 10.0, - light_type: LighType::Spot(SpotLight { - cone_angle: 50.0 * PI / 180.0, + light_type: LightType::Spot(SpotLight { + cone_angle: 50.0_f32.to_radians(), }), }; let mut light_transform = @@ -193,7 +193,7 @@ fn spawn_unlit_obj( } fn spawn_with_collider( - cameras: Query<(&Camera, &GlobalTranform)>, + cameras: Query<(&Camera, &GlobalTransform)>, mut cmd: CommandQueue, input: Res, asset_server: Res, diff --git a/examples/render-test/src/main.rs b/examples/render-test/src/main.rs index 0af3ebdd..080ec418 100644 --- a/examples/render-test/src/main.rs +++ b/examples/render-test/src/main.rs @@ -13,7 +13,7 @@ use glam::{Quat, Vec3, Vec4}; use render::{ assets::{material::StandardMaterial, mesh::Mesh, vertex::Vertex}, components::{ - light::{LighType, Light, SpotLight}, + light::{Light, LightType, SpotLight}, material_component::MaterialComponent, mesh_component::MeshComponent, }, @@ -115,7 +115,7 @@ fn spawn_camera_terminal( Light { color: Vec4::new(1.0, 1.0, 1.0, 1.0), intensity: 100.0, - light_type: LighType::Point, + light_type: LightType::Point, }, TerminalOutput, Transform::from_translation_rotation(Vec3::ZERO, Quat::IDENTITY), @@ -130,7 +130,7 @@ fn spawn_camera_windowed(mut cmd: CommandQueue) { Light { color: Vec4::new(1.0, 1.0, 1.0, 1.0), intensity: 10.0, - light_type: LighType::Point, + light_type: LightType::Point, }, ); }