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",
|
"promise",
|
||||||
"ring_buffer",
|
"ring_buffer",
|
||||||
"scene_update_macros",
|
"scene_update_macros",
|
||||||
|
"skybox",
|
||||||
"transaction_derive",
|
"transaction_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@ impl ImageFormatChecker {
|
||||||
self.image_data.height,
|
self.image_data.height,
|
||||||
)
|
)
|
||||||
.format(initial_format)
|
.format(initial_format)
|
||||||
.attach_sampler(Sampler::pretty_sampler().build(device)?);
|
.max_mip_map_levels()
|
||||||
|
.attach_pretty_sampler(device)?;
|
||||||
|
|
||||||
let mut format = initial_format;
|
let mut format = initial_format;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ impl ImageFormatChecker {
|
||||||
return Err(anyhow::Error::msg(format!(
|
return Err(anyhow::Error::msg(format!(
|
||||||
"Image format {:?} for asset does not work",
|
"Image format {:?} for asset does not work",
|
||||||
format
|
format
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,6 @@ use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
use std::time::{Duration, Instant};
|
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 {
|
pub struct Context {
|
||||||
core: VulkanCore,
|
core: VulkanCore,
|
||||||
pub(crate) presentation: PresentationCore,
|
pub(crate) presentation: PresentationCore,
|
||||||
|
@ -65,18 +57,17 @@ impl Context {
|
||||||
&mut self.sound_handler
|
&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 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(
|
match self.presentation.poll_events(
|
||||||
|event| {
|
|event| f(w, consumer, event),
|
||||||
// TODO
|
|
||||||
// if let Some(ctx_obj) = world.resources.get_mut_opt::<C>() {
|
|
||||||
// ctx_obj.event(event)?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
|w, h| render_core.write().unwrap().resize(world, w, h),
|
|w, h| render_core.write().unwrap().resize(world, w, h),
|
||||||
) {
|
) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
|
|
|
@ -2,5 +2,3 @@
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
pub use crate::core::context::ContextObject;
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
use super::engine_object::*;
|
use super::engine_event_handling::*;
|
||||||
use super::engine_settings::EngineSettings;
|
use super::engine_settings::EngineSettings;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -11,7 +11,7 @@ use crate::assets::asset_manager::AssetManager;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::Arc;
|
||||||
|
|
||||||
struct GuiPostProcess(Arc<GuiHandler>);
|
struct GuiPostProcess(Arc<GuiHandler>);
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@ impl context::prelude::PostProcess for GuiPostProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
input: Arc<RwLock<Input>>,
|
|
||||||
|
|
||||||
// loads and keeps track of raw data
|
// loads and keeps track of raw data
|
||||||
asset_manager: AssetManager,
|
asset_manager: AssetManager,
|
||||||
|
|
||||||
|
@ -43,7 +41,7 @@ pub struct Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn new(
|
pub fn new<T: EventConsumer>(
|
||||||
#[allow(unused)] mut create_info: EngineCreateInfo<'_>,
|
#[allow(unused)] mut create_info: EngineCreateInfo<'_>,
|
||||||
world: &mut WorldBuilder,
|
world: &mut WorldBuilder,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -188,13 +186,12 @@ impl Engine {
|
||||||
direction_mapping.insert(Keycode::Down, GuiDirection::Down);
|
direction_mapping.insert(Keycode::Down, GuiDirection::Down);
|
||||||
|
|
||||||
let engine = Engine {
|
let engine = Engine {
|
||||||
input: Arc::new(RwLock::new(Input { direction_mapping })),
|
|
||||||
|
|
||||||
asset_manager,
|
asset_manager,
|
||||||
|
|
||||||
resource_base_path: create_info.resource_base_path,
|
resource_base_path: create_info.resource_base_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
world.resources.insert(InputMap { direction_mapping });
|
||||||
world.resources.insert(context);
|
world.resources.insert(context);
|
||||||
world.resources.insert(engine);
|
world.resources.insert(engine);
|
||||||
world.resources.insert(engine_settings);
|
world.resources.insert(engine_settings);
|
||||||
|
@ -208,7 +205,7 @@ impl Engine {
|
||||||
|
|
||||||
world.resources.insert(scene);
|
world.resources.insert(scene);
|
||||||
|
|
||||||
world.add_system(Self::main_system);
|
world.add_system(Self::main_system::<T>);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -251,10 +248,25 @@ impl Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
fn main_system(world: &mut World) -> Result<bool> {
|
fn main_system<T: EventConsumer>(world: &mut World) -> Result<bool> {
|
||||||
world
|
world
|
||||||
.resources
|
.resources
|
||||||
.get_mut_unchecked::<Context>()
|
.get::<Arc<GuiHandler>>()
|
||||||
.next_frame::<()>(world)
|
.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;
|
||||||
pub mod engine_settings;
|
pub mod engine_settings;
|
||||||
|
|
||||||
pub mod engine_object;
|
pub mod engine_event_handling;
|
||||||
|
|
||||||
pub mod asset_handler;
|
pub mod asset_handler;
|
||||||
pub mod engine_create_info;
|
pub mod engine_create_info;
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub use crate::engine::{
|
||||||
asset_handler::{AssetHandler, AssetLoader},
|
asset_handler::{AssetHandler, AssetLoader},
|
||||||
engine::*,
|
engine::*,
|
||||||
engine_create_info::EngineCreateInfo,
|
engine_create_info::EngineCreateInfo,
|
||||||
engine_object::{EngineEvent, EngineObject},
|
engine_event_handling::{EngineEvent, EventConsumer},
|
||||||
engine_settings::*,
|
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 view;
|
||||||
|
|
||||||
pub mod camera_control;
|
pub mod top_down_camera_control;
|
||||||
|
|
||||||
pub mod view_frustum;
|
pub mod view_frustum;
|
||||||
|
|
||||||
|
pub mod free_camera_control;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
|
@ -6,6 +6,6 @@ pub use super::validcommandbuffer::*;
|
||||||
|
|
||||||
pub use super::view::*;
|
pub use super::view::*;
|
||||||
|
|
||||||
pub use super::camera_control::*;
|
pub use super::top_down_camera_control::*;
|
||||||
|
|
||||||
pub use super::view_frustum::*;
|
pub use super::view_frustum::*;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
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>,
|
zoom_levels: Vec<f32>,
|
||||||
current_zoom_level: usize,
|
current_zoom_level: usize,
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub struct CameraControl {
|
||||||
mouse_position_start: Option<(u32, u32)>,
|
mouse_position_start: Option<(u32, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraControl {
|
impl TopDownCameraControl {
|
||||||
const SCALE: f32 = 0.3;
|
const SCALE: f32 = 0.3;
|
||||||
const MIN_PITCH: f32 = 10.0;
|
const MIN_PITCH: f32 = 10.0;
|
||||||
const MAX_PITCH: f32 = 80.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.rotation = Deg((self.rotation.0 + (self.stick_direction.x * factors.x)) % 360.0);
|
||||||
self.arc = Deg(clamp(
|
self.arc = Deg(clamp(
|
||||||
self.arc.0 - (self.stick_direction.y * factors.y),
|
self.arc.0 - (self.stick_direction.y * factors.y),
|
||||||
CameraControl::MIN_PITCH,
|
TopDownCameraControl::MIN_PITCH,
|
||||||
CameraControl::MAX_PITCH,
|
TopDownCameraControl::MAX_PITCH,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.set_camera_offset(view)
|
self.set_camera_offset(view)
|
||||||
|
@ -102,14 +102,14 @@ impl CameraControl {
|
||||||
self.mouse_position = (x, y);
|
self.mouse_position = (x, y);
|
||||||
|
|
||||||
if let Some((start_x, start_y)) = self.mouse_position_start {
|
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 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 * CameraControl::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.rotation = Deg((self.rotation_start.0 + x_diff) % 360.0);
|
||||||
self.arc = Deg(clamp(
|
self.arc = Deg(clamp(
|
||||||
self.arc_start.0 - y_diff,
|
self.arc_start.0 - y_diff,
|
||||||
CameraControl::MIN_PITCH,
|
TopDownCameraControl::MIN_PITCH,
|
||||||
CameraControl::MAX_PITCH,
|
TopDownCameraControl::MAX_PITCH,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.set_camera_offset(view)?;
|
self.set_camera_offset(view)?;
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
plexus = "0.0.11"
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
|
||||||
ecs = { path = "../../ecs" }
|
ecs = { path = "../../ecs" }
|
||||||
|
|
|
@ -6,7 +6,55 @@ use engine::prelude::*;
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut world_builder = World::builder();
|
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()
|
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))?)
|
.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
|
where
|
||||||
F: Fn(Event) -> Result<()>,
|
F: FnMut(Event) -> Result<()>,
|
||||||
R: FnMut(u32, u32) -> Result<()>,
|
R: FnMut(u32, u32) -> Result<()>,
|
||||||
{
|
{
|
||||||
let mut controller_axis_changed = false;
|
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>
|
pub fn poll_events<F, R>(&mut self, event_callback: F, resize_event: R) -> Result<bool>
|
||||||
where
|
where
|
||||||
F: Fn(Event) -> Result<()>,
|
F: FnMut(Event) -> Result<()>,
|
||||||
R: FnMut(u32, u32) -> Result<()>,
|
R: FnMut(u32, u32) -> Result<()>,
|
||||||
{
|
{
|
||||||
self.event_system.poll_events(event_callback, resize_event)
|
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