Skip to content

Commit

Permalink
Implement op_value_ref_call for Browser Runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
zicklag committed Aug 16, 2022
1 parent bb24498 commit 7b96832
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 164 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ wasm_mutex = "0.1.4"
js-sys = "0.3.59"
wasm-bindgen = { version = "0.2.82", features = ["enable-interning"] }
serde-wasm-bindgen = "0.4.3"
slab = "0.4.7"
slotmap = { version = "1.0.6", features = ["serde"] }

[dev-dependencies]
bevy = { version = "0.8.0", default-features = false, features = ["render", "bevy_winit", "x11", "filesystem_watcher"] }
61 changes: 39 additions & 22 deletions assets/scripts/headless.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
let i = 0;
function filterComponentInfos(
infos: ComponentInfo[],
prefix: string
): string[] {
return infos
.filter((info) => info.name.startsWith(prefix))
.map((info) => info.name.replace(prefix, ""));
}

type Scoreboard = {
score: number;
extra: ExtraData;
};
type ExtraData = {
name: string;
};
const Scoreboard: BevyType<Scoreboard> = { typeName: "headless::Scoreboard" };
function componentId(name) {
let id = world.components.find((info) => info.name === name);
if (!id) throw new Error(`component id for ${name} not found`);
return id.id;
}

