Implement a "downcastable" wasm resource for ecs resources, cleanup code for exposing asset manager
This commit is contained in:
parent
68cd259bf7
commit
408127adea
|
@ -24,9 +24,8 @@ public class ExampleWorldImpl : IExampleWorld
|
||||||
Console.WriteLine($"C#: Delta time: {dt?.Seconds:0.##}");
|
Console.WriteLine($"C#: Delta time: {dt?.Seconds:0.##}");
|
||||||
} */
|
} */
|
||||||
|
|
||||||
AssetManager? man = world.GetAssetManager();
|
AssetManager? man = world.GetResource<AssetManager>();
|
||||||
if (man != null)
|
if (man != null) {
|
||||||
{
|
|
||||||
Handle<ImageHandle> han = man.Request<ImageHandle>("test_assets/white.png");
|
Handle<ImageHandle> han = man.Request<ImageHandle>("test_assets/white.png");
|
||||||
Console.WriteLine($"C#: Asset uuid: {han.Uuid}");
|
Console.WriteLine($"C#: Asset uuid: {han.Uuid}");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using LyraApi.Ecs;
|
using LyraApi.Ecs;
|
||||||
using ExampleWorld.wit.imports.lyra.api;
|
using ExampleWorld.wit.imports.lyra.api;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace LyraApi.Asset;
|
namespace LyraApi.Asset;
|
||||||
|
|
||||||
|
@ -15,11 +16,9 @@ public class AssetManager(IAsset.AssetManager assetManager) : IResource
|
||||||
{
|
{
|
||||||
case IEcs.WorldResourceResult.NONE:
|
case IEcs.WorldResourceResult.NONE:
|
||||||
return null;
|
return null;
|
||||||
case IEcs.WorldResourceResult.WASM_RESOURCE_REP:
|
case IEcs.WorldResourceResult.WASM_RESOURCE:
|
||||||
Console.WriteLine($"Got the resource rep: {result.AsWasmResourceRep}");
|
var handle = IAsset.AssetManager.FromEcsResource(result.AsWasmResource) ?? throw new MismatchedResourceResultException();
|
||||||
var handle = new IAsset.AssetManager.THandle((int)result.AsWasmResourceRep);
|
return new AssetManager(handle);
|
||||||
var inner = new IAsset.AssetManager(handle);
|
|
||||||
return new AssetManager(inner);
|
|
||||||
case IEcs.WorldResourceResult.BYTES:
|
case IEcs.WorldResourceResult.BYTES:
|
||||||
return null;
|
return null;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -4,10 +4,10 @@ public class Handle<T>(UntypedHandle handle) where T : IAssetHandle
|
||||||
{
|
{
|
||||||
internal UntypedHandle inner = handle;
|
internal UntypedHandle inner = handle;
|
||||||
|
|
||||||
public bool Watched { get => inner.Watched; set => inner.Watched = value; }
|
public bool Watched { get => inner.Watched; }
|
||||||
public ulong Version { get => inner.Version; }
|
public ulong Version { get => inner.Version; }
|
||||||
public Guid Uuid { get => inner.Uuid; }
|
public Guid Uuid { get => inner.Uuid; }
|
||||||
public string Path { get => inner.Path; }
|
public string? Path { get => inner.Path; }
|
||||||
public bool IsLoaded { get => inner.IsLoaded; }
|
public bool IsLoaded { get => inner.IsLoaded; }
|
||||||
|
|
||||||
public void WaitForLoad()
|
public void WaitForLoad()
|
||||||
|
|
|
@ -6,10 +6,10 @@ public class UntypedHandle(IAsset.AssetHandle handle)
|
||||||
{
|
{
|
||||||
internal IAsset.AssetHandle inner = handle;
|
internal IAsset.AssetHandle inner = handle;
|
||||||
|
|
||||||
public bool Watched { get => inner.IsWatched(); set => inner.SetWatched(value); }
|
public bool Watched { get => inner.IsWatched(); }
|
||||||
public ulong Version { get => inner.Version(); }
|
public ulong Version { get => inner.Version(); }
|
||||||
public Guid Uuid { get => Guid.Parse(inner.Uuid()); }
|
public Guid Uuid { get => Guid.Parse(inner.Uuid()); }
|
||||||
public string Path { get => inner.Path(); }
|
public string? Path { get => inner.Path(); }
|
||||||
public bool IsLoaded { get => inner.IsLoaded(); }
|
public bool IsLoaded { get => inner.IsLoaded(); }
|
||||||
|
|
||||||
public void WaitForLoad()
|
public void WaitForLoad()
|
||||||
|
|
|
@ -8,3 +8,5 @@ public interface IResource
|
||||||
|
|
||||||
public abstract static object? FromWasmResult(WorldResourceResult result);
|
public abstract static object? FromWasmResult(WorldResourceResult result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MismatchedResourceResultException : Exception {}
|
|
@ -35,7 +35,7 @@ public class World(IEcs.EcsWorld world)
|
||||||
return (T?)T.FromWasmResult(result);
|
return (T?)T.FromWasmResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssetManager? GetAssetManager()
|
/* public AssetManager? GetAssetManager()
|
||||||
{
|
{
|
||||||
IAsset.AssetManager? assetManager = IAsset.AssetManager.FromWorld(inner);
|
IAsset.AssetManager? assetManager = IAsset.AssetManager.FromWorld(inner);
|
||||||
|
|
||||||
|
@ -47,5 +47,5 @@ public class World(IEcs.EcsWorld world)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ public struct DeltaTime : IResource {
|
||||||
{
|
{
|
||||||
return result.Tag switch
|
return result.Tag switch
|
||||||
{
|
{
|
||||||
WorldResourceResult.NONE | WorldResourceResult.WASM_RESOURCE_REP => null,
|
WorldResourceResult.NONE | WorldResourceResult.WASM_RESOURCE => null,
|
||||||
WorldResourceResult.BYTES => MarshalUtils.FromBytes<DeltaTime>(result.AsBytes),
|
WorldResourceResult.BYTES => MarshalUtils.FromBytes<DeltaTime>(result.AsBytes),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
interface asset {
|
interface asset {
|
||||||
|
use ecs.{ecs-world, ecs-resource};
|
||||||
|
|
||||||
resource asset-handle {
|
resource asset-handle {
|
||||||
set-watched: func(watched: bool);
|
|
||||||
version: func() -> u64;
|
version: func() -> u64;
|
||||||
uuid: func() -> string;
|
uuid: func() -> string;
|
||||||
path: func() -> option<string>;
|
path: func() -> option<string>;
|
||||||
|
@ -18,10 +19,8 @@ interface asset {
|
||||||
get-bytes: func() -> option<list<u8>>;
|
get-bytes: func() -> option<list<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use ecs.{ecs-world};
|
|
||||||
|
|
||||||
resource asset-manager {
|
resource asset-manager {
|
||||||
from-world: static func(w: borrow<ecs-world>) -> option<asset-manager>;
|
from-ecs-resource: static func(w: borrow<ecs-resource>) -> option<asset-manager>;
|
||||||
request: func(path: string) -> asset-handle;
|
request: func(path: string) -> asset-handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,9 +37,16 @@ interface ecs {
|
||||||
next: func() -> option<tuple<entity, list<u8>>>;
|
next: func() -> option<tuple<entity, list<u8>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An resource that can be "downcasted" to a specific type.
|
||||||
|
///
|
||||||
|
/// You can use `T.from-ecs-resource` to "downcast" the type
|
||||||
|
resource ecs-resource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
variant world-resource-result {
|
variant world-resource-result {
|
||||||
none,
|
none,
|
||||||
wasm-resource-rep(u32),
|
wasm-resource(ecs-resource),
|
||||||
bytes(list<u8>),
|
bytes(list<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl EcsResource for DeltaTime {
|
||||||
fn from_wasm_result(result: &WorldResourceResult) -> Option<Self> {
|
fn from_wasm_result(result: &WorldResourceResult) -> Option<Self> {
|
||||||
match result {
|
match result {
|
||||||
WorldResourceResult::None => None,
|
WorldResourceResult::None => None,
|
||||||
WorldResourceResult::WasmResourceRep(_) => None,
|
WorldResourceResult::WasmResource(_) => None,
|
||||||
WorldResourceResult::Bytes(vec) => Some(Self(*bytemuck::from_bytes::<f32>(&vec))),
|
WorldResourceResult::Bytes(vec) => Some(Self(*bytemuck::from_bytes::<f32>(&vec))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
interface asset {
|
interface asset {
|
||||||
|
use ecs.{ecs-world, ecs-resource};
|
||||||
|
|
||||||
resource asset-handle {
|
resource asset-handle {
|
||||||
set-watched: func(watched: bool);
|
|
||||||
version: func() -> u64;
|
version: func() -> u64;
|
||||||
uuid: func() -> string;
|
uuid: func() -> string;
|
||||||
path: func() -> option<string>;
|
path: func() -> option<string>;
|
||||||
|
@ -18,10 +19,8 @@ interface asset {
|
||||||
get-bytes: func() -> option<list<u8>>;
|
get-bytes: func() -> option<list<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use ecs.{ecs-world};
|
|
||||||
|
|
||||||
resource asset-manager {
|
resource asset-manager {
|
||||||
from-world: static func(w: borrow<ecs-world>) -> option<asset-manager>;
|
from-ecs-resource: static func(w: borrow<ecs-resource>) -> option<asset-manager>;
|
||||||
request: func(path: string) -> asset-handle;
|
request: func(path: string) -> asset-handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,9 +37,16 @@ interface ecs {
|
||||||
next: func() -> option<tuple<entity, list<u8>>>;
|
next: func() -> option<tuple<entity, list<u8>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An resource that can be "downcasted" to a specific type.
|
||||||
|
///
|
||||||
|
/// You can use `T.from-ecs-resource` to "downcast" the type
|
||||||
|
resource ecs-resource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
variant world-resource-result {
|
variant world-resource-result {
|
||||||
none,
|
none,
|
||||||
wasm-resource-rep(u32),
|
wasm-resource(ecs-resource),
|
||||||
bytes(list<u8>),
|
bytes(list<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
interface asset {
|
interface asset {
|
||||||
|
use ecs.{ecs-world, ecs-resource};
|
||||||
|
|
||||||
resource asset-handle {
|
resource asset-handle {
|
||||||
set-watched: func(watched: bool);
|
|
||||||
version: func() -> u64;
|
version: func() -> u64;
|
||||||
uuid: func() -> string;
|
uuid: func() -> string;
|
||||||
path: func() -> option<string>;
|
path: func() -> option<string>;
|
||||||
|
@ -18,10 +19,8 @@ interface asset {
|
||||||
get-bytes: func() -> option<list<u8>>;
|
get-bytes: func() -> option<list<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use ecs.{ecs-world};
|
|
||||||
|
|
||||||
resource asset-manager {
|
resource asset-manager {
|
||||||
from-world: static func(w: borrow<ecs-world>) -> option<asset-manager>;
|
from-ecs-resource: static func(w: borrow<ecs-resource>) -> option<asset-manager>;
|
||||||
request: func(path: string) -> asset-handle;
|
request: func(path: string) -> asset-handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,9 +37,16 @@ interface ecs {
|
||||||
next: func() -> option<tuple<entity, list<u8>>>;
|
next: func() -> option<tuple<entity, list<u8>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An resource that can be "downcasted" to a specific type.
|
||||||
|
///
|
||||||
|
/// You can use `T.from-ecs-resource` to "downcast" the type
|
||||||
|
resource ecs-resource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
variant world-resource-result {
|
variant world-resource-result {
|
||||||
none,
|
none,
|
||||||
wasm-resource-rep(u32),
|
wasm-resource(ecs-resource),
|
||||||
bytes(list<u8>),
|
bytes(list<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
src/asset.rs
50
src/asset.rs
|
@ -1,10 +1,6 @@
|
||||||
use std::any::TypeId;
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tokio::task;
|
|
||||||
use wasmtime::component::Resource as WasmResource;
|
use wasmtime::component::Resource as WasmResource;
|
||||||
|
|
||||||
use crate::WasmError;
|
|
||||||
use crate::{lyra, Imports};
|
use crate::{lyra, Imports};
|
||||||
|
|
||||||
use lyra::api::asset as wasm_asset;
|
use lyra::api::asset as wasm_asset;
|
||||||
|
@ -14,17 +10,17 @@ impl wasm_asset::Host for Imports {}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl wasm_asset::HostAssetManager for Imports {
|
impl wasm_asset::HostAssetManager for Imports {
|
||||||
async fn from_world(&mut self, world: WasmResource<wasm_ecs::EcsWorld>) -> Option<WasmResource<wasm_asset::AssetManager>> {
|
async fn from_ecs_resource(&mut self, res: WasmResource<wasm_ecs::EcsResource>) -> Option<WasmResource<wasm_asset::AssetManager>> {
|
||||||
let world_entry = self
|
let res_rep = res.rep() as u32;
|
||||||
.world_slab
|
let res = self.resource_data_slab.get_mut(res_rep as _)?;
|
||||||
.get(world.rep() as _)
|
res.borrow += 1;
|
||||||
.ok_or(WasmError::InvalidResourceHandle("EcsWorld")).unwrap();
|
|
||||||
let world = &world_entry.world;
|
|
||||||
|
|
||||||
let man = world.get_resource_data::<lyra_engine::assets::ResourceManager>()?;
|
// ensure that the
|
||||||
let man_rep = self.asset_manager_slab.insert(man);
|
if !res.data.is::<lyra_engine::assets::ResourceManager>() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
Some(WasmResource::new_own(man_rep as _))
|
Some(WasmResource::new_own(res_rep as _))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request(
|
async fn request(
|
||||||
|
@ -32,33 +28,22 @@ impl wasm_asset::HostAssetManager for Imports {
|
||||||
this: WasmResource<wasm_asset::AssetManager>,
|
this: WasmResource<wasm_asset::AssetManager>,
|
||||||
path: String,
|
path: String,
|
||||||
) -> WasmResource<wasm_asset::AssetHandle> {
|
) -> WasmResource<wasm_asset::AssetHandle> {
|
||||||
let man = self.asset_manager_slab.get(this.rep() as _)
|
let man = self.resource_data_slab.get(this.rep() as _)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get::<lyra_engine::assets::ResourceManager>();
|
.data.get::<lyra_engine::assets::ResourceManager>();
|
||||||
let res = man.request_raw(&path).unwrap();
|
let res = man.request_raw(&path).unwrap();
|
||||||
let rep = self.asset_handles_slab.insert(res);
|
let rep = self.asset_handles_slab.insert(res);
|
||||||
WasmResource::new_own(rep as _)
|
WasmResource::new_own(rep as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn drop(&mut self, this: WasmResource<wasm_asset::AssetManager>) -> wasmtime::Result<()> {
|
async fn drop(&mut self, this: WasmResource<wasm_asset::AssetManager>) -> wasmtime::Result<()> {
|
||||||
let rep = this.rep() as usize;
|
self.resource_data_slab.drop_ref(this.rep() as _);
|
||||||
if self.asset_handles_slab.contains(rep) {
|
|
||||||
self.asset_manager_slab.remove(rep);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl wasm_asset::HostAssetHandle for Imports {
|
impl wasm_asset::HostAssetHandle for Imports {
|
||||||
async fn set_watched(&mut self, this: WasmResource<wasm_asset::AssetHandle>, watched: bool) {
|
|
||||||
let han = self.asset_handles_slab.get(this.rep() as _)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn version(&mut self, this: WasmResource<wasm_asset::AssetHandle>) -> u64 {
|
async fn version(&mut self, this: WasmResource<wasm_asset::AssetHandle>) -> u64 {
|
||||||
let han = self.asset_handles_slab.get(this.rep() as _)
|
let han = self.asset_handles_slab.get(this.rep() as _)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -111,7 +96,8 @@ impl wasm_asset::HostAssetHandle for Imports {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn drop(&mut self, this: WasmResource<wasm_asset::AssetHandle>) -> wasmtime::Result<()> {
|
async fn drop(&mut self, this: WasmResource<wasm_asset::AssetHandle>) -> wasmtime::Result<()> {
|
||||||
todo!()
|
self.asset_handles_slab.drop_ref(this.rep() as _);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +108,10 @@ impl wasm_asset::HostImageHandle for Imports {
|
||||||
// image will be none if the asset is not an image asset
|
// image will be none if the asset is not an image asset
|
||||||
let image = untyped.as_typed::<lyra_engine::assets::Image>();
|
let image = untyped.as_typed::<lyra_engine::assets::Image>();
|
||||||
if image.is_some() {
|
if image.is_some() {
|
||||||
Some(WasmResource::new_own(raw_handle.rep()))
|
let rep = raw_handle.rep();
|
||||||
|
self.asset_handles_slab.increment_ref(rep as _);
|
||||||
|
|
||||||
|
Some(WasmResource::new_own(rep))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -150,6 +139,7 @@ impl wasm_asset::HostImageHandle for Imports {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn drop(&mut self, this: WasmResource<wasm_asset::ImageHandle>) -> wasmtime::Result<()> {
|
async fn drop(&mut self, this: WasmResource<wasm_asset::ImageHandle>) -> wasmtime::Result<()> {
|
||||||
todo!()
|
self.asset_handles_slab.drop_ref(this.rep() as _);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
121
src/main.rs
121
src/main.rs
|
@ -9,22 +9,23 @@ use async_trait::async_trait;
|
||||||
use common_api::math::Vec3;
|
use common_api::math::Vec3;
|
||||||
use component::witguest::math;
|
use component::witguest::math;
|
||||||
use ecs::query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType};
|
use ecs::query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType};
|
||||||
use lyra_ecs::{query::dynamic::DynamicViewOne, DynTypeId, World};
|
use lyra_ecs::{query::dynamic::DynamicViewOne, World};
|
||||||
|
|
||||||
use lyra_ecs as ecs;
|
use lyra_ecs as ecs;
|
||||||
|
|
||||||
use lyra_engine::DeltaTime;
|
use lyra_engine::DeltaTime;
|
||||||
use lyra_reflect::{FromType, ReflectedResource, RegisteredType, TypeRegistry};
|
use lyra_reflect::{ReflectedResource, TypeRegistry};
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiView};
|
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiView};
|
||||||
|
|
||||||
use wasmtime::component::{Resource as WasmResource, ResourceAny};
|
use wasmtime::component::Resource as WasmResource;
|
||||||
|
|
||||||
mod proxy;
|
mod proxy;
|
||||||
pub use proxy::*;
|
pub use proxy::*;
|
||||||
|
|
||||||
mod asset;
|
mod asset;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use asset::*;
|
pub use asset::*;
|
||||||
|
|
||||||
/* #[allow(unused_imports)]
|
/* #[allow(unused_imports)]
|
||||||
|
@ -85,13 +86,84 @@ struct DynamicViewEntry {
|
||||||
view: DynamicViewStateIter,
|
view: DynamicViewStateIter,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct RefCountedData<T> {
|
||||||
|
pub borrow: u64,
|
||||||
|
pub data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for RefCountedData<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::DerefMut for RefCountedData<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Slab of reference counted data.
|
||||||
|
pub(crate) struct SlabRcData<T>(Slab<RefCountedData<T>>);
|
||||||
|
|
||||||
|
impl<T> From<Slab<RefCountedData<T>>> for SlabRcData<T> {
|
||||||
|
fn from(value: Slab<RefCountedData<T>>) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for SlabRcData<T> {
|
||||||
|
type Target = Slab<RefCountedData<T>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::DerefMut for SlabRcData<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SlabRcData<T> {
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self(Slab::with_capacity(capacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn increment_ref(&mut self, r: usize) {
|
||||||
|
if let Some(count) = self.0.get_mut(r) {
|
||||||
|
count.borrow += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop_ref(&mut self, r: usize) {
|
||||||
|
if let Some(count) = self.0.get_mut(r) {
|
||||||
|
// only remove the data from the slab if this is the only borrow
|
||||||
|
if count.borrow == 1 {
|
||||||
|
self.0.remove(r);
|
||||||
|
} else {
|
||||||
|
count.borrow -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert a new reference counted element into the slab.
|
||||||
|
pub fn insert(&mut self, data: T) -> usize {
|
||||||
|
self.0.insert(RefCountedData { borrow: 1, data, })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl Send for DynamicViewEntry {}
|
unsafe impl Send for DynamicViewEntry {}
|
||||||
|
|
||||||
pub(crate) struct Imports {
|
pub struct Imports {
|
||||||
pub(crate) world_slab: Slab<WorldEntry>,
|
pub(crate) world_slab: Slab<WorldEntry>,
|
||||||
pub(crate) world_views_slab: Slab<DynamicViewEntry>,
|
pub(crate) world_views_slab: Slab<DynamicViewEntry>,
|
||||||
pub(crate) asset_manager_slab: Slab<lyra_ecs::ResourceData>,
|
pub(crate) resource_data_slab: SlabRcData<lyra_ecs::ResourceData>,
|
||||||
pub(crate) asset_handles_slab: Slab<lyra_engine::assets::UntypedResHandle>,
|
pub(crate) asset_handles_slab: SlabRcData<lyra_engine::assets::UntypedResHandle>,
|
||||||
|
|
||||||
pub(crate) ctx: WasiCtx,
|
pub(crate) ctx: WasiCtx,
|
||||||
pub(crate) table: ResourceTable,
|
pub(crate) table: ResourceTable,
|
||||||
|
@ -279,9 +351,16 @@ impl wasm_ecs::HostEcsWorld for Imports {
|
||||||
let w = NonNull::from(world);
|
let w = NonNull::from(world);
|
||||||
let world = unsafe { w.as_ref() };
|
let world = unsafe { w.as_ref() };
|
||||||
let refl = refl.reflect(world).unwrap();
|
let refl = refl.reflect(world).unwrap();
|
||||||
let res = proxy.marshal_to_bytes(self, refl.deref());
|
let res = proxy.marshal_to_bytes(self, this.rep(), refl.deref());
|
||||||
|
|
||||||
res
|
match res {
|
||||||
|
ProxyResult::None => wasm_ecs::WorldResourceResult::None,
|
||||||
|
ProxyResult::Bytes(bytes) => wasm_ecs::WorldResourceResult::Bytes(bytes),
|
||||||
|
ProxyResult::WasmResource(data) => {
|
||||||
|
let rep = self.resource_data_slab.insert(data);
|
||||||
|
wasm_ecs::WorldResourceResult::WasmResource(WasmResource::new_own(rep as _))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn drop(
|
async fn drop(
|
||||||
|
@ -439,6 +518,18 @@ impl GuestTypeLookup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl wasm_ecs::HostEcsResource for Imports {
|
||||||
|
async fn drop(
|
||||||
|
&mut self,
|
||||||
|
this: wasmtime::component::Resource<wasm_ecs::EcsResource>,
|
||||||
|
) -> wasmtime::Result<()> {
|
||||||
|
self.resource_data_slab.drop_ref(this.rep() as _);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl wasm_ecs::Host for Imports {}
|
impl wasm_ecs::Host for Imports {}
|
||||||
|
|
||||||
|
@ -466,8 +557,8 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
// wants another world for some reason.
|
// wants another world for some reason.
|
||||||
world_slab: Slab::with_capacity(1),
|
world_slab: Slab::with_capacity(1),
|
||||||
world_views_slab: Slab::with_capacity(10),
|
world_views_slab: Slab::with_capacity(10),
|
||||||
asset_manager_slab: Slab::with_capacity(1),
|
resource_data_slab: SlabRcData::with_capacity(25),
|
||||||
asset_handles_slab: Slab::with_capacity(25),
|
asset_handles_slab: SlabRcData::with_capacity(25),
|
||||||
ctx: builder.build(),
|
ctx: builder.build(),
|
||||||
table: ResourceTable::new(),
|
table: ResourceTable::new(),
|
||||||
},
|
},
|
||||||
|
@ -478,7 +569,7 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
let bytes = std::fs::read("guests/csharp/dotnet-guest-test/bin/Debug/net9.0/wasi-wasm/native/dotnet-guest-test.wasm")?;
|
let bytes = std::fs::read("guests/csharp/dotnet-guest-test/bin/Debug/net9.0/wasi-wasm/native/dotnet-guest-test.wasm")?;
|
||||||
let component = wasmtime::component::Component::new(&engine, bytes)?;
|
let component = wasmtime::component::Component::new(&engine, bytes)?;
|
||||||
|
|
||||||
let (script_en, (world_res_a, world_res_b)) = {
|
let (script_en, (world_res_a, _)) = {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
|
|
||||||
world.add_resource(DeltaTime::from(100.00));
|
world.add_resource(DeltaTime::from(100.00));
|
||||||
|
@ -492,12 +583,8 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut reg = world.get_resource_or_default::<TypeRegistry>();
|
let mut reg = world.get_resource_or_default::<TypeRegistry>();
|
||||||
|
add_proxy_type_data::<DeltaTime>(&mut reg);
|
||||||
let mut dt_type = RegisteredType::new();
|
add_proxy_type_data::<lyra_engine::assets::ResourceManager>(&mut reg);
|
||||||
dt_type.add_data(<ReflectedResource as FromType::<DeltaTime>>::from_type());
|
|
||||||
dt_type.add_data(<WasmProxied as FromType::<DeltaTime>>::from_type());
|
|
||||||
|
|
||||||
reg.add_registered_type(TypeId::of::<DeltaTime>(), dt_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let script_en = world.spawn(());
|
let script_en = world.spawn(());
|
||||||
|
|
46
src/proxy.rs
46
src/proxy.rs
|
@ -1,20 +1,28 @@
|
||||||
use crate::{lyra::api::ecs as wasm_ecs, Imports};
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
use crate::Imports;
|
||||||
use common_api::bytemuck;
|
use common_api::bytemuck;
|
||||||
use lyra_engine::DeltaTime;
|
use lyra_engine::DeltaTime;
|
||||||
use lyra_reflect::{FromType, Reflect};
|
use lyra_reflect::{FromType, Reflect, ReflectedResource, TypeRegistry};
|
||||||
|
|
||||||
|
pub enum ProxyResult {
|
||||||
|
None,
|
||||||
|
WasmResource(lyra_ecs::ResourceData),
|
||||||
|
Bytes(Vec<u8>)
|
||||||
|
}
|
||||||
|
|
||||||
pub trait WasmProxy {
|
pub trait WasmProxy {
|
||||||
fn marshal_to_bytes(&self, imports: &mut Imports) -> wasm_ecs::WorldResourceResult;
|
fn marshal_to_bytes(&self, imports: &mut Imports, world_idx: u32) -> ProxyResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WasmProxied {
|
pub struct WasmProxied {
|
||||||
fn_marshal: for<'a> fn (&mut Imports, &'a dyn Reflect) -> wasm_ecs::WorldResourceResult,
|
fn_marshal: for<'a> fn (&mut Imports, world_idx: u32, &'a dyn Reflect) -> ProxyResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmProxied {
|
impl WasmProxied {
|
||||||
pub fn marshal_to_bytes(&self, imports: &mut Imports, reflected: &dyn Reflect) -> wasm_ecs::WorldResourceResult {
|
pub fn marshal_to_bytes(&self, imports: &mut Imports, world_idx: u32, reflected: &dyn Reflect) -> ProxyResult {
|
||||||
(self.fn_marshal)(imports, reflected)
|
(self.fn_marshal)(imports, world_idx, reflected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,25 +32,33 @@ where
|
||||||
{
|
{
|
||||||
fn from_type() -> Self {
|
fn from_type() -> Self {
|
||||||
WasmProxied {
|
WasmProxied {
|
||||||
fn_marshal: |imports, reflect| {
|
fn_marshal: |imports, world_idx: u32, reflect| {
|
||||||
let this: &T = reflect.as_any().downcast_ref().unwrap();
|
let this: &T = reflect.as_any().downcast_ref().unwrap();
|
||||||
this.marshal_to_bytes(imports)
|
this.marshal_to_bytes(imports, world_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_proxy_type_data<T: WasmProxy + lyra_ecs::ResourceObject + lyra_reflect::Reflect>(reg: &mut TypeRegistry) {
|
||||||
|
let ty = reg.get_type_or_default(TypeId::of::<T>());
|
||||||
|
ty.add_data(<ReflectedResource as FromType::<T>>::from_type());
|
||||||
|
ty.add_data(<WasmProxied as FromType::<T>>::from_type());
|
||||||
|
}
|
||||||
|
|
||||||
impl WasmProxy for DeltaTime {
|
impl WasmProxy for DeltaTime {
|
||||||
fn marshal_to_bytes(&self, _: &mut Imports) -> wasm_ecs::WorldResourceResult {
|
fn marshal_to_bytes(&self, _: &mut Imports, _: u32) -> ProxyResult {
|
||||||
wasm_ecs::WorldResourceResult::Bytes(bytemuck::bytes_of(&**self).to_vec())
|
ProxyResult::Bytes(bytemuck::bytes_of(&**self).to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmProxy for lyra_engine::assets::ResourceManager {
|
impl WasmProxy for lyra_engine::assets::ResourceManager {
|
||||||
fn marshal_to_bytes(&self, imports: &mut Imports) -> wasm_ecs::WorldResourceResult {
|
fn marshal_to_bytes(&self, imports: &mut Imports, world_idx: u32) -> ProxyResult {
|
||||||
//imports.
|
let world = &imports.world_slab.get(world_idx as _)
|
||||||
|
.unwrap().world;
|
||||||
todo!()
|
match world.get_resource_data::<Self>() {
|
||||||
//imports.asset_manager_slab.insert(val)
|
Some(data) => ProxyResult::WasmResource(data),
|
||||||
|
None => ProxyResult::None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue