beginning of action system
This commit is contained in:
@@ -7,7 +7,7 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_xr::camera::{XrCameraBundle, XrProjection, XrView};
|
use bevy_xr::camera::{XrCameraBundle, XrProjection, XrView};
|
||||||
use openxr::CompositionLayerFlags;
|
use openxr::{CompositionLayerFlags, ViewStateFlags};
|
||||||
|
|
||||||
use crate::resources::*;
|
use crate::resources::*;
|
||||||
use crate::{init::begin_xr_session, layer_builder::*};
|
use crate::{init::begin_xr_session, layer_builder::*};
|
||||||
@@ -51,6 +51,7 @@ pub fn init_views(
|
|||||||
swapchain_images: Res<XrSwapchainImages>,
|
swapchain_images: Res<XrSwapchainImages>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
|
let _span = info_span!("xr_init_views");
|
||||||
let temp_tex = swapchain_images.first().unwrap();
|
let temp_tex = swapchain_images.first().unwrap();
|
||||||
// this for loop is to easily add support for quad or mono views in the future.
|
// this for loop is to easily add support for quad or mono views in the future.
|
||||||
let mut views = vec![];
|
let mut views = vec![];
|
||||||
@@ -74,6 +75,7 @@ pub fn init_views(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_frame(mut frame_waiter: ResMut<XrFrameWaiter>, mut commands: Commands) {
|
pub fn wait_frame(mut frame_waiter: ResMut<XrFrameWaiter>, mut commands: Commands) {
|
||||||
|
let _span = info_span!("xr_wait_frame");
|
||||||
let state = frame_waiter.wait().expect("Failed to wait frame");
|
let state = frame_waiter.wait().expect("Failed to wait frame");
|
||||||
// Here we insert the predicted display time for when this frame will be displayed.
|
// Here we insert the predicted display time for when this frame will be displayed.
|
||||||
// TODO: don't add predicted_display_period if pipelined rendering plugin not enabled
|
// TODO: don't add predicted_display_period if pipelined rendering plugin not enabled
|
||||||
@@ -89,6 +91,7 @@ pub fn update_views(
|
|||||||
stage: Res<XrStage>,
|
stage: Res<XrStage>,
|
||||||
time: Res<XrTime>,
|
time: Res<XrTime>,
|
||||||
) {
|
) {
|
||||||
|
let _span = info_span!("xr_wait_frame");
|
||||||
let (_flags, xr_views) = session
|
let (_flags, xr_views) = session
|
||||||
.locate_views(
|
.locate_views(
|
||||||
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
||||||
@@ -222,6 +225,7 @@ pub fn insert_texture_views(
|
|||||||
mut manual_texture_views: ResMut<ManualTextureViews>,
|
mut manual_texture_views: ResMut<ManualTextureViews>,
|
||||||
graphics_info: Res<XrGraphicsInfo>,
|
graphics_info: Res<XrGraphicsInfo>,
|
||||||
) {
|
) {
|
||||||
|
let _span = info_span!("xr_insert_texture_views");
|
||||||
let index = swapchain.acquire_image().expect("Failed to acquire image");
|
let index = swapchain.acquire_image().expect("Failed to acquire image");
|
||||||
swapchain
|
swapchain
|
||||||
.wait_image(openxr::Duration::INFINITE)
|
.wait_image(openxr::Duration::INFINITE)
|
||||||
@@ -262,16 +266,37 @@ pub fn end_frame(
|
|||||||
stage: Res<XrStage>,
|
stage: Res<XrStage>,
|
||||||
display_time: Res<XrTime>,
|
display_time: Res<XrTime>,
|
||||||
graphics_info: Res<XrGraphicsInfo>,
|
graphics_info: Res<XrGraphicsInfo>,
|
||||||
|
mut openxr_views: Local<Vec<openxr::View>>,
|
||||||
) {
|
) {
|
||||||
|
let _span = info_span!("xr_end_frame");
|
||||||
swapchain.release_image().unwrap();
|
swapchain.release_image().unwrap();
|
||||||
let (_flags, views) = session
|
let (flags, views) = session
|
||||||
.locate_views(
|
.locate_views(
|
||||||
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
||||||
**display_time,
|
**display_time,
|
||||||
&stage,
|
&stage,
|
||||||
)
|
)
|
||||||
.expect("Failed to locate views");
|
.expect("Failed to locate views");
|
||||||
|
if openxr_views.len() != views.len() {
|
||||||
|
openxr_views.resize(views.len(), default());
|
||||||
|
}
|
||||||
|
match (
|
||||||
|
flags & ViewStateFlags::ORIENTATION_VALID == ViewStateFlags::ORIENTATION_VALID,
|
||||||
|
flags & ViewStateFlags::POSITION_VALID == ViewStateFlags::POSITION_VALID,
|
||||||
|
) {
|
||||||
|
(true, true) => *openxr_views = views,
|
||||||
|
(true, false) => {
|
||||||
|
for (i, view) in openxr_views.iter_mut().enumerate() {
|
||||||
|
view.pose.orientation = views[i].pose.orientation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(false, true) => {
|
||||||
|
for (i, view) in openxr_views.iter_mut().enumerate() {
|
||||||
|
view.pose.position = views[i].pose.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(false, false) => {}
|
||||||
|
}
|
||||||
let rect = openxr::Rect2Di {
|
let rect = openxr::Rect2Di {
|
||||||
offset: openxr::Offset2Di { x: 0, y: 0 },
|
offset: openxr::Offset2Di { x: 0, y: 0 },
|
||||||
extent: openxr::Extent2Di {
|
extent: openxr::Extent2Di {
|
||||||
@@ -288,8 +313,8 @@ pub fn end_frame(
|
|||||||
.space(&stage)
|
.space(&stage)
|
||||||
.views(&[
|
.views(&[
|
||||||
CompositionLayerProjectionView::new()
|
CompositionLayerProjectionView::new()
|
||||||
.pose(views[0].pose)
|
.pose(openxr_views[0].pose)
|
||||||
.fov(views[0].fov)
|
.fov(openxr_views[0].fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(&swapchain)
|
||||||
@@ -297,8 +322,8 @@ pub fn end_frame(
|
|||||||
.image_rect(rect),
|
.image_rect(rect),
|
||||||
),
|
),
|
||||||
CompositionLayerProjectionView::new()
|
CompositionLayerProjectionView::new()
|
||||||
.pose(views[1].pose)
|
.pose(openxr_views[1].pose)
|
||||||
.fov(views[1].fov)
|
.fov(openxr_views[1].fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(&swapchain)
|
||||||
|
|||||||
@@ -277,5 +277,5 @@ pub struct XrGraphicsInfo {
|
|||||||
pub format: wgpu::TextureFormat,
|
pub format: wgpu::TextureFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Resource)]
|
#[derive(Clone, Resource, ExtractResource)]
|
||||||
pub struct XrViews(pub Vec<Entity>);
|
pub struct XrViews(pub Vec<Entity>);
|
||||||
|
|||||||
97
crates/bevy_xr/src/actions.rs
Normal file
97
crates/bevy_xr/src/actions.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
app::{App, First, Plugin},
|
||||||
|
ecs::system::{ResMut, Resource},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ActionPlugin<A: Action>(PhantomData<A>);
|
||||||
|
|
||||||
|
impl<A: Action> Default for ActionPlugin<A> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Action> Plugin for ActionPlugin<A> {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(First, reset_action_state::<A>)
|
||||||
|
.init_resource::<Actions>();
|
||||||
|
app.world.resource_mut::<Actions>().0.push(A::INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ActionType {
|
||||||
|
Bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ActionTy: Send + Sync + Default + Clone + Copy {
|
||||||
|
const TYPE: ActionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionTy for bool {
|
||||||
|
const TYPE: ActionType = ActionType::Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Action: Send + Sync + 'static {
|
||||||
|
type ActionType: ActionTy;
|
||||||
|
|
||||||
|
const INFO: ActionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ActionInfo {
|
||||||
|
pub pretty_name: &'static str,
|
||||||
|
pub name: &'static str,
|
||||||
|
pub action_type: ActionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct Actions(pub Vec<ActionInfo>);
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct ActionState<A: Action> {
|
||||||
|
previous_state: A::ActionType,
|
||||||
|
current_state: A::ActionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Action> ActionState<A> {
|
||||||
|
pub fn current_state(&self) -> A::ActionType {
|
||||||
|
self.current_state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn previous_state(&self) -> A::ActionType {
|
||||||
|
self.previous_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Action<ActionType = bool>> ActionState<A> {
|
||||||
|
pub fn pressed(&self) -> bool {
|
||||||
|
self.current_state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn just_pressed(&self) -> bool {
|
||||||
|
self.previous_state == false && self.current_state == true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn just_released(&self) -> bool {
|
||||||
|
self.previous_state == true && self.current_state == false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn press(&mut self) {
|
||||||
|
self.current_state = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_action_state<A: Action>(mut action_state: ResMut<ActionState<A>>) {
|
||||||
|
action_state.previous_state = std::mem::take(&mut action_state.current_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ActionApp {
|
||||||
|
fn register_action<A: Action>(&mut self) -> &mut Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionApp for App {
|
||||||
|
fn register_action<A: Action>(&mut self) -> &mut Self {
|
||||||
|
self.add_plugins(ActionPlugin::<A>::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
|
pub mod actions;
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
|
|||||||
Reference in New Issue
Block a user