info("Loaded");
let firstIteration = true;
function run() {
if (firstIteration) {
firstIteration = false;

export default {
update() {
if (i == 0) {
info(world.resources);
}
// info("Components: " + world.components.map(info => info.name).join(", "));
// info("Resources:");
// 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("----------");

if (i % 3 == 0) {
let score = world.resource(Scoreboard);
info(score.toString());
info(score.score);
info(score.extra.name);
let transformId = componentId(
"bevy_transform::components::transform::Transform"
);

let query = world.query({
components: [transformId],
});
let [transform1, transform2] = query.map((item) => item.components[0]);
let [translation1, translation2] = [transform1.translation, transform2.translation];

for (const s of [0.0, 0.25, 0.5, 0.75, 1.0]) {
info(translation1.lerp(translation2, s).toString());
}
}
}

i++;
},
export default {
update: run,
};
65 changes: 4 additions & 61 deletions src/runtime/native/ecs/call.rs
Original file line number Diff line number Diff line change
@@ -1,74 +1,17 @@
use crate::runtime::types::{Primitive, ReflectArgIntermediate, ReflectArgIntermediateValue};

use super::{
v8_utils::{
create_value_ref_object, reflect_value_ref_from_v8_value_transmit,
reflect_value_ref_from_value_transmit, ValueRefObject,
},
WorldResource,
};
use bevy::prelude::*;
use bevy_ecs_dynamic::reflect_value_ref::{
ReflectValueRef, ReflectValueRefBorrow, ReflectValueRefBorrowMut,
};
use bevy_ecs_dynamic::reflect_value_ref::ReflectValueRef;
use bevy_reflect_fns::{PassMode, ReflectArg};
use deno_core::{error::AnyError, op, serde_v8, v8, OpState, ResourceId};
use std::{any::TypeId, cell::RefCell, rc::Rc};

// Value, from which a `ReflectArg` can be borrowed
enum ReflectArgIntermediate<'a> {
Value(ReflectArgIntermediateValue<'a>),
Primitive(Primitive, PassMode),
}

enum ReflectArgIntermediateValue<'a> {
Ref(ReflectValueRefBorrow<'a>),
#[allow(dead_code)]
RefMut(ReflectValueRefBorrowMut<'a>),
Owned(ReflectValueRefBorrow<'a>),
}

impl<'a> ReflectArgIntermediateValue<'a> {
fn to_arg(&mut self) -> ReflectArg<'_> {
match self {
ReflectArgIntermediateValue::Ref(val) => ReflectArg::Ref(&**val),
ReflectArgIntermediateValue::RefMut(val) => ReflectArg::RefMut(&mut **val),
ReflectArgIntermediateValue::Owned(val) => ReflectArg::Owned(&**val),
}
}
}
impl<'a> ReflectArgIntermediate<'a> {
fn to_arg(&mut self) -> ReflectArg<'_> {
match self {
ReflectArgIntermediate::Value(val) => val.to_arg(),
ReflectArgIntermediate::Primitive(prim, pass_mode) => prim.to_arg(*pass_mode),
}
}
}

#[allow(non_camel_case_types)]
enum Primitive {
f32(f32),
f64(f64),
i32(i32),
u32(u32),
}

impl Primitive {
fn to_arg(&mut self, pass_mode: PassMode) -> ReflectArg<'_> {
let reflect: &mut dyn Reflect = match self {
Primitive::f32(val) => val,
Primitive::f64(val) => val,
Primitive::i32(val) => val,
Primitive::u32(val) => val,
};

match pass_mode {
PassMode::Ref => ReflectArg::Ref(reflect),
PassMode::RefMut => ReflectArg::RefMut(reflect),
PassMode::Owned => ReflectArg::Owned(reflect),
}
}
}

#[op(v8)]
fn op_value_ref_call(
state: &mut OpState,
Expand Down Expand Up @@ -150,7 +93,7 @@ fn op_value_ref_call(
.collect::<Result<Vec<_>, AnyError>>()?;
let mut args: Vec<ReflectArg> = std::iter::once(&mut receiver_intermediate)
.chain(arg_intermediates.iter_mut())
.map(|intermediate| intermediate.to_arg())
.map(|intermediate| intermediate.as_arg())
.collect();

let ret = method.call(args.as_mut_slice())?;
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/native/ecs/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub fn op_value_ref_get(
let reflect_methods = type_registry
.get_type_data::<bevy_reflect_fns::ReflectMethods>(value_ref.get(&world)?.type_id());
if let Some(reflect_methods) = reflect_methods {
let method_name = path.trim_start_matches(".");
if let Some(reflect_function) = reflect_methods.get(method_name.trim_start_matches(".")) {
let method_name = path.trim_start_matches('.');
if let Some(reflect_function) = reflect_methods.get(method_name.trim_start_matches('.')) {
return Ok(unsafe {
create_value_ref_object(
scope,
Expand Down Expand Up @@ -146,6 +146,6 @@ pub fn op_value_ref_to_string(
let reflect = value.get(&world)?;
Ok(format!("{reflect:?}"))
}
ReflectValueRefTransmit::Method(_, method) => Ok(format!("{}", method.fn_name)),
ReflectValueRefTransmit::Method(_, method) => Ok(method.fn_name.to_string()),
}
}
62 changes: 61 additions & 1 deletion src/runtime/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use bevy::{
ecs::component::{ComponentId, ComponentInfo},
prelude::{Entity, World},
};
use bevy_reflect::TypeRegistryArc;
use bevy_ecs_dynamic::reflect_value_ref::{ReflectValueRefBorrow, ReflectValueRefBorrowMut};
use bevy_reflect::{Reflect, TypeRegistryArc};
use bevy_reflect_fns::{PassMode, ReflectArg};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Debug)]
Expand Down Expand Up @@ -87,3 +89,61 @@ impl From<Entity> for JsEntity {
pub struct QueryDescriptor {
pub components: Vec<JsComponentId>,
}

// Value, from which a `ReflectArg` can be borrowed
pub enum ReflectArgIntermediate<'a> {
Value(ReflectArgIntermediateValue<'a>),
Primitive(Primitive, PassMode),
}

pub enum ReflectArgIntermediateValue<'a> {
Ref(ReflectValueRefBorrow<'a>),
#[allow(dead_code)]
RefMut(ReflectValueRefBorrowMut<'a>),
Owned(ReflectValueRefBorrow<'a>),
}

impl<'a> ReflectArgIntermediateValue<'a> {
pub fn as_arg(&mut self) -> ReflectArg<'_> {
match self {
ReflectArgIntermediateValue::Ref(val) => ReflectArg::Ref(&**val),
ReflectArgIntermediateValue::RefMut(val) => ReflectArg::RefMut(&mut **val),
ReflectArgIntermediateValue::Owned(val) => ReflectArg::Owned(&**val),
}
}
}
impl<'a> ReflectArgIntermediate<'a> {
pub fn as_arg(&mut self) -> ReflectArg<'_> {
match self {
ReflectArgIntermediate::Value(val) => val.as_arg(),
ReflectArgIntermediate::Primitive(prim, pass_mode) => prim.as_arg(*pass_mode),
}
}
}

#[allow(non_camel_case_types)]
#[derive(Deserialize, Debug)]
#[serde(untagged)]
pub enum Primitive {
f32(f32),
f64(f64),
i32(i32),
u32(u32),
}

impl Primitive {
pub fn as_arg(&mut self, pass_mode: PassMode) -> ReflectArg<'_> {
let reflect: &mut dyn Reflect = match self {
Primitive::f32(val) => val,
Primitive::f64(val) => val,
Primitive::i32(val) => val,
Primitive::u32(val) => val,
};

match pass_mode {
PassMode::Ref => ReflectArg::Ref(reflect),
PassMode::RefMut => ReflectArg::RefMut(reflect),
PassMode::Owned => ReflectArg::Owned(reflect),
}
}
}
Loading

0 comments on commit 7b96832

Please sign in to comment.