lua: remove ReflectBranch::as_component_unchecked and improve error handling
This commit is contained in:
parent
b2b19c9ccc
commit
ba4acba638
7 changed files with 139 additions and 95 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1949,6 +1949,7 @@ name = "lyra-scripting-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"paste",
|
"paste",
|
||||||
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
|
|
|
@ -35,18 +35,6 @@ pub enum ReflectBranch {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReflectBranch {
|
impl ReflectBranch {
|
||||||
/// Gets self as a [`ReflectedComponent`].
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
/// If `self` is not a variant of [`ReflectBranch::Component`].
|
|
||||||
#[deprecated(note = "use ReflectBranch::as_component instead")]
|
|
||||||
pub fn as_component_unchecked(&self) -> &ReflectedComponent {
|
|
||||||
match self {
|
|
||||||
ReflectBranch::Component(c) => c,
|
|
||||||
_ => panic!("`self` is not an instance of `ReflectBranch::Component`"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets self as a [`ReflectedComponent`].
|
/// Gets self as a [`ReflectedComponent`].
|
||||||
///
|
///
|
||||||
/// Returns `None` if `self` is not a component.
|
/// Returns `None` if `self` is not a component.
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl ViewQueryItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if self is a Query.
|
/// Returns `true` if self is a Query.
|
||||||
///
|
///
|
||||||
/// If self is a function, it will return true. Else, it checks for a function with the
|
/// If self is a function, it will return true. Else, it checks for a function with the
|
||||||
/// name of [`FN_NAME_INTERNAL_ECS_QUERY_RESULT`] on the table or userdata. If the function
|
/// name of [`FN_NAME_INTERNAL_ECS_QUERY_RESULT`] on the table or userdata. If the function
|
||||||
/// is found, it returns true.
|
/// is found, it returns true.
|
||||||
|
@ -105,7 +105,7 @@ impl mlua::UserData for View {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Results of queries in a View.
|
/// Results of queries in a View.
|
||||||
///
|
///
|
||||||
/// Represents the results of multiple queries.
|
/// Represents the results of multiple queries.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum ViewQueryResult {
|
pub(crate) enum ViewQueryResult {
|
||||||
|
@ -163,16 +163,31 @@ impl ViewResult {
|
||||||
ViewQueryItem::UserData(ud) => {
|
ViewQueryItem::UserData(ud) => {
|
||||||
let reflect = ud
|
let reflect = ud
|
||||||
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
.expect("Type does not implement 'reflect_type' properly");
|
.map_err(|_| mlua::Error::BadArgument {
|
||||||
let refl_comp = reflect.reflect_branch.as_component()
|
to: Some("ViewResult.new".into()),
|
||||||
.expect("`self` is not an instance of `ReflectBranch::Component`");
|
pos: 2 + idx,
|
||||||
|
name: Some("query...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage(
|
||||||
|
format!("userdata does not implement type reflection"),
|
||||||
|
))),
|
||||||
|
})?;
|
||||||
|
let refl_comp = reflect.reflect_branch.as_component().ok_or_else(|| {
|
||||||
|
mlua::Error::BadArgument {
|
||||||
|
to: Some("ViewResult.new".into()),
|
||||||
|
pos: 2 + idx,
|
||||||
|
name: Some("query...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage(
|
||||||
|
format!("userdata is not a Component"),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
||||||
view.push(dyn_type);
|
view.push(dyn_type);
|
||||||
}
|
}
|
||||||
// functions are queries, the if statement at the start would cause this to
|
// functions are queries, the if statement at the start would cause this to
|
||||||
// be unreachable.
|
// be unreachable.
|
||||||
ViewQueryItem::Function(_) => unreachable!()
|
ViewQueryItem::Function(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,19 +238,19 @@ impl ViewResult {
|
||||||
let mut index_mod = 0;
|
let mut index_mod = 0;
|
||||||
for (query, i) in &self.queries {
|
for (query, i) in &self.queries {
|
||||||
let qres = query.get_query_result(self.world.clone(), entity)?;
|
let qres = query.get_query_result(self.world.clone(), entity)?;
|
||||||
|
|
||||||
match qres {
|
match qres {
|
||||||
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
||||||
LuaQueryResult::AlwaysNone => return Ok(ViewQueryResult::AlwaysNone),
|
LuaQueryResult::AlwaysNone => return Ok(ViewQueryResult::AlwaysNone),
|
||||||
LuaQueryResult::FilterPass => {
|
LuaQueryResult::FilterPass => {
|
||||||
// do not push a boolean to values, its considered a filter
|
// do not push a boolean to values, its considered a filter
|
||||||
index_mod += 1;
|
index_mod += 1;
|
||||||
},
|
}
|
||||||
LuaQueryResult::FilterDeny => return Ok(ViewQueryResult::FilterDeny),
|
LuaQueryResult::FilterDeny => return Ok(ViewQueryResult::FilterDeny),
|
||||||
LuaQueryResult::Some(value) => {
|
LuaQueryResult::Some(value) => {
|
||||||
let idx = (*i - index_mod).max(0);
|
let idx = (*i - index_mod).max(0);
|
||||||
query_vals.push((value, idx));
|
query_vals.push((value, idx));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,11 +283,11 @@ impl mlua::UserData for ViewResult {
|
||||||
ViewQueryResult::Some(v) => v,
|
ViewQueryResult::Some(v) => v,
|
||||||
ViewQueryResult::AlwaysNone => {
|
ViewQueryResult::AlwaysNone => {
|
||||||
return mlua::Value::Nil.into_lua_multi(lua);
|
return mlua::Value::Nil.into_lua_multi(lua);
|
||||||
},
|
}
|
||||||
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
||||||
// try to get it next loop
|
// try to get it next loop
|
||||||
continue;
|
continue;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// insert query values to the result row
|
// insert query values to the result row
|
||||||
|
@ -309,11 +324,11 @@ impl mlua::UserData for ViewResult {
|
||||||
ViewQueryResult::Some(v) => v,
|
ViewQueryResult::Some(v) => v,
|
||||||
ViewQueryResult::AlwaysNone => {
|
ViewQueryResult::AlwaysNone => {
|
||||||
return mlua::Value::Nil.into_lua_multi(lua);
|
return mlua::Value::Nil.into_lua_multi(lua);
|
||||||
},
|
}
|
||||||
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
||||||
// try to get it next loop
|
// try to get it next loop
|
||||||
continue;
|
continue;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// insert query values to the result row
|
// insert query values to the result row
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use lyra_ecs::{query::dynamic::{DynamicViewOneOwned, QueryDynamicType}, Entity};
|
use lyra_ecs::{
|
||||||
|
query::dynamic::{DynamicViewOneOwned, QueryDynamicType},
|
||||||
|
Entity,
|
||||||
|
};
|
||||||
use lyra_reflect::TypeRegistry;
|
use lyra_reflect::TypeRegistry;
|
||||||
use mlua::{IntoLua, IntoLuaMulti, ObjectLike};
|
use mlua::{IntoLua, IntoLuaMulti, ObjectLike};
|
||||||
|
|
||||||
use crate::{lua::{ReflectLuaProxy, TypeLookup, WorldError, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptBorrow, ScriptWorldPtr};
|
use crate::{
|
||||||
|
lua::{ReflectLuaProxy, TypeLookup, WorldError, FN_NAME_INTERNAL_REFLECT_TYPE},
|
||||||
|
ScriptBorrow, ScriptWorldPtr,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{query::{LuaQuery, LuaQueryResult}, View, ViewQueryItem, ViewQueryResult};
|
use super::{
|
||||||
|
query::{LuaQuery, LuaQueryResult},
|
||||||
|
View, ViewQueryItem, ViewQueryResult,
|
||||||
|
};
|
||||||
|
|
||||||
/// The result of an ecs world View of a single entity.
|
/// The result of an ecs world View of a single entity.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -69,16 +78,31 @@ impl ViewOneResult {
|
||||||
ViewQueryItem::UserData(ud) => {
|
ViewQueryItem::UserData(ud) => {
|
||||||
let reflect = ud
|
let reflect = ud
|
||||||
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
.expect("Type does not implement 'reflect_type' properly");
|
.ok_or_else(|| mlua::Error::BadArgument {
|
||||||
let refl_comp = reflect.reflect_branch.as_component()
|
to: Some("ViewOneResult.new".into()),
|
||||||
.expect("`self` is not an instance of `ReflectBranch::Component`");
|
pos: 2 + idx,
|
||||||
|
name: Some("query...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage(
|
||||||
|
format!("userdata does not implement type reflection"),
|
||||||
|
))),
|
||||||
|
})?;
|
||||||
|
let refl_comp = reflect.reflect_branch.as_component().ok_or_else(|| {
|
||||||
|
mlua::Error::BadArgument {
|
||||||
|
to: Some("ViewOneResult.new".into()),
|
||||||
|
pos: 2 + idx,
|
||||||
|
name: Some("query...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage(
|
||||||
|
format!("userdata is not a Component"),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
||||||
view.queries.push(dyn_type);
|
view.queries.push(dyn_type);
|
||||||
}
|
}
|
||||||
// functions are queries, the if statement at the start would cause this to
|
// functions are queries, the if statement at the start would cause this to
|
||||||
// be unreachable.
|
// be unreachable.
|
||||||
ViewQueryItem::Function(_) => unreachable!()
|
ViewQueryItem::Function(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,19 +127,19 @@ impl ViewOneResult {
|
||||||
let mut index_mod = 0;
|
let mut index_mod = 0;
|
||||||
for (query, i) in &self.queries {
|
for (query, i) in &self.queries {
|
||||||
let qres = query.get_query_result(self.world.clone(), entity)?;
|
let qres = query.get_query_result(self.world.clone(), entity)?;
|
||||||
|
|
||||||
match qres {
|
match qres {
|
||||||
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
||||||
LuaQueryResult::AlwaysNone => return Ok(ViewQueryResult::AlwaysNone),
|
LuaQueryResult::AlwaysNone => return Ok(ViewQueryResult::AlwaysNone),
|
||||||
LuaQueryResult::FilterPass => {
|
LuaQueryResult::FilterPass => {
|
||||||
// do not push a boolean to values, its considered a filter
|
// do not push a boolean to values, its considered a filter
|
||||||
index_mod += 1;
|
index_mod += 1;
|
||||||
},
|
}
|
||||||
LuaQueryResult::FilterDeny => return Ok(ViewQueryResult::FilterDeny),
|
LuaQueryResult::FilterDeny => return Ok(ViewQueryResult::FilterDeny),
|
||||||
LuaQueryResult::Some(value) => {
|
LuaQueryResult::Some(value) => {
|
||||||
let idx = (*i - index_mod).max(0);
|
let idx = (*i - index_mod).max(0);
|
||||||
query_vals.push((value, idx));
|
query_vals.push((value, idx));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +163,19 @@ impl ViewOneResult {
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
for d in row.iter() {
|
for d in row.iter() {
|
||||||
let id = d.info.type_id().as_rust();
|
let id = d.info.type_id().as_rust();
|
||||||
|
|
||||||
let reg_type = reg.get_type(id)
|
let reg_type = reg
|
||||||
|
.get_type(id)
|
||||||
.expect("Requested type was not found in TypeRegistry");
|
.expect("Requested type was not found in TypeRegistry");
|
||||||
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
let proxy = reg_type
|
||||||
|
.get_data::<ReflectLuaProxy>()
|
||||||
// TODO: properly handle this error
|
// TODO: properly handle this error
|
||||||
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
||||||
let value = proxy.as_lua(lua, d.ptr.cast()).unwrap()
|
let value = proxy
|
||||||
.into_lua(lua).unwrap();
|
.as_lua(lua, d.ptr.cast())
|
||||||
|
.unwrap()
|
||||||
|
.into_lua(lua)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
vals.push(value);
|
vals.push(value);
|
||||||
}
|
}
|
||||||
|
@ -165,9 +194,7 @@ impl ViewOneResult {
|
||||||
|
|
||||||
impl mlua::UserData for ViewOneResult {
|
impl mlua::UserData for ViewOneResult {
|
||||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||||
methods.add_method_mut("get", |lua, this, ()| {
|
methods.add_method_mut("get", |lua, this, ()| this.get_res_impl(lua));
|
||||||
this.get_res_impl(lua)
|
|
||||||
});
|
|
||||||
methods.add_meta_method(mlua::MetaMethod::Call, |lua, this, ()| {
|
methods.add_meta_method(mlua::MetaMethod::Call, |lua, this, ()| {
|
||||||
this.get_res_impl(lua)
|
this.get_res_impl(lua)
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,9 @@ use mlua::{IntoLua, ObjectLike};
|
||||||
|
|
||||||
use crate::{ScriptBorrow, ScriptWorldPtr};
|
use crate::{ScriptBorrow, ScriptWorldPtr};
|
||||||
|
|
||||||
use super::{reflect_type_user_data, Error, ReflectLuaProxy, TypeLookup, FN_NAME_INTERNAL_REFLECT_TYPE};
|
use super::{
|
||||||
|
reflect_type_user_data, Error, ReflectLuaProxy, TypeLookup, FN_NAME_INTERNAL_REFLECT_TYPE,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum LuaComponent {
|
pub enum LuaComponent {
|
||||||
|
@ -50,14 +52,14 @@ impl LuaComponent {
|
||||||
}
|
}
|
||||||
Self::UserData(ud) => {
|
Self::UserData(ud) => {
|
||||||
let lua_comp = reflect_type_user_data(ud);
|
let lua_comp = reflect_type_user_data(ud);
|
||||||
let refl_comp = lua_comp.reflect_branch.as_component_unchecked();
|
let refl_comp = lua_comp.reflect_branch.as_component()?;
|
||||||
Some(refl_comp.info.type_id().as_rust())
|
Some(refl_comp.info.type_id().as_rust())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call the internal reflect type function and return the result.
|
/// Call the internal reflect type function and return the result.
|
||||||
///
|
///
|
||||||
/// This calls the [`FN_NAME_INTERNAL_REFLECT_TYPE`] function on the Component.
|
/// This calls the [`FN_NAME_INTERNAL_REFLECT_TYPE`] function on the Component.
|
||||||
pub fn reflect_type(&self) -> Result<ScriptBorrow, Error> {
|
pub fn reflect_type(&self) -> Result<ScriptBorrow, Error> {
|
||||||
self.call_function(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
self.call_function(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
|
@ -65,9 +67,13 @@ impl LuaComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a Lua function on the Component.
|
/// Call a Lua function on the Component.
|
||||||
///
|
///
|
||||||
/// This is a helper function so you don't have to match on the component.
|
/// This is a helper function so you don't have to match on the component.
|
||||||
pub fn call_function<R: mlua::FromLuaMulti>(&self, name: &str, args: impl mlua::IntoLuaMulti) -> mlua::Result<R> {
|
pub fn call_function<R: mlua::FromLuaMulti>(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
args: impl mlua::IntoLuaMulti,
|
||||||
|
) -> mlua::Result<R> {
|
||||||
match self {
|
match self {
|
||||||
LuaComponent::UserData(ud) => ud.call_function(name, args),
|
LuaComponent::UserData(ud) => ud.call_function(name, args),
|
||||||
LuaComponent::Table(t) => t.call_function(name, args),
|
LuaComponent::Table(t) => t.call_function(name, args),
|
||||||
|
@ -75,9 +81,13 @@ impl LuaComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a Lua method on the Component.
|
/// Call a Lua method on the Component.
|
||||||
///
|
///
|
||||||
/// This is a helper function so you don't have to match on the component.
|
/// This is a helper function so you don't have to match on the component.
|
||||||
pub fn call_method<R: mlua::FromLuaMulti>(&self, name: &str, args: impl mlua::IntoLuaMulti) -> mlua::Result<R> {
|
pub fn call_method<R: mlua::FromLuaMulti>(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
args: impl mlua::IntoLuaMulti,
|
||||||
|
) -> mlua::Result<R> {
|
||||||
match self {
|
match self {
|
||||||
LuaComponent::UserData(ud) => ud.call_method(name, args),
|
LuaComponent::UserData(ud) => ud.call_method(name, args),
|
||||||
LuaComponent::Table(t) => t.call_method(name, args),
|
LuaComponent::Table(t) => t.call_method(name, args),
|
||||||
|
@ -87,12 +97,8 @@ impl LuaComponent {
|
||||||
/// Returns `true` if the Component has a function of `name`.
|
/// Returns `true` if the Component has a function of `name`.
|
||||||
pub fn has_function(&self, name: &str) -> mlua::Result<bool> {
|
pub fn has_function(&self, name: &str) -> mlua::Result<bool> {
|
||||||
match self {
|
match self {
|
||||||
LuaComponent::UserData(ud) => {
|
LuaComponent::UserData(ud) => ud.get::<mlua::Value>(name).map(|v| !v.is_nil()),
|
||||||
ud.get::<mlua::Value>(name).map(|v| !v.is_nil())
|
LuaComponent::Table(t) => t.contains_key(name),
|
||||||
},
|
|
||||||
LuaComponent::Table(t) => {
|
|
||||||
t.contains_key(name)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,10 +113,7 @@ pub struct LuaEntityRef {
|
||||||
|
|
||||||
impl LuaEntityRef {
|
impl LuaEntityRef {
|
||||||
pub fn new(world: ScriptWorldPtr, en: Entity) -> Self {
|
pub fn new(world: ScriptWorldPtr, en: Entity) -> Self {
|
||||||
Self {
|
Self { en, world }
|
||||||
en,
|
|
||||||
world,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +142,7 @@ impl mlua::UserData for LuaEntityRef {
|
||||||
let arch_idx = *arch.entity_indexes().get(&this.en).unwrap();
|
let arch_idx = *arch.entity_indexes().get(&this.en).unwrap();
|
||||||
let col = arch.get_column_mut(tid).unwrap();
|
let col = arch.get_column_mut(tid).unwrap();
|
||||||
let col_ptr = col.component_ptr(*arch_idx as usize, &world_tick).cast();
|
let col_ptr = col.component_ptr(*arch_idx as usize, &world_tick).cast();
|
||||||
|
|
||||||
// get the type registry to apply the new value
|
// get the type registry to apply the new value
|
||||||
let reg = world.get_resource::<TypeRegistry>().unwrap();
|
let reg = world.get_resource::<TypeRegistry>().unwrap();
|
||||||
let reg_type = reg.get_type(tid).unwrap();
|
let reg_type = reg.get_type(tid).unwrap();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::{any::TypeId, collections::HashMap, ptr::NonNull};
|
use std::{any::TypeId, collections::HashMap, ptr::NonNull, sync::Arc};
|
||||||
|
|
||||||
use mlua::ObjectLike;
|
|
||||||
use lyra_ecs::{ComponentInfo, DynamicBundle};
|
use lyra_ecs::{ComponentInfo, DynamicBundle};
|
||||||
use lyra_reflect::Reflect;
|
use lyra_reflect::Reflect;
|
||||||
|
use mlua::ObjectLike;
|
||||||
|
|
||||||
use crate::{ScriptBorrow, ScriptDynamicBundle};
|
use crate::{ScriptBorrow, ScriptDynamicBundle};
|
||||||
|
|
||||||
use super::{Error, FN_NAME_INTERNAL_REFLECT};
|
use super::{Error, WorldError, FN_NAME_INTERNAL_REFLECT};
|
||||||
|
|
||||||
pub trait LuaWrapper: Sized {
|
pub trait LuaWrapper: Sized {
|
||||||
type Wrap: 'static;
|
type Wrap: 'static;
|
||||||
|
@ -18,7 +18,7 @@ pub trait LuaWrapper: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_wrapped(self) -> Self::Wrap;
|
fn into_wrapped(self) -> Self::Wrap;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from_wrapped(wrap: Self::Wrap) -> Option<Self> {
|
fn from_wrapped(wrap: Self::Wrap) -> Option<Self> {
|
||||||
let _ = wrap;
|
let _ = wrap;
|
||||||
|
@ -28,35 +28,21 @@ pub trait LuaWrapper: Sized {
|
||||||
|
|
||||||
/// A trait that used to convert something into lua, or to set something to a value from lua.
|
/// A trait that used to convert something into lua, or to set something to a value from lua.
|
||||||
pub trait LuaProxy {
|
pub trait LuaProxy {
|
||||||
fn as_lua_value(
|
fn as_lua_value(lua: &mlua::Lua, this: &dyn Reflect) -> mlua::Result<mlua::Value>;
|
||||||
lua: &mlua::Lua,
|
|
||||||
this: &dyn Reflect,
|
|
||||||
) -> mlua::Result<mlua::Value>;
|
|
||||||
|
|
||||||
fn apply(
|
fn apply(lua: &mlua::Lua, this: &mut dyn Reflect, value: &mlua::Value) -> mlua::Result<()>;
|
||||||
lua: &mlua::Lua,
|
|
||||||
this: &mut dyn Reflect,
|
|
||||||
value: &mlua::Value,
|
|
||||||
) -> mlua::Result<()>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> LuaProxy for T
|
impl<'a, T> LuaProxy for T
|
||||||
where
|
where
|
||||||
T: Reflect + Clone + mlua::FromLua + mlua::IntoLua
|
T: Reflect + Clone + mlua::FromLua + mlua::IntoLua,
|
||||||
{
|
{
|
||||||
fn as_lua_value(
|
fn as_lua_value(lua: &mlua::Lua, this: &dyn Reflect) -> mlua::Result<mlua::Value> {
|
||||||
lua: &mlua::Lua,
|
|
||||||
this: &dyn Reflect,
|
|
||||||
) -> mlua::Result<mlua::Value> {
|
|
||||||
let this = this.as_any().downcast_ref::<T>().unwrap();
|
let this = this.as_any().downcast_ref::<T>().unwrap();
|
||||||
this.clone().into_lua(lua)
|
this.clone().into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(
|
fn apply(lua: &mlua::Lua, this: &mut dyn Reflect, apply: &mlua::Value) -> mlua::Result<()> {
|
||||||
lua: &mlua::Lua,
|
|
||||||
this: &mut dyn Reflect,
|
|
||||||
apply: &mlua::Value,
|
|
||||||
) -> mlua::Result<()> {
|
|
||||||
let this = this.as_any_mut().downcast_mut::<T>().unwrap();
|
let this = this.as_any_mut().downcast_mut::<T>().unwrap();
|
||||||
let apply = T::from_lua(apply.clone(), lua)?;
|
let apply = T::from_lua(apply.clone(), lua)?;
|
||||||
|
|
||||||
|
@ -67,7 +53,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ECS resource that can be used to lookup types via name.
|
/// ECS resource that can be used to lookup types via name.
|
||||||
///
|
///
|
||||||
/// You can get the [`TypeId`] of the type via name, or the [`ComponentInfo`].
|
/// You can get the [`TypeId`] of the type via name, or the [`ComponentInfo`].
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TypeLookup {
|
pub struct TypeLookup {
|
||||||
|
@ -78,8 +64,7 @@ pub struct TypeLookup {
|
||||||
/// A struct used for Proxying types to and from Lua.
|
/// A struct used for Proxying types to and from Lua.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ReflectLuaProxy {
|
pub struct ReflectLuaProxy {
|
||||||
fn_as_lua:
|
fn_as_lua: for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<()>) -> mlua::Result<mlua::Value>,
|
||||||
for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<()>) -> mlua::Result<mlua::Value>,
|
|
||||||
fn_apply: for<'a> fn(
|
fn_apply: for<'a> fn(
|
||||||
lua: &'a mlua::Lua,
|
lua: &'a mlua::Lua,
|
||||||
this_ptr: NonNull<()>,
|
this_ptr: NonNull<()>,
|
||||||
|
@ -90,8 +75,8 @@ pub struct ReflectLuaProxy {
|
||||||
impl ReflectLuaProxy {
|
impl ReflectLuaProxy {
|
||||||
/// Create from a type that implements LuaProxy (among some other required traits)
|
/// Create from a type that implements LuaProxy (among some other required traits)
|
||||||
pub fn from_lua_proxy<'a, T>() -> Self
|
pub fn from_lua_proxy<'a, T>() -> Self
|
||||||
where
|
where
|
||||||
T: Reflect + LuaProxy
|
T: Reflect + LuaProxy,
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
fn_as_lua: |lua, this| -> mlua::Result<mlua::Value> {
|
fn_as_lua: |lua, this| -> mlua::Result<mlua::Value> {
|
||||||
|
@ -108,7 +93,7 @@ impl ReflectLuaProxy {
|
||||||
/// Create from a type that implements FromLua and AsLua
|
/// Create from a type that implements FromLua and AsLua
|
||||||
pub fn from_as_and_from_lua<T>() -> Self
|
pub fn from_as_and_from_lua<T>() -> Self
|
||||||
where
|
where
|
||||||
T: mlua::FromLua + mlua::IntoLua + Clone
|
T: mlua::FromLua + mlua::IntoLua + Clone,
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
fn_as_lua: |lua, this| -> mlua::Result<mlua::Value> {
|
fn_as_lua: |lua, this| -> mlua::Result<mlua::Value> {
|
||||||
|
@ -120,7 +105,7 @@ impl ReflectLuaProxy {
|
||||||
let new_val = T::from_lua(value.clone(), lua)?;
|
let new_val = T::from_lua(value.clone(), lua)?;
|
||||||
|
|
||||||
*this = new_val;
|
*this = new_val;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -132,7 +117,12 @@ impl ReflectLuaProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the contents in the pointer to a Lua value.
|
/// Set the contents in the pointer to a Lua value.
|
||||||
pub fn apply(&self, lua: &mlua::Lua, this_ptr: NonNull<()>, value: &mlua::Value) -> mlua::Result<()> {
|
pub fn apply(
|
||||||
|
&self,
|
||||||
|
lua: &mlua::Lua,
|
||||||
|
this_ptr: NonNull<()>,
|
||||||
|
value: &mlua::Value,
|
||||||
|
) -> mlua::Result<()> {
|
||||||
(self.fn_apply)(lua, this_ptr, value)
|
(self.fn_apply)(lua, this_ptr, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +142,18 @@ impl mlua::UserData for ScriptDynamicBundle {
|
||||||
methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new())));
|
methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new())));
|
||||||
methods.add_method_mut("push", |_, this, comp: mlua::AnyUserData| {
|
methods.add_method_mut("push", |_, this, comp: mlua::AnyUserData| {
|
||||||
let script_brw = comp.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
let script_brw = comp.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
||||||
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
let reflect =
|
||||||
|
script_brw
|
||||||
|
.reflect_branch
|
||||||
|
.as_component()
|
||||||
|
.ok_or(mlua::Error::BadArgument {
|
||||||
|
to: Some("DynamicBundle:push".into()),
|
||||||
|
pos: 2,
|
||||||
|
name: Some("component...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage(
|
||||||
|
"userdata is not a Component".into(),
|
||||||
|
))),
|
||||||
|
})?;
|
||||||
|
|
||||||
let refl_data = script_brw.data.unwrap();
|
let refl_data = script_brw.data.unwrap();
|
||||||
reflect.bundle_insert(&mut this.0, refl_data);
|
reflect.bundle_insert(&mut this.0, refl_data);
|
||||||
|
@ -160,4 +161,4 @@ impl mlua::UserData for ScriptDynamicBundle {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,16 @@ impl mlua::UserData for ScriptWorldPtr {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let reflect = comp_borrow.reflect_branch.as_component_unchecked();
|
let reflect =
|
||||||
|
comp_borrow
|
||||||
|
.reflect_branch
|
||||||
|
.as_component()
|
||||||
|
.ok_or(mlua::Error::BadArgument {
|
||||||
|
to: Some("World:spawn".into()),
|
||||||
|
pos: 2 + i, // i starts at 0
|
||||||
|
name: Some("components...".into()),
|
||||||
|
cause: Arc::new(mlua::Error::runtime("userdata is not a Component")),
|
||||||
|
})?;
|
||||||
let refl_data = comp_borrow.data.unwrap();
|
let refl_data = comp_borrow.data.unwrap();
|
||||||
reflect.bundle_insert(&mut bundle, refl_data);
|
reflect.bundle_insert(&mut bundle, refl_data);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue