Skip to content

Commit

Permalink
hook up script input events
Browse files Browse the repository at this point in the history
  • Loading branch information
kayhhh committed Jul 2, 2024
1 parent 14fab9c commit ba056c8
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 27 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 12 additions & 14 deletions crates/unavi-player/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use bevy::input::keyboard::KeyCode;
use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;
use unavi_constants::layers::{OTHER_PLAYER_LAYER, WORLD_LAYER};
use unavi_scripting::actions::handler::NodeId;
use unavi_scripting::{
actions::handler::InputHandler, api::wired_input::input_handler::ScriptInputEvent,
};

use crate::PlayerCamera;

Expand Down Expand Up @@ -53,28 +55,19 @@ const RAYCAST_DISTANCE: f32 = 10.0;
pub fn handle_raycast_input(
camera: Query<&GlobalTransform, With<PlayerCamera>>,
mouse: Res<ButtonInput<MouseButton>>,
mut draw_ray: Local<(Vec3, Vec3)>,
mut gizmos: Gizmos,
nodes: Query<(Entity, &NodeId)>,
nodes: Query<(Entity, &InputHandler)>,
query: SpatialQuery,
) {
if camera.is_empty() {
return;
}

gizmos.arrow(draw_ray.0, draw_ray.1, Color::BLUE);

if mouse.just_pressed(MouseButton::Left) {
let transform = camera.single();
let (_, rotation, translation) = transform.to_scale_rotation_translation();

let direction = rotation.normalize() * Direction3d::NEG_Z;

// TODO: Raycast from cursor location if not pointer-locked.

let end = translation + direction * RAYCAST_DISTANCE;
*draw_ray = (translation, end);

if let Some(hit) = query.cast_ray(
translation,
direction,
Expand All @@ -85,11 +78,16 @@ pub fn handle_raycast_input(
..default()
},
) {
for (ent, id) in nodes.iter() {
// TODO: Recursive check to see if children were hit.
for (ent, handler) in nodes.iter() {
// TODO: Recursive check if children were hit.

if hit.entity == ent {
info!("Hit node: {:?}", id);
if let Err(e) = handler.send(ScriptInputEvent::Raycast {
origin: translation,
orientation: rotation,
}) {
error!("Failed to send script input event: {}", e);
};
break;
}
}
Expand Down
11 changes: 7 additions & 4 deletions crates/unavi-scripting/src/actions/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ use bevy::{
utils::HashMap,
};
use bevy_xpbd_3d::prelude::*;
use crossbeam::channel::Sender;
use unavi_constants::layers::WORLD_LAYER;

use crate::api::wired_input::input_handler::ScriptInputEvent;

use super::{ActionReceiver, ScriptAction};

#[derive(Component)]
pub struct InputHandler;
#[derive(Component, Deref)]
pub struct InputHandler(pub Sender<ScriptInputEvent>);

#[derive(Component, Clone, Copy, Debug)]
pub struct NodeId(pub u32);
Expand Down Expand Up @@ -308,8 +311,8 @@ pub fn handle_actions(
let s = span.entered();

if let Some((ent, ..)) = find_node(nodes, id, world) {
if handler.is_some() {
world.entity_mut(ent).insert(InputHandler);
if let Some(sender) = handler {
world.entity_mut(ent).insert(InputHandler(sender));
} else {
world.entity_mut(ent).remove::<InputHandler>();
}
Expand Down
6 changes: 4 additions & 2 deletions crates/unavi-scripting/src/actions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;
use crossbeam::channel::Receiver;
use crossbeam::channel::{Receiver, Sender};

use crate::api::wired_input::input_handler::ScriptInputEvent;

pub mod handler;

Expand Down Expand Up @@ -45,7 +47,7 @@ pub enum ScriptAction {
},
SetNodeInputHandler {
id: u32,
handler: Option<()>,
handler: Option<Sender<ScriptInputEvent>>,
},
SetNodeMesh {
id: u32,
Expand Down
62 changes: 59 additions & 3 deletions crates/unavi-scripting/src/api/wired_input/input_handler.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
use std::cell::Cell;

use crossbeam::channel::{Receiver, Sender};
use wasm_bridge::component::Resource;

use crate::{
api::utils::{RefCount, RefResource},
state::StoreState,
};

use super::wired::input::{handler::HostInputHandler, types::InputEvent};
use super::wired::{
input::{
handler::HostInputHandler,
types::{InputEvent, InputType, Ray},
},
math::types::{Quat, Vec3},
};

pub enum ScriptInputEvent {
Raycast {
origin: bevy::math::Vec3,
orientation: bevy::math::Quat,
},
}

pub struct InputHandler {
pub sender: Sender<ScriptInputEvent>,
receiver: Receiver<ScriptInputEvent>,
ref_count: Cell<usize>,
}

Expand All @@ -23,8 +39,12 @@ impl RefResource for InputHandler {}

impl InputHandler {
pub fn new() -> Self {
let (sender, receiver) = crossbeam::channel::bounded(10);

Self {
receiver,
ref_count: Cell::new(1),
sender,
}
}
}
Expand All @@ -39,9 +59,45 @@ impl HostInputHandler for StoreState {

fn handle_input(
&mut self,
_self_: Resource<InputHandler>,
self_: Resource<InputHandler>,
) -> wasm_bridge::Result<Option<InputEvent>> {
Ok(None)
let data = self.table.get(&self_)?;

if let Ok(event) = data.receiver.try_recv() {
let e = match event {
ScriptInputEvent::Raycast {
origin,
orientation,
} => {
let origin = Vec3 {
x: origin.x,
y: origin.y,
z: origin.z,
};

let orientation = Quat {
x: orientation.x,
y: orientation.y,
z: orientation.z,
w: orientation.w,
};

InputEvent {
id: 0,
input: InputType::Ray(Ray {
origin,
orientation,
}),
order: 0,
distance: 0.0,
}
}
};

Ok(Some(e))
} else {
Ok(None)
}
}

fn drop(&mut self, rep: Resource<InputHandler>) -> wasm_bridge::Result<()> {
Expand Down
13 changes: 13 additions & 0 deletions crates/unavi-scripting/src/api/wired_scene/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,21 @@ impl HostNode for StoreState {
self_: Resource<Node>,
value: Option<Resource<InputHandler>>,
) -> wasm_bridge::Result<()> {
let handler = if let Some(value) = &value {
let data = self.table.get(value)?;
Some(data.sender.clone())
} else {
None
};

let node = self.table.get_mut(&self_)?;
node.input_handler = value;

self.sender.send(ScriptAction::SetNodeInputHandler {
id: self_.rep(),
handler,
})?;

Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion crates/unavi-scripting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy::prelude::*;
use self::{asset::Wasm, load::Scripts};

pub mod actions;
mod api;
pub mod api;
pub mod asset;
mod execution;
mod load;
Expand Down
1 change: 1 addition & 0 deletions wasm/example-wired-input/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license.workspace = true
crate-type = ["cdylib"]

[dependencies]
rand = "0.8.5"
wit-bindgen-rt.workspace = true

[package.metadata.component]
Expand Down
12 changes: 9 additions & 3 deletions wasm/example-wired-input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ use bindings::{
math::types::Vec3,
physics::types::{Collider, Shape},
scene::{
material::{create_material, Material},
material::{create_material, Color, Material},
node::create_node,
},
},
};
use rand::Rng;

#[allow(warnings)]
mod bindings;
Expand Down Expand Up @@ -49,8 +50,13 @@ impl GuestScript for Script {
while let Some(event) = self.handler.handle_input() {
log(LogLevel::Info, &format!("Got input: {:?}", event));

let mut color = self.material.color();
color.b += 0.1;
let mut rng = rand::thread_rng();
let r = rng.gen_range(0.0..1.0);
let g = rng.gen_range(0.0..1.0);
let b = rng.gen_range(0.0..1.0);
let a = rng.gen_range(0.2..1.0);

self.material.set_color(Color { r, g, b, a });
}
}
}
Expand Down

0 comments on commit ba056c8

Please sign in to comment.