lua: implement world:view_one for lua
This commit is contained in:
parent
964c4ec423
commit
0e613bd216
|
@ -1,4 +1,5 @@
|
||||||
local is_window_setup = false
|
local is_window_setup = false
|
||||||
|
local cube_entity = nil
|
||||||
|
|
||||||
---Return the userdata's name from its metatable.
|
---Return the userdata's name from its metatable.
|
||||||
---
|
---
|
||||||
|
@ -40,6 +41,7 @@ function on_init()
|
||||||
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
||||||
|
|
||||||
local e = world:spawn(pos, cube_scene)
|
local e = world:spawn(pos, cube_scene)
|
||||||
|
cube_entity = e
|
||||||
print("spawned entity " .. tostring(e))
|
print("spawned entity " .. tostring(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -100,6 +102,14 @@ function on_update()
|
||||||
for _, tick in tick_res:iter() do
|
for _, tick in tick_res:iter() do
|
||||||
print("Entity transform last changed on tick " .. tostring(tick))
|
print("Entity transform last changed on tick " .. tostring(tick))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local pos_view = View.new(Transform)
|
||||||
|
local vone = world:view_one(cube_entity, pos_view)
|
||||||
|
local r = vone()
|
||||||
|
if r ~= nil then
|
||||||
|
local pos = r[1]
|
||||||
|
print("Found cube entity at '" .. tostring(pos) .. "'")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ function on_post_update()
|
--[[ function on_post_update()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use crate::{query::Fetch, Entity, World};
|
use crate::{query::Fetch, Entity, World};
|
||||||
|
|
||||||
use super::{DynamicType, FetchDynamicTypeUnsafe, QueryDynamicType};
|
use super::{DynamicType, FetchDynamicTypeUnsafe, QueryDynamicType};
|
||||||
|
@ -9,16 +11,28 @@ use super::{DynamicType, FetchDynamicTypeUnsafe, QueryDynamicType};
|
||||||
/// since Rust doesn't actually need to know the types of what its iterating over.
|
/// since Rust doesn't actually need to know the types of what its iterating over.
|
||||||
pub struct DynamicViewOne<'a> {
|
pub struct DynamicViewOne<'a> {
|
||||||
world: &'a World,
|
world: &'a World,
|
||||||
pub entity: Entity,
|
inner: DynamicViewOneOwned,
|
||||||
pub queries: Vec<QueryDynamicType>
|
}
|
||||||
|
|
||||||
|
impl<'a> Deref for DynamicViewOne<'a> {
|
||||||
|
type Target = DynamicViewOneOwned;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DerefMut for DynamicViewOne<'a> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DynamicViewOne<'a> {
|
impl<'a> DynamicViewOne<'a> {
|
||||||
pub fn new(world: &'a World, entity: Entity) -> Self {
|
pub fn new(world: &'a World, entity: Entity) -> Self {
|
||||||
Self {
|
Self {
|
||||||
world,
|
world,
|
||||||
entity,
|
inner: DynamicViewOneOwned::new(entity)
|
||||||
queries: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,36 +40,67 @@ impl<'a> DynamicViewOne<'a> {
|
||||||
pub fn new_with(world: &'a World, entity: Entity, queries: Vec<QueryDynamicType>) -> Self {
|
pub fn new_with(world: &'a World, entity: Entity, queries: Vec<QueryDynamicType>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
world,
|
world,
|
||||||
|
inner: DynamicViewOneOwned::new_with(entity, queries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self) -> Option<Vec<DynamicType>> {
|
||||||
|
self.inner.get(&self.world)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A variant of [`DynamicViewOne`] that doesn't store a borrow of the world.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DynamicViewOneOwned {
|
||||||
|
pub entity: Entity,
|
||||||
|
pub queries: Vec<QueryDynamicType>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicViewOneOwned {
|
||||||
|
pub fn new(entity: Entity) -> Self {
|
||||||
|
Self {
|
||||||
|
entity,
|
||||||
|
queries: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new [`DynamicViewOne`] with queries.
|
||||||
|
pub fn new_with(entity: Entity, queries: Vec<QueryDynamicType>) -> Self {
|
||||||
|
Self {
|
||||||
entity,
|
entity,
|
||||||
queries
|
queries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self) -> Option<Vec<DynamicType>> {
|
pub fn get(self, world: &World) -> Option<Vec<DynamicType>> {
|
||||||
let arch = self.world.entity_archetype(self.entity)?;
|
dynamic_view_one_get_impl(world, &self.queries, self.entity)
|
||||||
let aid = arch.entity_indexes().get(&self.entity)?;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get all fetchers for the queries
|
fn dynamic_view_one_get_impl(world: &World, queries: &Vec<QueryDynamicType>, entity: Entity) -> Option<Vec<DynamicType>> {
|
||||||
let mut fetchers: Vec<FetchDynamicTypeUnsafe> = self.queries.iter()
|
let arch = world.entity_archetype(entity)?;
|
||||||
.map(|q| unsafe { q.fetch(self.world, arch.id(), arch) } )
|
let aid = arch.entity_indexes().get(&entity)?;
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut fetch_res = vec![];
|
// get all fetchers for the queries
|
||||||
for fetcher in fetchers.iter_mut() {
|
let mut fetchers: Vec<FetchDynamicTypeUnsafe> = queries.iter()
|
||||||
if !fetcher.can_visit_item(*aid) {
|
.map(|q| unsafe { q.fetch(world, arch.id(), arch) } )
|
||||||
return None;
|
.collect();
|
||||||
} else {
|
|
||||||
let i = unsafe { fetcher.get_item(*aid) };
|
|
||||||
fetch_res.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fetch_res.is_empty() {
|
let mut fetch_res = vec![];
|
||||||
None
|
for fetcher in fetchers.iter_mut() {
|
||||||
|
if !fetcher.can_visit_item(*aid) {
|
||||||
|
return None;
|
||||||
} else {
|
} else {
|
||||||
Some(fetch_res)
|
let i = unsafe { fetcher.get_item(*aid) };
|
||||||
|
fetch_res.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fetch_res.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(fetch_res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -10,7 +10,6 @@ use super::ReflectLuaProxy;
|
||||||
|
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
pub struct ReflectedItem {
|
pub struct ReflectedItem {
|
||||||
//pub proxy: &'a ReflectLuaProxy,
|
|
||||||
pub comp_ptr: NonNull<u8>,
|
pub comp_ptr: NonNull<u8>,
|
||||||
pub comp_val: mlua::Value,
|
pub comp_val: mlua::Value,
|
||||||
}
|
}
|
||||||
|
@ -24,7 +23,6 @@ pub struct ReflectedRow {
|
||||||
pub struct ReflectedIteratorOwned {
|
pub struct ReflectedIteratorOwned {
|
||||||
pub world_ptr: ScriptWorldPtr,
|
pub world_ptr: ScriptWorldPtr,
|
||||||
pub dyn_view: DynamicViewStateIter,
|
pub dyn_view: DynamicViewStateIter,
|
||||||
//pub reflected_components: Option<NonNull<TypeRegistry>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReflectedIteratorOwned {
|
impl ReflectedIteratorOwned {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
mod view;
|
mod view;
|
||||||
pub use view::*;
|
pub use view::*;
|
||||||
|
|
||||||
|
mod view_one;
|
||||||
|
pub use view_one::*;
|
||||||
|
|
||||||
pub mod query;
|
pub mod query;
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
use super::query::{LuaQuery, LuaQueryResult};
|
use super::query::{LuaQuery, LuaQueryResult};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum ViewQueryItem {
|
pub(crate) enum ViewQueryItem {
|
||||||
UserData(mlua::AnyUserData),
|
UserData(mlua::AnyUserData),
|
||||||
Table(mlua::Table),
|
Table(mlua::Table),
|
||||||
Function(mlua::Function),
|
Function(mlua::Function),
|
||||||
|
@ -76,7 +76,7 @@ impl ViewQueryItem {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct View {
|
pub struct View {
|
||||||
items: Vec<ViewQueryItem>,
|
pub(crate) items: Vec<ViewQueryItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl mlua::FromLua for View {
|
impl mlua::FromLua for View {
|
||||||
|
@ -104,11 +104,15 @@ impl mlua::UserData for View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Results of queries in a View.
|
||||||
|
///
|
||||||
|
/// Represents the results of multiple queries.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum QueryRowResult {
|
pub(crate) enum ViewQueryResult {
|
||||||
None,
|
None,
|
||||||
AlwaysNone,
|
AlwaysNone,
|
||||||
FilterDeny,
|
FilterDeny,
|
||||||
|
/// The results of the queries and the index they should be inserted at in the resulting row.
|
||||||
Some(Vec<(mlua::Value, u32)>),
|
Some(Vec<(mlua::Value, u32)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +215,7 @@ impl ViewResult {
|
||||||
///
|
///
|
||||||
/// The indexes are used to make sure that the results are in the same order that the script
|
/// The indexes are used to make sure that the results are in the same order that the script
|
||||||
/// requested them in.
|
/// requested them in.
|
||||||
fn get_query_results(&self, entity: Entity) -> mlua::Result<QueryRowResult> {
|
fn get_query_results(&self, entity: Entity) -> mlua::Result<ViewQueryResult> {
|
||||||
let mut query_vals = vec![];
|
let mut query_vals = vec![];
|
||||||
|
|
||||||
// A modifier is used that will be incremented every time a filter allowed the query.
|
// A modifier is used that will be incremented every time a filter allowed the query.
|
||||||
|
@ -221,13 +225,13 @@ impl ViewResult {
|
||||||
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(QueryRowResult::None),
|
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
||||||
LuaQueryResult::AlwaysNone => return Ok(QueryRowResult::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(QueryRowResult::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));
|
||||||
|
@ -235,7 +239,7 @@ impl ViewResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(QueryRowResult::Some(query_vals))
|
Ok(ViewQueryResult::Some(query_vals))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,11 +265,11 @@ impl mlua::UserData for ViewResult {
|
||||||
Some((en, mut vals)) => {
|
Some((en, mut vals)) => {
|
||||||
loop {
|
loop {
|
||||||
let query_vals = match this.get_query_results(en)? {
|
let query_vals = match this.get_query_results(en)? {
|
||||||
QueryRowResult::Some(v) => v,
|
ViewQueryResult::Some(v) => v,
|
||||||
QueryRowResult::AlwaysNone => {
|
ViewQueryResult::AlwaysNone => {
|
||||||
return mlua::Value::Nil.into_lua_multi(lua);
|
return mlua::Value::Nil.into_lua_multi(lua);
|
||||||
},
|
},
|
||||||
QueryRowResult::None | QueryRowResult::FilterDeny => {
|
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
||||||
// try to get it next loop
|
// try to get it next loop
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
@ -302,11 +306,11 @@ impl mlua::UserData for ViewResult {
|
||||||
LuaEntityRef::new(this.world.clone(), en).into_lua(lua)?;
|
LuaEntityRef::new(this.world.clone(), en).into_lua(lua)?;
|
||||||
|
|
||||||
let query_vals = match this.get_query_results(en)? {
|
let query_vals = match this.get_query_results(en)? {
|
||||||
QueryRowResult::Some(v) => v,
|
ViewQueryResult::Some(v) => v,
|
||||||
QueryRowResult::AlwaysNone => {
|
ViewQueryResult::AlwaysNone => {
|
||||||
return mlua::Value::Nil.into_lua_multi(lua);
|
return mlua::Value::Nil.into_lua_multi(lua);
|
||||||
},
|
},
|
||||||
QueryRowResult::None | QueryRowResult::FilterDeny => {
|
ViewQueryResult::None | ViewQueryResult::FilterDeny => {
|
||||||
// try to get it next loop
|
// try to get it next loop
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use lyra_ecs::{query::dynamic::{DynamicViewOneOwned, QueryDynamicType}, Entity};
|
||||||
|
use lyra_reflect::TypeRegistry;
|
||||||
|
use mlua::{IntoLua, IntoLuaMulti, ObjectLike};
|
||||||
|
|
||||||
|
use crate::{lua::{ReflectLuaProxy, TypeLookup, WorldError, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptBorrow, ScriptWorldPtr};
|
||||||
|
|
||||||
|
use super::{query::{LuaQuery, LuaQueryResult}, View, ViewQueryItem, ViewQueryResult};
|
||||||
|
|
||||||
|
/// The result of an ecs world View of a single entity.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ViewOneResult {
|
||||||
|
world: ScriptWorldPtr,
|
||||||
|
dynamic_view: DynamicViewOneOwned,
|
||||||
|
/// The queries and the index they would be inserted in the result.
|
||||||
|
queries: Vec<(LuaQuery, u32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mlua::FromLua for ViewOneResult {
|
||||||
|
fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
|
||||||
|
let tyname = value.type_name();
|
||||||
|
value
|
||||||
|
.as_userdata()
|
||||||
|
.ok_or(mlua::Error::FromLuaConversionError {
|
||||||
|
from: tyname,
|
||||||
|
to: "View".into(),
|
||||||
|
message: None,
|
||||||
|
})
|
||||||
|
.and_then(|ud| ud.borrow::<Self>())
|
||||||
|
.map(|ud| ud.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViewOneResult {
|
||||||
|
pub fn new(world: ScriptWorldPtr, entity: Entity, view: &View) -> Result<Self, mlua::Error> {
|
||||||
|
let items = view.items.clone();
|
||||||
|
let w = world.read();
|
||||||
|
let mut view = DynamicViewOneOwned::new(entity);
|
||||||
|
let mut queries = vec![];
|
||||||
|
|
||||||
|
for (idx, comp) in items.iter().enumerate() {
|
||||||
|
if comp.is_query()? {
|
||||||
|
queries.push((comp.as_query(), idx as u32));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match comp {
|
||||||
|
ViewQueryItem::Table(t) => {
|
||||||
|
let name: String = t.get(mlua::MetaMethod::Type.name())?;
|
||||||
|
|
||||||
|
let lookup = w.get_resource::<TypeLookup>().ok_or(mlua::Error::runtime(
|
||||||
|
"Unable to lookup table proxy, none were ever registered!",
|
||||||
|
))?;
|
||||||
|
let info = lookup.comp_info_from_name.get(&name).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!("the 'Table' with name {} is unknown to the engine!", name),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let dyn_type = QueryDynamicType::from_info(info.clone());
|
||||||
|
view.queries.push(dyn_type);
|
||||||
|
}
|
||||||
|
ViewQueryItem::UserData(ud) => {
|
||||||
|
let reflect = ud
|
||||||
|
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
|
.expect("Type does not implement 'reflect_type' properly");
|
||||||
|
let refl_comp = reflect.reflect_branch.as_component()
|
||||||
|
.expect("`self` is not an instance of `ReflectBranch::Component`");
|
||||||
|
|
||||||
|
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
||||||
|
view.queries.push(dyn_type);
|
||||||
|
}
|
||||||
|
// functions are queries, the if statement at the start would cause this to
|
||||||
|
// be unreachable.
|
||||||
|
ViewQueryItem::Function(_) => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(w);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
world,
|
||||||
|
dynamic_view: view,
|
||||||
|
queries,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the query results and the indexes that they were provided in.
|
||||||
|
///
|
||||||
|
/// The indexes are used to make sure that the results are in the same order that the script
|
||||||
|
/// requested them in.
|
||||||
|
fn get_query_results(&self, entity: Entity) -> mlua::Result<ViewQueryResult> {
|
||||||
|
let mut query_vals = vec![];
|
||||||
|
|
||||||
|
// A modifier is used that will be incremented every time a filter allowed the query.
|
||||||
|
// this is used to remove the value of a filter without leaving a gap in the results.
|
||||||
|
let mut index_mod = 0;
|
||||||
|
for (query, i) in &self.queries {
|
||||||
|
let qres = query.get_query_result(self.world.clone(), entity)?;
|
||||||
|
|
||||||
|
match qres {
|
||||||
|
LuaQueryResult::None => return Ok(ViewQueryResult::None),
|
||||||
|
LuaQueryResult::AlwaysNone => return Ok(ViewQueryResult::AlwaysNone),
|
||||||
|
LuaQueryResult::FilterPass => {
|
||||||
|
// do not push a boolean to values, its considered a filter
|
||||||
|
index_mod += 1;
|
||||||
|
},
|
||||||
|
LuaQueryResult::FilterDeny => return Ok(ViewQueryResult::FilterDeny),
|
||||||
|
LuaQueryResult::Some(value) => {
|
||||||
|
let idx = (*i - index_mod).max(0);
|
||||||
|
query_vals.push((value, idx));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ViewQueryResult::Some(query_vals))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_res_impl(&self, lua: &mlua::Lua) -> mlua::Result<mlua::MultiValue> {
|
||||||
|
let world = self.world.read();
|
||||||
|
|
||||||
|
let qresults = self.get_query_results(self.dynamic_view.entity)?;
|
||||||
|
let qvals = match qresults {
|
||||||
|
ViewQueryResult::None => return mlua::Value::Nil.into_lua_multi(lua),
|
||||||
|
ViewQueryResult::AlwaysNone => return mlua::Value::Nil.into_lua_multi(lua),
|
||||||
|
ViewQueryResult::FilterDeny => return mlua::Value::Nil.into_lua_multi(lua),
|
||||||
|
ViewQueryResult::Some(vec) => vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
let dv = self.dynamic_view.clone();
|
||||||
|
if let Some(row) = dv.get(&world) {
|
||||||
|
let reg = world.get_resource::<TypeRegistry>().unwrap();
|
||||||
|
let mut vals = vec![];
|
||||||
|
for d in row.iter() {
|
||||||
|
let id = d.info.type_id().as_rust();
|
||||||
|
|
||||||
|
let reg_type = reg.get_type(id)
|
||||||
|
.expect("Requested type was not found in TypeRegistry");
|
||||||
|
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
||||||
|
// TODO: properly handle this error
|
||||||
|
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
||||||
|
let value = proxy.as_lua(lua, d.ptr.cast()).unwrap()
|
||||||
|
.into_lua(lua).unwrap();
|
||||||
|
|
||||||
|
vals.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert query values to the result row
|
||||||
|
for (v, i) in qvals {
|
||||||
|
vals.insert(i as _, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
vals.into_lua_multi(lua)
|
||||||
|
} else {
|
||||||
|
mlua::Value::Nil.into_lua_multi(lua)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mlua::UserData for ViewOneResult {
|
||||||
|
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||||
|
methods.add_method_mut("get", |lua, this, ()| {
|
||||||
|
this.get_res_impl(lua)
|
||||||
|
});
|
||||||
|
methods.add_meta_method(mlua::MetaMethod::Call, |lua, this, ()| {
|
||||||
|
this.get_res_impl(lua)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ use lyra_resource::ResourceManager;
|
||||||
use mlua::{IntoLua, ObjectLike};
|
use mlua::{IntoLua, ObjectLike};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
ecs::{View, ViewResult}, reflect_user_data, wrappers::{LuaResHandleToComponent, LuaTick, LuaWrappedEventProxy}, Error, ReflectLuaProxy, ReflectedIterator, TypeLookup, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
|
ecs::{View, ViewOneResult, ViewResult}, reflect_user_data, wrappers::{LuaResHandleToComponent, LuaTick, LuaWrappedEventProxy}, Error, ReflectLuaProxy, ReflectedIterator, TypeLookup, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
impl mlua::FromLua for ScriptEntity {
|
impl mlua::FromLua for ScriptEntity {
|
||||||
|
@ -356,5 +356,8 @@ impl mlua::UserData for ScriptWorldPtr {
|
||||||
let w = this.read();
|
let w = this.read();
|
||||||
Ok(LuaTick(w.current_tick()))
|
Ok(LuaTick(w.current_tick()))
|
||||||
});
|
});
|
||||||
|
methods.add_method("view_one", |_, this, (entity, view): (ScriptEntity, mlua::UserDataRef<View>)| {
|
||||||
|
ViewOneResult::new(this.clone(), *entity, &view)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue