Start sky box example
This commit is contained in:
parent
8205b91ec9
commit
0a93da3b5b
19 changed files with 535 additions and 469 deletions
|
@ -19,6 +19,7 @@ members = [
|
|||
"promise",
|
||||
"ring_buffer",
|
||||
"scene_update_macros",
|
||||
"skybox",
|
||||
"transaction_derive",
|
||||
]
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ impl ImageFormatChecker {
|
|||
self.image_data.height,
|
||||
)
|
||||
.format(initial_format)
|
||||
.attach_sampler(Sampler::pretty_sampler().build(device)?);
|
||||
.max_mip_map_levels()
|
||||
.attach_pretty_sampler(device)?;
|
||||
|
||||
let mut format = initial_format;
|
||||
|
||||
|
@ -35,7 +36,7 @@ impl ImageFormatChecker {
|
|||
return Err(anyhow::Error::msg(format!(
|
||||
"Image format {:?} for asset does not work",
|
||||
format
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,14 +22,6 @@ use std::rc::Rc;
|
|||
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub trait ContextObject {
|
||||
fn name(&self) -> &str;
|
||||
|
||||
fn update(&mut self) -> Result<()>;
|
||||
|
||||
fn event(&mut self, event: Event) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
core: VulkanCore,
|
||||
pub(crate) presentation: PresentationCore,
|
||||
|
@ -65,18 +57,17 @@ impl Context {
|
|||
&mut self.sound_handler
|
||||
}
|
||||
|
||||
pub fn next_frame<C>(&mut self, world: &mut World) -> Result<bool> {
|
||||
pub fn next_frame<C, F>(&mut self, world: &mut World, mut f: F) -> Result<bool>
|
||||
where
|
||||
C: Send + Sync + 'static,
|
||||
F: FnMut(&mut World, &mut C, Event) -> Result<()> + Send + Sync + 'static,
|
||||
{
|
||||
let render_core = self.render_core.clone();
|
||||
let consumer = world.resources.get_mut_unchecked::<C>();
|
||||
let w = unsafe { remove_life_time_mut(world) };
|
||||
|
||||
match self.presentation.poll_events(
|
||||
|event| {
|
||||
// TODO
|
||||
// if let Some(ctx_obj) = world.resources.get_mut_opt::<C>() {
|
||||
// ctx_obj.event(event)?;
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|event| f(w, consumer, event),
|
||||
|w, h| render_core.write().unwrap().resize(world, w, h),
|
||||
) {
|
||||
Ok(res) => {
|
||||
|
|
|
@ -2,5 +2,3 @@
|
|||
|
||||
pub mod core;
|
||||
pub mod prelude;
|
||||
|
||||
pub use crate::core::context::ContextObject;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use super::engine_object::*;
|
||||
use super::engine_event_handling::*;
|
||||
use super::engine_settings::EngineSettings;
|
||||
|
||||
use anyhow::Result;
|
||||
|
@ -11,7 +11,7 @@ use crate::assets::asset_manager::AssetManager;
|
|||
use crate::prelude::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct GuiPostProcess(Arc<GuiHandler>);
|
||||
|
||||
|
@ -34,8 +34,6 @@ impl context::prelude::PostProcess for GuiPostProcess {
|
|||
}
|
||||
|
||||
pub struct Engine {
|
||||
input: Arc<RwLock<Input>>,
|
||||
|
||||
// loads and keeps track of raw data
|
||||
asset_manager: AssetManager,
|
||||
|
||||
|
@ -43,7 +41,7 @@ pub struct Engine {
|
|||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn new(
|
||||
pub fn new<T: EventConsumer>(
|
||||
#[allow(unused)] mut create_info: EngineCreateInfo<'_>,
|
||||
world: &mut WorldBuilder,
|
||||
) -> Result<()> {
|
||||
|
@ -188,13 +186,12 @@ impl Engine {
|
|||
direction_mapping.insert(Keycode::Down, GuiDirection::Down);
|
||||
|
||||
let engine = Engine {
|
||||
input: Arc::new(RwLock::new(Input { direction_mapping })),
|
||||
|
||||
asset_manager,
|
||||
|
||||
resource_base_path: create_info.resource_base_path,
|
||||
};
|
||||
|
||||
world.resources.insert(InputMap { direction_mapping });
|
||||
world.resources.insert(context);
|
||||
world.resources.insert(engine);
|
||||
world.resources.insert(engine_settings);
|
||||
|
@ -208,7 +205,7 @@ impl Engine {
|
|||
|
||||
world.resources.insert(scene);
|
||||
|
||||
world.add_system(Self::main_system);
|
||||
world.add_system(Self::main_system::<T>);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -251,10 +248,25 @@ impl Engine {
|
|||
}
|
||||
|
||||
impl Engine {
|
||||
fn main_system(world: &mut World) -> Result<bool> {
|
||||
fn main_system<T: EventConsumer>(world: &mut World) -> Result<bool> {
|
||||
world
|
||||
.resources
|
||||
.get_mut_unchecked::<Context>()
|
||||
.next_frame::<()>(world)
|
||||
.get::<Arc<GuiHandler>>()
|
||||
.process_callbacks()?;
|
||||
|
||||
let gui_handler = world.resources.get_unchecked::<Arc<GuiHandler>>();
|
||||
let input_map = world.resources.get_unchecked::<InputMap>();
|
||||
let context = world.resources.get_unchecked::<Context>();
|
||||
|
||||
let res = world.resources.get_mut_unchecked::<Context>().next_frame(
|
||||
world,
|
||||
|world, consumer: &mut T, event| {
|
||||
Self::event(world, context, gui_handler, input_map, consumer, event)
|
||||
},
|
||||
)?;
|
||||
|
||||
gui_handler.process_callbacks()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
|
332
engine/src/engine/engine_event_handling.rs
Normal file
332
engine/src/engine/engine_event_handling.rs
Normal file
|
@ -0,0 +1,332 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
// use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EngineEvent {
|
||||
MouseMotion(u32, u32),
|
||||
MouseButtonDown(MouseButton),
|
||||
MouseButtonUp(MouseButton),
|
||||
MouseWheel(i32, i32, MouseWheelDirection),
|
||||
|
||||
KeyDown(Keycode),
|
||||
KeyUp(Keycode),
|
||||
|
||||
ButtonDown(ControllerButton),
|
||||
ButtonUp(ControllerButton),
|
||||
ControllerAxis(ControllerAxis),
|
||||
|
||||
ControllerAdded(Arc<RwLock<Controller>>),
|
||||
ControllerRemoved(Arc<RwLock<Controller>>),
|
||||
|
||||
FileDrop(String),
|
||||
}
|
||||
|
||||
pub trait EventConsumer: Send + Sync + 'static {
|
||||
fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct InputMap {
|
||||
pub direction_mapping: HashMap<Keycode, GuiDirection>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub(crate) fn event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
context: &Context,
|
||||
gui_handler: &GuiHandler,
|
||||
input: &InputMap,
|
||||
consumer: &mut T,
|
||||
event: Event,
|
||||
) -> anyhow::Result<()> {
|
||||
match event {
|
||||
Event::MouseMotion(x, y) => {
|
||||
gui_handler.set_mouse_pos(x, y)?;
|
||||
consumer.event(world, EngineEvent::MouseMotion(x, y))?;
|
||||
}
|
||||
Event::MouseButtonDown(mouse_button) => {
|
||||
if !gui_handler.mouse_down(mouse_button)? {
|
||||
consumer.event(world, EngineEvent::MouseButtonDown(mouse_button))?;
|
||||
}
|
||||
}
|
||||
Event::MouseButtonUp(mouse_button) => {
|
||||
if !gui_handler.mouse_up(mouse_button)? {
|
||||
consumer.event(world, EngineEvent::MouseButtonUp(mouse_button))?;
|
||||
}
|
||||
}
|
||||
Event::MouseWheel(x, y, direction) => {
|
||||
consumer.event(world, EngineEvent::MouseWheel(x, y, direction))?
|
||||
}
|
||||
Event::KeyDown(keycode) => {
|
||||
Self::key_down_event(world, context, gui_handler, input, consumer, keycode)?;
|
||||
}
|
||||
Event::KeyUp(keycode) => {
|
||||
Self::key_up_event(world, gui_handler, input, consumer, keycode)?;
|
||||
}
|
||||
Event::TextInput(text) => {
|
||||
Self::text_input(gui_handler, text)?;
|
||||
}
|
||||
Event::ControllerButtonDown(button) => {
|
||||
Self::button_down_event(world, gui_handler, consumer, button)?;
|
||||
}
|
||||
Event::ControllerButtonUp(button) => {
|
||||
Self::button_up_event(world, consumer, button)?;
|
||||
}
|
||||
Event::ControllerAxis(controller) => {
|
||||
let controller = controller.read().unwrap();
|
||||
|
||||
if !gui_handler.check_navigatable()? {
|
||||
Self::axis_event(world, consumer, &controller)?
|
||||
} else {
|
||||
gui_handler.update_selection(controller.direction())?;
|
||||
}
|
||||
}
|
||||
Event::ControllerAdded(controller) => {
|
||||
Self::controller_added(world, consumer, controller)?
|
||||
}
|
||||
Event::ControllerRemoved(controller) => {
|
||||
Self::controller_removed(world, consumer, controller)?
|
||||
}
|
||||
Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
#[inline]
|
||||
fn controller_added<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
consumer: &mut T,
|
||||
controller: Arc<RwLock<Controller>>,
|
||||
) -> Result<()> {
|
||||
consumer.event(world, EngineEvent::ControllerAdded(controller))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn controller_removed<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
consumer: &mut T,
|
||||
controller: Arc<RwLock<Controller>>,
|
||||
) -> Result<()> {
|
||||
consumer.event(world, EngineEvent::ControllerRemoved(controller))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn key_up_event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
gui_handler: &GuiHandler,
|
||||
input: &InputMap,
|
||||
consumer: &mut T,
|
||||
keycode: Keycode,
|
||||
) -> Result<()> {
|
||||
if input.direction_mapping.get(&keycode).is_some()
|
||||
&& gui_handler.update_selection(GuiDirection::None)?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
consumer.event(world, EngineEvent::KeyUp(keycode))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn key_down_event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
context: &Context,
|
||||
gui_handler: &GuiHandler,
|
||||
input: &InputMap,
|
||||
consumer: &mut T,
|
||||
keycode: Keycode,
|
||||
) -> Result<()> {
|
||||
if let Some(direction) = input.direction_mapping.get(&keycode) {
|
||||
if gui_handler.update_selection(*direction)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
match keycode {
|
||||
Keycode::Backspace => {
|
||||
if gui_handler.remove_char()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::Return => {
|
||||
if gui_handler.accept_selection()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::Escape => {
|
||||
if gui_handler.decline_topgui()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::V => {
|
||||
if let Some(writeable) = gui_handler.writeable()? {
|
||||
if let Some(content) = context.window_config().clipboard_content()? {
|
||||
writeable.set_text(content)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
consumer.event(world, EngineEvent::KeyDown(keycode))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn button_up_event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
consumer: &mut T,
|
||||
button: ControllerButton,
|
||||
) -> Result<()> {
|
||||
consumer.event(world, EngineEvent::ButtonUp(button))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn button_down_event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
gui_handler: &GuiHandler,
|
||||
consumer: &mut T,
|
||||
button: ControllerButton,
|
||||
) -> Result<()> {
|
||||
if gui_handler.check_navigatable()? {
|
||||
Self::check_button_down(world, gui_handler, consumer, button)?;
|
||||
} else {
|
||||
consumer.event(world, EngineEvent::ButtonDown(button))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn axis_event<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
consumer: &mut T,
|
||||
controller: &Controller,
|
||||
) -> Result<()> {
|
||||
consumer.event(
|
||||
world,
|
||||
EngineEvent::ControllerAxis(controller.controller_axis()),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_button_down<T: EventConsumer>(
|
||||
world: &mut World,
|
||||
gui_handler: &GuiHandler,
|
||||
consumer: &mut T,
|
||||
button: ControllerButton,
|
||||
) -> Result<()> {
|
||||
match button {
|
||||
ControllerButton::A => {
|
||||
if gui_handler.accept_selection()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::B => {
|
||||
if gui_handler.decline_topgui()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::RightButton => {
|
||||
if gui_handler.next_tab_topgui(false)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::LeftButton => {
|
||||
if gui_handler.previous_tab_topgui(false)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::RightTrigger => {
|
||||
if gui_handler.next_tab_topgui(true)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::LeftTrigger => {
|
||||
if gui_handler.previous_tab_topgui(true)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadDown => {
|
||||
let selection_res = gui_handler.update_selection(GuiDirection::Down)?;
|
||||
gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadUp => {
|
||||
let selection_res = gui_handler.update_selection(GuiDirection::Up)?;
|
||||
gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadRight => {
|
||||
let selection_res = gui_handler.update_selection(GuiDirection::Right)?;
|
||||
gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadLeft => {
|
||||
let selection_res = gui_handler.update_selection(GuiDirection::Left)?;
|
||||
gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if !gui_handler.accept_custom_selection(button)? {
|
||||
consumer.event(world, EngineEvent::ButtonDown(button))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn text_input(gui_handler: &GuiHandler, text: String) -> Result<()> {
|
||||
if let Some(writeable) = gui_handler.writeable()? {
|
||||
for c in text.chars() {
|
||||
writeable.add_letter(c)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,420 +0,0 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use anyhow::Result;
|
||||
use context::ContextObject;
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
// use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EngineEvent {
|
||||
MouseMotion(u32, u32),
|
||||
MouseButtonDown(MouseButton),
|
||||
MouseButtonUp(MouseButton),
|
||||
MouseWheel(i32, i32, MouseWheelDirection),
|
||||
|
||||
KeyDown(Keycode),
|
||||
KeyUp(Keycode),
|
||||
|
||||
ButtonDown(ControllerButton),
|
||||
ButtonUp(ControllerButton),
|
||||
ControllerAxis(ControllerAxis),
|
||||
|
||||
ControllerAdded(Arc<RwLock<Controller>>),
|
||||
ControllerRemoved(Arc<RwLock<Controller>>),
|
||||
|
||||
FileDrop(String),
|
||||
}
|
||||
|
||||
// pub trait EngineObjectHelper: Any {
|
||||
// type Payload: Send + Sync;
|
||||
|
||||
// fn access(&self) -> EngineObjectAccess<'_, Self::Payload>;
|
||||
// fn payload(&self) -> EngineObjectDataHandle<Self::Payload>;
|
||||
// fn ui(&self) -> &States;
|
||||
// fn ui_mut(&mut self) -> &mut States;
|
||||
|
||||
// fn access_callback_mut<'a, F>(
|
||||
// &'a self,
|
||||
// f: F,
|
||||
// ) -> impl FnMut() -> Result<()> + Send + Sync + 'static
|
||||
// where
|
||||
// F: FnMut(EngineObjectAccess<'a, Self::Payload>) -> Result<()> + Send + Sync + 'static,
|
||||
// {
|
||||
// self.payload().access_callback_mut(f)
|
||||
// }
|
||||
|
||||
// fn access_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static
|
||||
// where
|
||||
// F: Fn(EngineObjectAccess<'_, Self::Payload>) -> Result<()> + Send + Sync + 'static,
|
||||
// {
|
||||
// self.payload().access_callback(f)
|
||||
// }
|
||||
|
||||
// fn handle_callback_mut<F>(&self, mut f: F) -> impl FnMut() -> Result<()> + Send + Sync + 'static
|
||||
// where
|
||||
// F: FnMut(
|
||||
// EngineObjectDataHandle<Self::Payload>,
|
||||
// EngineObjectAccess<'_, Self::Payload>,
|
||||
// ) -> Result<()>
|
||||
// + Send
|
||||
// + Sync
|
||||
// + 'static,
|
||||
// {
|
||||
// let handle = self.payload();
|
||||
|
||||
// move || {
|
||||
// let data = handle.as_data();
|
||||
// let access = data.access();
|
||||
|
||||
// f(handle.copy(), access)
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn handle_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static
|
||||
// where
|
||||
// F: Fn(
|
||||
// EngineObjectDataHandle<Self::Payload>,
|
||||
// EngineObjectAccess<'_, Self::Payload>,
|
||||
// ) -> Result<()>
|
||||
// + Send
|
||||
// + Sync
|
||||
// + 'static,
|
||||
// {
|
||||
// let handle = self.payload();
|
||||
|
||||
// move || {
|
||||
// let data = handle.as_data();
|
||||
// let access = data.access();
|
||||
|
||||
// f(handle.copy(), access)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
pub trait EngineObject: Any {
|
||||
fn name(&self) -> &str;
|
||||
|
||||
fn update(&mut self) -> Result<()>;
|
||||
fn event(&mut self, event: EngineEvent) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct Input {
|
||||
pub direction_mapping: HashMap<Keycode, GuiDirection>,
|
||||
}
|
||||
|
||||
pub struct ContextObjectImpl<E>
|
||||
where
|
||||
E: EngineObject + Send + Sync,
|
||||
{
|
||||
engine_object: E,
|
||||
|
||||
context: Arc<Context>,
|
||||
input: Arc<RwLock<Input>>,
|
||||
gui_handler: Arc<GuiHandler>,
|
||||
|
||||
ctrl_pressed: bool,
|
||||
}
|
||||
|
||||
impl<E> ContextObjectImpl<E>
|
||||
where
|
||||
E: EngineObject + Send + Sync,
|
||||
{
|
||||
pub fn new(
|
||||
context: Arc<Context>,
|
||||
engine_object: E,
|
||||
input: Arc<RwLock<Input>>,
|
||||
gui_handler: Arc<GuiHandler>,
|
||||
) -> Result<Self> {
|
||||
Ok(ContextObjectImpl {
|
||||
context,
|
||||
engine_object,
|
||||
input,
|
||||
gui_handler,
|
||||
ctrl_pressed: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ContextObject for ContextObjectImpl<E>
|
||||
where
|
||||
E: EngineObject + Send + Sync,
|
||||
{
|
||||
fn name(&self) -> &str {
|
||||
self.engine_object.name()
|
||||
}
|
||||
|
||||
fn update(&mut self) -> anyhow::Result<()> {
|
||||
self.gui_handler.process_callbacks()?;
|
||||
self.engine_object.update()
|
||||
}
|
||||
|
||||
fn event(&mut self, event: Event) -> anyhow::Result<()> {
|
||||
match event {
|
||||
Event::MouseMotion(x, y) => {
|
||||
self.gui_handler.set_mouse_pos(x, y)?;
|
||||
self.engine_object.event(EngineEvent::MouseMotion(x, y))?;
|
||||
}
|
||||
Event::MouseButtonDown(mouse_button) => {
|
||||
if !self.gui_handler.mouse_down(mouse_button)? {
|
||||
self.engine_object
|
||||
.event(EngineEvent::MouseButtonDown(mouse_button))?;
|
||||
}
|
||||
}
|
||||
Event::MouseButtonUp(mouse_button) => {
|
||||
if !self.gui_handler.mouse_up(mouse_button)? {
|
||||
self.engine_object
|
||||
.event(EngineEvent::MouseButtonUp(mouse_button))?;
|
||||
}
|
||||
}
|
||||
Event::MouseWheel(x, y, direction) => self
|
||||
.engine_object
|
||||
.event(EngineEvent::MouseWheel(x, y, direction))?,
|
||||
Event::KeyDown(keycode) => {
|
||||
self.key_down_event(keycode)?;
|
||||
}
|
||||
Event::KeyUp(keycode) => {
|
||||
self.key_up_event(keycode)?;
|
||||
}
|
||||
Event::TextInput(text) => {
|
||||
self.text_input(text)?;
|
||||
}
|
||||
Event::ControllerButtonDown(button) => {
|
||||
self.button_down_event(button)?;
|
||||
}
|
||||
Event::ControllerButtonUp(button) => {
|
||||
self.button_up_event(button)?;
|
||||
}
|
||||
Event::ControllerAxis(controller) => {
|
||||
let controller = controller.read().unwrap();
|
||||
|
||||
if !self.gui_handler.check_navigatable()? {
|
||||
self.axis_event(&controller)?
|
||||
} else {
|
||||
self.gui_handler.update_selection(controller.direction())?;
|
||||
}
|
||||
}
|
||||
Event::ControllerAdded(controller) => self.controller_added(controller)?,
|
||||
Event::ControllerRemoved(controller) => self.controller_removed(controller)?,
|
||||
Event::FileDrop(filename) => {
|
||||
self.engine_object.event(EngineEvent::FileDrop(filename))?
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ContextObjectImpl<E>
|
||||
where
|
||||
E: EngineObject + Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn controller_added(&mut self, controller: Arc<RwLock<Controller>>) -> Result<()> {
|
||||
self.engine_object
|
||||
.event(EngineEvent::ControllerAdded(controller))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn controller_removed(&mut self, controller: Arc<RwLock<Controller>>) -> Result<()> {
|
||||
self.engine_object
|
||||
.event(EngineEvent::ControllerRemoved(controller))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn key_up_event(&mut self, keycode: Keycode) -> Result<()> {
|
||||
let input = self.input.read().unwrap();
|
||||
|
||||
if input.direction_mapping.get(&keycode).is_some()
|
||||
&& self.gui_handler.update_selection(GuiDirection::None)?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match keycode {
|
||||
Keycode::RCtrl | Keycode::LCtrl => {
|
||||
self.ctrl_pressed = false;
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.engine_object.event(EngineEvent::KeyUp(keycode))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn key_down_event(&mut self, keycode: Keycode) -> Result<()> {
|
||||
let input = self.input.read().unwrap();
|
||||
|
||||
if let Some(direction) = input.direction_mapping.get(&keycode) {
|
||||
if self.gui_handler.update_selection(*direction)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
match keycode {
|
||||
Keycode::Backspace => {
|
||||
if self.gui_handler.remove_char()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::Return => {
|
||||
if self.gui_handler.accept_selection()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::Escape => {
|
||||
if self.gui_handler.decline_topgui()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Keycode::RCtrl | Keycode::LCtrl => {
|
||||
self.ctrl_pressed = true;
|
||||
}
|
||||
Keycode::V => {
|
||||
if let Some(writeable) = self.gui_handler.writeable()? {
|
||||
if let Some(content) = self.context.window_config().clipboard_content()? {
|
||||
writeable.set_text(content)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.engine_object.event(EngineEvent::KeyDown(keycode))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn button_up_event(&mut self, button: ControllerButton) -> Result<()> {
|
||||
self.engine_object.event(EngineEvent::ButtonUp(button))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn button_down_event(&mut self, button: ControllerButton) -> Result<()> {
|
||||
if self.gui_handler.check_navigatable()? {
|
||||
self.check_button_down(button)?;
|
||||
} else {
|
||||
self.engine_object.event(EngineEvent::ButtonDown(button))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn axis_event(&mut self, controller: &Controller) -> Result<()> {
|
||||
self.engine_object
|
||||
.event(EngineEvent::ControllerAxis(controller.controller_axis()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_button_down(&mut self, button: ControllerButton) -> Result<()> {
|
||||
match button {
|
||||
ControllerButton::A => {
|
||||
if self.gui_handler.accept_selection()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::B => {
|
||||
if self.gui_handler.decline_topgui()? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::RightButton => {
|
||||
if self.gui_handler.next_tab_topgui(false)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::LeftButton => {
|
||||
if self.gui_handler.previous_tab_topgui(false)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::RightTrigger => {
|
||||
if self.gui_handler.next_tab_topgui(true)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::LeftTrigger => {
|
||||
if self.gui_handler.previous_tab_topgui(true)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadDown => {
|
||||
let selection_res = self.gui_handler.update_selection(GuiDirection::Down)?;
|
||||
self.gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadUp => {
|
||||
let selection_res = self.gui_handler.update_selection(GuiDirection::Up)?;
|
||||
self.gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadRight => {
|
||||
let selection_res = self.gui_handler.update_selection(GuiDirection::Right)?;
|
||||
self.gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ControllerButton::DPadLeft => {
|
||||
let selection_res = self.gui_handler.update_selection(GuiDirection::Left)?;
|
||||
self.gui_handler.update_selection(GuiDirection::None)?;
|
||||
|
||||
if selection_res {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if !self.gui_handler.accept_custom_selection(button)? {
|
||||
self.engine_object.event(EngineEvent::ButtonDown(button))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn text_input(&self, text: String) -> Result<()> {
|
||||
if let Some(writeable) = self.gui_handler.writeable()? {
|
||||
for c in text.chars() {
|
||||
writeable.add_letter(c)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
pub mod engine;
|
||||
pub mod engine_settings;
|
||||
|
||||
pub mod engine_object;
|
||||
pub mod engine_event_handling;
|
||||
|
||||
pub mod asset_handler;
|
||||
pub mod engine_create_info;
|
||||
|
|
|
@ -10,7 +10,7 @@ pub use crate::engine::{
|
|||
asset_handler::{AssetHandler, AssetLoader},
|
||||
engine::*,
|
||||
engine_create_info::EngineCreateInfo,
|
||||
engine_object::{EngineEvent, EngineObject},
|
||||
engine_event_handling::{EngineEvent, EventConsumer},
|
||||
engine_settings::*,
|
||||
};
|
||||
|
||||
|
|
36
engine/src/scene/general/free_camera_control.rs
Normal file
36
engine/src/scene/general/free_camera_control.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::prelude::*;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct FreeCameraControl {}
|
||||
|
||||
impl Default for FreeCameraControl {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FreeCameraControl {
|
||||
pub fn roll(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pitch(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn yaw(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn forward_back(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn left_right(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn up_down(&mut self, view: &View) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -6,8 +6,9 @@ pub mod validcommandbuffer;
|
|||
|
||||
pub mod view;
|
||||
|
||||
pub mod camera_control;
|
||||
pub mod top_down_camera_control;
|
||||
|
||||
pub mod view_frustum;
|
||||
|
||||
pub mod free_camera_control;
|
||||
pub mod prelude;
|
||||
|
|
|
@ -6,6 +6,6 @@ pub use super::validcommandbuffer::*;
|
|||
|
||||
pub use super::view::*;
|
||||
|
||||
pub use super::camera_control::*;
|
||||
pub use super::top_down_camera_control::*;
|
||||
|
||||
pub use super::view_frustum::*;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::prelude::*;
|
||||
use anyhow::Result;
|
||||
use cgmath::{num_traits::clamp, vec3, Deg, Matrix4, Vector2, Vector3};
|
||||
use cgmath::{Deg, Matrix4, Vector2, Vector3, num_traits::clamp, vec3};
|
||||
|
||||
pub struct CameraControl {
|
||||
pub struct TopDownCameraControl {
|
||||
zoom_levels: Vec<f32>,
|
||||
current_zoom_level: usize,
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub struct CameraControl {
|
|||
mouse_position_start: Option<(u32, u32)>,
|
||||
}
|
||||
|
||||
impl CameraControl {
|
||||
impl TopDownCameraControl {
|
||||
const SCALE: f32 = 0.3;
|
||||
const MIN_PITCH: f32 = 10.0;
|
||||
const MAX_PITCH: f32 = 80.0;
|
||||
|
@ -91,8 +91,8 @@ impl CameraControl {
|
|||
self.rotation = Deg((self.rotation.0 + (self.stick_direction.x * factors.x)) % 360.0);
|
||||
self.arc = Deg(clamp(
|
||||
self.arc.0 - (self.stick_direction.y * factors.y),
|
||||
CameraControl::MIN_PITCH,
|
||||
CameraControl::MAX_PITCH,
|
||||
TopDownCameraControl::MIN_PITCH,
|
||||
TopDownCameraControl::MAX_PITCH,
|
||||
));
|
||||
|
||||
self.set_camera_offset(view)
|
||||
|
@ -102,14 +102,14 @@ impl CameraControl {
|
|||
self.mouse_position = (x, y);
|
||||
|
||||
if let Some((start_x, start_y)) = self.mouse_position_start {
|
||||
let x_diff = (start_x as i32 - x as i32) as f32 * CameraControl::SCALE;
|
||||
let y_diff = (start_y as i32 - y as i32) as f32 * CameraControl::SCALE;
|
||||
let x_diff = (start_x as i32 - x as i32) as f32 * TopDownCameraControl::SCALE;
|
||||
let y_diff = (start_y as i32 - y as i32) as f32 * TopDownCameraControl::SCALE;
|
||||
|
||||
self.rotation = Deg((self.rotation_start.0 + x_diff) % 360.0);
|
||||
self.arc = Deg(clamp(
|
||||
self.arc_start.0 - y_diff,
|
||||
CameraControl::MIN_PITCH,
|
||||
CameraControl::MAX_PITCH,
|
||||
TopDownCameraControl::MIN_PITCH,
|
||||
TopDownCameraControl::MAX_PITCH,
|
||||
));
|
||||
|
||||
self.set_camera_offset(view)?;
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
plexus = "0.0.11"
|
||||
anyhow.workspace = true
|
||||
|
||||
ecs = { path = "../../ecs" }
|
||||
|
|
|
@ -6,7 +6,55 @@ use engine::prelude::*;
|
|||
fn main() -> Result<()> {
|
||||
let mut world_builder = World::builder();
|
||||
|
||||
Engine::new(EngineCreateInfo::default(), &mut world_builder)?;
|
||||
Engine::new::<GameState>(EngineCreateInfo::default(), &mut world_builder)?;
|
||||
|
||||
world_builder.add_system(GameState::update);
|
||||
world_builder.resources.insert(GameState::Startup);
|
||||
|
||||
world_builder.build().run()
|
||||
}
|
||||
|
||||
enum GameState {
|
||||
Startup,
|
||||
Loading,
|
||||
Menu,
|
||||
Game(Game),
|
||||
}
|
||||
|
||||
impl GameState {
|
||||
fn update(world: &mut World) -> Result<bool> {
|
||||
match world.resources.get_mut_unchecked::<Self>() {
|
||||
GameState::Startup => (),
|
||||
GameState::Loading => (),
|
||||
GameState::Menu => (),
|
||||
GameState::Game(game) => game.update(world)?,
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventConsumer for GameState {
|
||||
fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> {
|
||||
match self {
|
||||
GameState::Startup => (),
|
||||
GameState::Loading => (),
|
||||
GameState::Menu => (),
|
||||
GameState::Game(game) => game.event(world, event)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct Game {}
|
||||
|
||||
impl Game {
|
||||
fn update(&mut self, world: &mut World) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,9 +178,9 @@ impl EventSystem {
|
|||
.map_err(|s| anyhow::Error::msg(s))?)
|
||||
}
|
||||
|
||||
pub fn poll_events<F, R>(&mut self, event_callback: F, mut resize: R) -> Result<bool>
|
||||
pub fn poll_events<F, R>(&mut self, mut event_callback: F, mut resize: R) -> Result<bool>
|
||||
where
|
||||
F: Fn(Event) -> Result<()>,
|
||||
F: FnMut(Event) -> Result<()>,
|
||||
R: FnMut(u32, u32) -> Result<()>,
|
||||
{
|
||||
let mut controller_axis_changed = false;
|
||||
|
|
|
@ -113,7 +113,7 @@ impl PresentationCore {
|
|||
|
||||
pub fn poll_events<F, R>(&mut self, event_callback: F, resize_event: R) -> Result<bool>
|
||||
where
|
||||
F: Fn(Event) -> Result<()>,
|
||||
F: FnMut(Event) -> Result<()>,
|
||||
R: FnMut(u32, u32) -> Result<()>,
|
||||
{
|
||||
self.event_system.poll_events(event_callback, resize_event)
|
||||
|
|
11
skybox/Cargo.toml
Normal file
11
skybox/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "skybox"
|
||||
version = "0.1.0"
|
||||
authors = ["hodasemi <michaelh.95@t-online.de>"]
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
|
||||
ecs = { path = "../ecs" }
|
||||
context = { path = "../context" }
|
54
skybox/src/lib.rs
Normal file
54
skybox/src/lib.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use context::prelude::*;
|
||||
use ecs::*;
|
||||
|
||||
pub struct SkyBoxImages {
|
||||
left: PathBuf,
|
||||
right: PathBuf,
|
||||
front: PathBuf,
|
||||
back: PathBuf,
|
||||
top: PathBuf,
|
||||
bottom: PathBuf,
|
||||
}
|
||||
|
||||
impl<T: ExactSizeIterator<Item = PathBuf>> From<T> for SkyBoxImages {
|
||||
fn from(mut paths: T) -> Self {
|
||||
debug_assert_eq!(paths.len(), 6);
|
||||
|
||||
Self {
|
||||
left: paths.next().unwrap(),
|
||||
right: paths.next().unwrap(),
|
||||
front: paths.next().unwrap(),
|
||||
back: paths.next().unwrap(),
|
||||
top: paths.next().unwrap(),
|
||||
bottom: paths.next().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SkyBox {
|
||||
cube_map: Arc<Image>,
|
||||
}
|
||||
|
||||
impl SkyBox {
|
||||
pub fn new(world: &mut WorldBuilder, images: impl Into<SkyBoxImages>) -> Result<Self> {
|
||||
let images = images.into();
|
||||
let context = world.resources.get::<Context>();
|
||||
|
||||
let cube_map = Image::cube_map([
|
||||
images.left.try_into()?,
|
||||
images.right.try_into()?,
|
||||
images.front.try_into()?,
|
||||
images.back.try_into()?,
|
||||
images.top.try_into()?,
|
||||
images.bottom.try_into()?,
|
||||
])?
|
||||
.max_mip_map_levels()
|
||||
.attach_pretty_sampler(context.device())?
|
||||
.build(context.device(), context.queue())?;
|
||||
|
||||
Ok(Self { cube_map })
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue