Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser Runtime Implementation #11

Merged
merged 14 commits into from
Sep 2, 2022
Prev Previous commit
Next Next commit
Cleanup Browser Runtime Code
zicklag committed Aug 16, 2022
commit 305425dd061cbc8e909dcfe7d21ac4b8792114da
2 changes: 1 addition & 1 deletion assets/scripts/headless.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ function run() {
// info(world.resources.map(info => info.name));
// info("Resources (headless): " + filterComponentInfos(world.resources, "headless::").join(", "));
// info("Entitites: " + (world.entities.map(entity => `Entity(${entity.id}v${entity.generation})`).join(", ")));
// info("----------");
info("----------");

let transformId = componentId(
"bevy_transform::components::transform::Transform"
26 changes: 0 additions & 26 deletions examples/headless.rs
Original file line number Diff line number Diff line change
@@ -24,33 +24,7 @@ fn main() {
.add_startup_system(setup)
.add_js_system("scripts/headless.ts")
.register_type::<TestComponent>()
.register_type::<Scoreboard>()
.insert_resource(Scoreboard::default())
.run();
}

// This resource tracks the game's score
#[derive(Reflect)]
struct Scoreboard {
score: usize,
extra: ExtraData,
}

#[derive(Reflect)]
struct ExtraData {
name: String,
}

impl Default for Scoreboard {
fn default() -> Self {
Self {
score: 7,
extra: ExtraData {
name: "Awesome".into(),
},
}
}
}

#[derive(Component, Reflect)]
struct TestComponent {
66 changes: 66 additions & 0 deletions src/runtime/wasm/ecs/info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use bevy::{ecs::component::ComponentId, prelude::*, utils::HashSet};
use wasm_bindgen::prelude::*;

use crate::runtime::{
types::{JsComponentInfo, JsEntity},
wasm::{BevyModJsScripting, WORLD_RID},
};

#[wasm_bindgen]
impl BevyModJsScripting {
pub fn op_world_tostring(&self, rid: u32) -> String {
assert_eq!(rid, WORLD_RID);
let state = self.state();
let world = &state.world;

format!("{world:?}")
}

pub fn op_world_components(&self, rid: u32) -> Result<JsValue, JsValue> {
assert_eq!(rid, WORLD_RID);
let state = self.state();
let world = &state.world;

let resource_components: HashSet<ComponentId> =
world.archetypes().resource().components().collect();

let infos = world
.components()
.iter()
.filter(|info| !resource_components.contains(&info.id()))
.map(JsComponentInfo::from)
.collect::<Vec<_>>();

Ok(serde_wasm_bindgen::to_value(&infos)?)
}

pub fn op_world_resources(&self, rid: u32) -> Result<JsValue, JsValue> {
assert_eq!(rid, WORLD_RID);
let state = self.state();
let world = &state.world;

let infos = world
.archetypes()
.resource()
.components()
.map(|id| world.components().get_info(id).unwrap())
.map(JsComponentInfo::from)
.collect::<Vec<_>>();

Ok(serde_wasm_bindgen::to_value(&infos)?)
}

pub fn op_world_entities(&self, rid: u32) -> Result<JsValue, JsValue> {
assert_eq!(rid, WORLD_RID);
let mut state = self.state();
let world = &mut state.world;

let entities = world
.query::<Entity>()
.iter(world)
.map(JsEntity::from)
.collect::<Vec<_>>();

Ok(serde_wasm_bindgen::to_value(&entities)?)
}
}
5 changes: 5 additions & 0 deletions src/runtime/wasm/ecs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

mod info;
mod query;
mod resource;
mod value;
49 changes: 49 additions & 0 deletions src/runtime/wasm/ecs/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use bevy::ecs::component::ComponentId;
use bevy_ecs_dynamic::reflect_value_ref::{query::EcsValueRefQuery, ReflectValueRef};
use wasm_bindgen::prelude::*;

use crate::runtime::{
types::QueryDescriptor,
wasm::{BevyModJsScripting, JsQueryItem, JsRuntimeState, JsValueRef, WORLD_RID},
};

#[wasm_bindgen]
impl BevyModJsScripting {
pub fn op_world_query(&self, rid: u32, query: JsValue) -> Result<JsValue, JsValue> {
assert_eq!(rid, WORLD_RID);
let mut state = self.state();
let JsRuntimeState {
world, value_refs, ..
} = &mut *state;

let descriptor: QueryDescriptor = serde_wasm_bindgen::from_value(query)?;

let components: Vec<ComponentId> = descriptor
.components
.iter()
.map(ComponentId::from)
.collect();

let mut query = EcsValueRefQuery::new(world, &components);
let results = query
.iter(world)
.map(|item| {
let components = item
.items
.into_iter()
.map(|value| JsValueRef {
key: value_refs.insert(ReflectValueRef::ecs_ref(value)),
function: None,
})
.collect();

JsQueryItem {
entity: item.entity.into(),
components,
}
})
.collect::<Vec<_>>();

Ok(serde_wasm_bindgen::to_value(&results)?)
}
}
35 changes: 35 additions & 0 deletions src/runtime/wasm/ecs/resource.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use bevy_ecs_dynamic::reflect_value_ref::{EcsValueRef, ReflectValueRef};
use wasm_bindgen::prelude::*;

use crate::runtime::{
types::ComponentIdOrBevyType,
wasm::{BevyModJsScripting, JsRuntimeState, JsValueRef, WORLD_RID},
ToJsErr,
};

#[wasm_bindgen]
impl BevyModJsScripting {
pub fn op_world_get_resource(
&self,
rid: u32,
component_id: JsValue,
) -> Result<JsValue, JsValue> {
assert_eq!(rid, WORLD_RID);
let mut state = self.state();
let JsRuntimeState {
world, value_refs, ..
} = &mut *state;

let component_id: ComponentIdOrBevyType = serde_wasm_bindgen::from_value(component_id)?;
let component_id = component_id.component_id(world).to_js_error()?;

let value_ref = EcsValueRef::resource(world, component_id).to_js_error()?;

let value_ref = JsValueRef {
key: value_refs.insert(ReflectValueRef::ecs_ref(value_ref)),
function: None,
};

Ok(serde_wasm_bindgen::to_value(&value_ref)?)
}
}
Loading