Skip to content

Commit

Permalink
add primitive apis
Browse files Browse the repository at this point in the history
  • Loading branch information
kayhhh committed Jun 5, 2024
1 parent a55f24d commit edae30e
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 345 deletions.
4 changes: 4 additions & 0 deletions crates/unavi-scripting/src/host/wired_gltf/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub fn handle_wired_gltf_actions(
});
}
}
WiredGltfAction::CreatePrimitive { id, mesh } => {}
WiredGltfAction::RemoveMesh { id } => {
if let Some(ent) = find_mesh(&meshes, id) {
commands.entity(ent).despawn_recursive();
Expand All @@ -68,6 +69,7 @@ pub fn handle_wired_gltf_actions(
warn!("Node {} does not exist", id);
}
}
WiredGltfAction::RemovePrimitive { id, mesh } => {}
WiredGltfAction::SetNodeParent { id, parent } => {
if let Some(ent) = find_node(&nodes, id) {
if let Some(parent) = parent {
Expand Down Expand Up @@ -301,4 +303,6 @@ mod tests {
send.send(WiredGltfAction::RemoveMesh { id: 0 }).unwrap();
app.update();
}

// Primitive
}
244 changes: 225 additions & 19 deletions crates/unavi-scripting/src/host/wired_gltf/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,13 @@ use wasm_component_layer::{

use crate::{load::EngineBackend, resource_table::ResourceTable, StoreData};

use super::{LocalData, MeshData, WiredGltfAction};
use super::{LocalData, MeshData, PrimitiveData, WiredGltfAction};

#[derive(Clone)]
pub struct MeshResource {
id: u32,
}
pub struct MeshResource(u32);

impl MeshResource {
fn new(id: u32) -> Self {
Self { id }
}
}
#[derive(Clone)]
pub struct PrimitiveResource(u32);

pub fn add_to_host(
store: &mut Store<StoreData, EngineBackend>,
Expand All @@ -33,21 +28,190 @@ pub fn add_to_host(

let mesh_type = ResourceType::new::<MeshResource>(None);
let mesh_list_type = ListType::new(ValueType::Own(mesh_type.clone()));
let primitive_type = ResourceType::new::<PrimitiveResource>(None);
let primitive_list_type = ListType::new(ValueType::Own(primitive_type.clone()));

let primitive_id_fn = Func::new(
store.as_context_mut(),
FuncType::new(
[ValueType::Borrow(primitive_type.clone())],
[ValueType::U32],
),
move |ctx, args, results| {
let resource = match &args[0] {
Value::Borrow(v) => v,
_ => bail!("invalid arg"),
};

let ctx_ref = ctx.as_context();
let primitive: &PrimitiveResource = resource.rep(&ctx_ref)?;

results[0] = Value::U32(primitive.0);

Ok(())
},
);

let mesh_id_fn = Func::new(
store.as_context_mut(),
FuncType::new([ValueType::Borrow(mesh_type.clone())], [ValueType::U32]),
move |ctx, args, results| {
let resource = match &args[0] {
Value::Borrow(v) => v,
_ => bail!("invalid arg"),
};

let ctx_ref = ctx.as_context();
let mesh: &MeshResource = resource.rep(&ctx_ref)?;

results[0] = Value::U32(mesh.0);

Ok(())
},
);

let mesh_list_primitives_fn = {
let local_data = local_data.clone();
let primitive_type = primitive_type.clone();
let resource_table = resource_table.clone();
Func::new(
store.as_context_mut(),
FuncType::new(
[ValueType::Borrow(mesh_type.clone())],
[ValueType::List(primitive_list_type.clone())],
),
move |mut ctx, args, results| {
let resource = match &args[0] {
Value::Borrow(v) => v,
_ => bail!("invalid arg"),
};

let ctx_ref = ctx.as_context();
let mesh: &MeshResource = resource.rep(&ctx_ref)?;
let mesh_id = mesh.0;

let mut local_data = local_data.write().unwrap();
let mut resource_table = resource_table.write().unwrap();

if let Some(data) = local_data.meshes.get(&mesh_id) {
let primitives = data
.primitives
.keys()
.copied()
.collect::<Vec<_>>()
.into_iter()
.map(|id| {
create_primitive_resource(
id,
mesh_id,
&primitive_type,
&mut ctx,
&mut local_data,
&mut resource_table,
)
})
.collect::<Result<Vec<_>>>()?;

results[0] = Value::List(List::new(primitive_list_type.clone(), primitives)?);
}

Ok(())
},
)
};

let mesh_id_fn = {
let mesh_create_primitive_fn = {
let local_data = local_data.clone();
let primitive_type = primitive_type.clone();
let resource_table = resource_table.clone();
let sender = sender.clone();
Func::new(
store.as_context_mut(),
FuncType::new([ValueType::Borrow(mesh_type.clone())], [ValueType::U32]),
move |ctx, args, results| {
FuncType::new(
[ValueType::Borrow(mesh_type.clone())],
[ValueType::Own(primitive_type.clone())],
),
move |mut ctx, args, results| {
let resource = match &args[0] {
Value::Borrow(v) => v,
_ => bail!("invalid arg"),
};

let ctx_ref = ctx.as_context();
let mesh: &MeshResource = resource.rep(&ctx_ref)?;
let mesh_id = mesh.0;

let mut local_data = local_data.write().unwrap();
let mut resource_table = resource_table.write().unwrap();

let id = local_data.new_id();

if let Some(data) = local_data.meshes.get_mut(&mesh_id) {
data.primitives.insert(id, PrimitiveData::default());

sender.send(WiredGltfAction::CreatePrimitive { id, mesh: mesh_id })?;

let value = create_primitive_resource(
id,
mesh_id,
&primitive_type,
&mut ctx,
&mut local_data,
&mut resource_table,
)?;

results[0] = value;
}

Ok(())
},
)
};

let mesh_remove_primitive_fn = {
let local_data = local_data.clone();
let primitive_type = primitive_type.clone();
let resource_table = resource_table.clone();
let sender = sender.clone();
Func::new(
store.as_context_mut(),
FuncType::new(
[
ValueType::Borrow(mesh_type.clone()),
ValueType::Own(primitive_type.clone()),
],
[],
),
move |ctx, args, _results| {
let mesh_res = match &args[0] {
Value::Borrow(v) => v,
_ => bail!("invalid arg"),
};

results[0] = Value::U32(mesh.id);
let primitive_res = match &args[1] {
Value::Own(v) => v,
_ => bail!("invalid arg"),
};

let ctx_ref = ctx.as_context();
let mesh: &MeshResource = mesh_res.rep(&ctx_ref)?;
let primitive: &PrimitiveResource = primitive_res.rep(&ctx_ref)?;

sender.send(WiredGltfAction::RemovePrimitive {
id: primitive.0,
mesh: mesh.0,
})?;

let mut local_data = local_data.write().unwrap();
let mut resource_table = resource_table.write().unwrap();

if let Some(data) = local_data.meshes.get_mut(&mesh.0) {
if let Some(primitive_data) = data.primitives.remove(&primitive.0) {
for id in primitive_data.resources {
resource_table.remove(&id);
}
}
}

Ok(())
},
Expand Down Expand Up @@ -141,23 +305,35 @@ pub fn add_to_host(
let mut local_data = local_data.write().unwrap();
let mut resource_table = resource_table.write().unwrap();

sender.send(WiredGltfAction::RemoveMesh { id: mesh.id })?;
sender.send(WiredGltfAction::RemoveMesh { id: mesh.0 })?;

if let Some(data) = local_data.meshes.remove(&mesh.id) {
if let Some(data) = local_data.meshes.remove(&mesh.0) {
for id in data.resources {
resource_table.remove(&id);
}
};

// TODO: Remove material (?)
for p_data in data.primitives.values() {
// TODO: move into a function with mesh_remove_primitive_fn logic

for id in &p_data.resources {
resource_table.remove(id);
}
}
};

Ok(())
},
)
};

interface.define_resource("primitive", primitive_type)?;
interface.define_func("[method]primitive.id", primitive_id_fn)?;

interface.define_resource("mesh", mesh_type)?;
interface.define_func("[method]mesh.id", mesh_id_fn)?;
interface.define_func("[method]mesh.list-primitives", mesh_list_primitives_fn)?;
interface.define_func("[method]mesh.create-primitive", mesh_create_primitive_fn)?;
interface.define_func("[method]mesh.remove-primitive", mesh_remove_primitive_fn)?;

interface.define_func("list-meshes", list_meshes_fn)?;
interface.define_func("create-mesh", create_mesh_fn)?;
Expand All @@ -166,7 +342,6 @@ pub fn add_to_host(
Ok(())
}

/// Creates a new mesh resource for the given mesh ID.
fn create_mesh_resource(
id: u32,
mesh_type: &ResourceType,
Expand All @@ -176,7 +351,7 @@ fn create_mesh_resource(
) -> anyhow::Result<Value> {
let (res_id, resource) =
resource_table.push(ctx.as_context_mut(), mesh_type.clone(), |_| {
MeshResource::new(id)
MeshResource(id)
})?;

let data = local_data
Expand All @@ -188,3 +363,34 @@ fn create_mesh_resource(

Ok(Value::Own(resource))
}

fn create_primitive_resource(
id: u32,
mesh_id: u32,
primitive_type: &ResourceType,
ctx: &mut StoreContextMut<StoreData, EngineBackend>,
local_data: &mut RwLockWriteGuard<LocalData>,
resource_table: &mut RwLockWriteGuard<ResourceTable>,
) -> anyhow::Result<Value> {
let (res_id, resource) =
resource_table.push(ctx.as_context_mut(), primitive_type.clone(), |_| {
PrimitiveResource(id)
})?;

let mesh_data = local_data
.meshes
.get_mut(&mesh_id)
.ok_or(anyhow!("Mesh not found"))?;

let primitive_data = match mesh_data.primitives.get_mut(&id) {
Some(d) => d,
None => {
mesh_data.primitives.insert(id, PrimitiveData::default());
mesh_data.primitives.get_mut(&id).unwrap()
}
};

primitive_data.resources.insert(res_id);

Ok(Value::Own(resource))
}
16 changes: 15 additions & 1 deletion crates/unavi-scripting/src/host/wired_gltf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ pub struct WiredGltfReceiver(pub Receiver<WiredGltfAction>);
pub enum WiredGltfAction {
CreateMesh { id: u32 },
CreateNode { id: u32 },
CreatePrimitive { id: u32, mesh: u32 },
RemoveMesh { id: u32 },
RemoveNode { id: u32 },
RemovePrimitive { id: u32, mesh: u32 },
SetNodeParent { id: u32, parent: Option<u32> },
SetNodeTransform { id: u32, transform: Transform },
}
Expand Down Expand Up @@ -60,6 +62,12 @@ struct NodeData {

#[derive(Default)]
struct MeshData {
primitives: HashMap<u32, PrimitiveData>,
resources: HashSet<u32>,
}

#[derive(Default)]
struct PrimitiveData {
resources: HashSet<u32>,
}

Expand All @@ -72,8 +80,14 @@ pub fn add_to_host(

let local_data = Arc::new(RwLock::new(LocalData::default()));

node::add_to_host(
store,
linker,
send.clone(),
local_data.clone(),
data.clone(),
)?;
mesh::add_to_host(store, linker, send.clone(), local_data.clone())?;
node::add_to_host(store, linker, send, local_data, data.clone())?;

Ok((WiredGltfReceiver(recv), WiredGltfData(data)))
}
Expand Down
1 change: 0 additions & 1 deletion crates/unavi-scripting/src/host/wired_gltf/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ pub fn add_to_host(
Ok(())
}

/// Creates a new node resource for the given node ID.
fn create_node_resource(
id: u32,
node_type: &ResourceType,
Expand Down
Loading

0 comments on commit edae30e

Please sign in to comment.