Improve Lua ECS #30
|
@ -77,11 +77,9 @@ end
|
|||
end ]]
|
||||
|
||||
function on_update()
|
||||
-- Although WorldTransform isn't used, I only want to
|
||||
-- modify entities with that component.
|
||||
local view = View.new(Transform, Has(WorldTransform), Res(DeltaTime))
|
||||
-- Get entities without WorldTransform
|
||||
local view = View.new(Transform, Not(Has(WorldTransform)), Res(DeltaTime))
|
||||
local res = world:view_query(view)
|
||||
|
||||
---@param transform Transform
|
||||
---@param dt DeltaTime
|
||||
for entity, transform, dt in res:iter() do
|
||||
|
|
|
@ -25,3 +25,12 @@ end
|
|||
function Has(val)
|
||||
return HasQuery.new(val)
|
||||
end
|
||||
|
||||
---Create a `NotQuery` filter that will allow results if
|
||||
---
|
||||
---@see NotQuery
|
||||
---@param val function|table|userdata
|
||||
---@return NotQuery
|
||||
function Not(val)
|
||||
return NotQuery.new(val)
|
||||
end
|
|
@ -7,14 +7,20 @@ pub use changed::*;
|
|||
mod has;
|
||||
pub use has::*;
|
||||
|
||||
mod not;
|
||||
pub use not::*;
|
||||
|
||||
use lyra_ecs::Entity;
|
||||
|
||||
use crate::{lua::{LuaComponent, FN_NAME_INTERNAL_ECS_QUERY_RESULT}, ScriptEntity, ScriptWorldPtr};
|
||||
use crate::{
|
||||
lua::{LuaComponent, FN_NAME_INTERNAL_ECS_QUERY_RESULT},
|
||||
ScriptEntity, ScriptWorldPtr,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum QueryInner {
|
||||
Component(LuaComponent),
|
||||
Function(mlua::Function)
|
||||
Function(mlua::Function),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -33,15 +39,39 @@ impl LuaQuery {
|
|||
///
|
||||
/// > WARNING: ensure that the world pointer is not locked. If its locked when you call this,
|
||||
/// you WILL cause a deadlock.
|
||||
pub fn get_query_result(&self, world: ScriptWorldPtr, entity: Entity) -> mlua::Result<mlua::Value> {
|
||||
pub fn get_query_result(
|
||||
&self,
|
||||
world: ScriptWorldPtr,
|
||||
entity: Entity,
|
||||
) -> mlua::Result<mlua::Value> {
|
||||
let lua_en = ScriptEntity(entity);
|
||||
match &self.0 {
|
||||
QueryInner::Component(comp) => comp.call_method(FN_NAME_INTERNAL_ECS_QUERY_RESULT, (world, lua_en)),
|
||||
QueryInner::Component(comp) => {
|
||||
comp.call_method(FN_NAME_INTERNAL_ECS_QUERY_RESULT, (world, lua_en))
|
||||
}
|
||||
QueryInner::Function(function) => function.call((world, lua_en)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl mlua::FromLua for LuaQuery {
|
||||
fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
|
||||
let tyname = value.type_name();
|
||||
|
||||
if let Some(f) = value.as_function() {
|
||||
Ok(Self(QueryInner::Function(f.clone())))
|
||||
} else if let Ok(c) = LuaComponent::from_lua(value, lua) {
|
||||
Ok(Self(QueryInner::Component(c)))
|
||||
} else {
|
||||
Err(mlua::Error::FromLuaConversionError {
|
||||
from: tyname,
|
||||
to: "Query".into(),
|
||||
message: Some("expected query function, table, or user data".into()),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum LuaQueryResult {
|
||||
None,
|
||||
|
@ -59,20 +89,20 @@ impl mlua::IntoLua for LuaQueryResult {
|
|||
match self {
|
||||
LuaQueryResult::None => {
|
||||
t.set("result", "none")?;
|
||||
},
|
||||
}
|
||||
LuaQueryResult::AlwaysNone => {
|
||||
t.set("result", "always_none")?;
|
||||
},
|
||||
}
|
||||
LuaQueryResult::FilterPass => {
|
||||
t.set("result", "filter_pass")?;
|
||||
},
|
||||
}
|
||||
LuaQueryResult::FilterDeny => {
|
||||
t.set("result", "filter_deny")?;
|
||||
},
|
||||
}
|
||||
LuaQueryResult::Some(value) => {
|
||||
t.set("result", "some")?;
|
||||
t.set("val", value)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
t.into_lua(lua)
|
||||
|
@ -93,17 +123,22 @@ fn malformed_table_error_query_result(ty: &'static str, missing_field: &str) ->
|
|||
mlua::Error::FromLuaConversionError {
|
||||
from: ty,
|
||||
to: "QueryResult".into(),
|
||||
message: Some(format!("malformed table, cannot convert, failed to get field '{}'", missing_field)),
|
||||
message: Some(format!(
|
||||
"malformed table, cannot convert, failed to get field '{}'",
|
||||
missing_field
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
impl mlua::FromLua for LuaQueryResult {
|
||||
fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
|
||||
let ty = value.type_name();
|
||||
let table = value.as_table()
|
||||
let table = value
|
||||
.as_table()
|
||||
.ok_or(from_lua_error_query_result(ty, "expected Table"))?;
|
||||
|
||||
let var_name: String = table.get("enum_ty")
|
||||
let var_name: String = table
|
||||
.get("enum_ty")
|
||||
.map_err(|_| malformed_table_error_query_result(ty, "enum_ty"))?;
|
||||
if var_name != "query_result" {
|
||||
return Err(mlua::Error::FromLuaConversionError {
|
||||
|
@ -113,7 +148,8 @@ impl mlua::FromLua for LuaQueryResult {
|
|||
});
|
||||
}
|
||||
|
||||
let result: String = table.get("result")
|
||||
let result: String = table
|
||||
.get("result")
|
||||
.map_err(|_| malformed_table_error_query_result(ty, "result"))?;
|
||||
let result_str = result.as_str();
|
||||
|
||||
|
@ -123,17 +159,16 @@ impl mlua::FromLua for LuaQueryResult {
|
|||
"filter_pass" => Ok(Self::FilterPass),
|
||||
"filter_deny" => Ok(Self::FilterDeny),
|
||||
"value" => {
|
||||
let val: mlua::Value = table.get("val")
|
||||
let val: mlua::Value = table
|
||||
.get("val")
|
||||
.map_err(|_| malformed_table_error_query_result(ty, "val"))?;
|
||||
Ok(Self::Some(val))
|
||||
},
|
||||
_ => {
|
||||
Err(mlua::Error::FromLuaConversionError {
|
||||
}
|
||||
_ => Err(mlua::Error::FromLuaConversionError {
|
||||
from: ty,
|
||||
to: "QueryResult".into(),
|
||||
message: Some(format!("unknown result type: '{}'", result_str)),
|
||||
})
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
use crate::{
|
||||
lua::FN_NAME_INTERNAL_ECS_QUERY_RESULT,
|
||||
ScriptEntity, ScriptWorldPtr,
|
||||
};
|
||||
|
||||
use super::LuaQuery;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LuaNotQuery(LuaQuery);
|
||||
|
||||
impl mlua::FromLua for LuaNotQuery {
|
||||
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: "NotQuery".into(),
|
||||
message: None,
|
||||
})
|
||||
.and_then(|ud| ud.borrow::<Self>())
|
||||
.map(|ud| ud.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl mlua::UserData for LuaNotQuery {
|
||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_function("new", |_, q: LuaQuery| {
|
||||
Ok(Self(q))
|
||||
});
|
||||
|
||||
methods.add_method(
|
||||
FN_NAME_INTERNAL_ECS_QUERY_RESULT,
|
||||
|_, this, (world, en): (ScriptWorldPtr, ScriptEntity)| {
|
||||
let res = this.0.get_query_result(world, en.0)?;
|
||||
|
||||
if let Some(res_bool) = res.as_boolean() {
|
||||
Ok(!res_bool)
|
||||
} else if res.is_nil() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use lyra_ecs::ResourceObject;
|
||||
use lyra_reflect::Reflect;
|
||||
|
||||
use crate::{lua::{ecs::{query::{LuaChangedQuery, LuaHasQuery, LuaResQuery}, View}, wrappers::*, LuaContext, LuaWrapper, RegisterLuaType, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptApiProvider, ScriptBorrow, ScriptData, ScriptDynamicBundle, ScriptWorldPtr};
|
||||
use crate::{lua::{ecs::{query::{LuaChangedQuery, LuaHasQuery, LuaNotQuery, LuaResQuery}, View}, wrappers::*, LuaContext, LuaWrapper, RegisterLuaType, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptApiProvider, ScriptBorrow, ScriptData, ScriptDynamicBundle, ScriptWorldPtr};
|
||||
|
||||
//fn register_lua_proxy::<T:
|
||||
|
||||
|
@ -48,6 +48,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
|||
globals.set("ResQuery", ctx.create_proxy::<LuaResQuery>()?)?;
|
||||
globals.set("ChangedQuery", ctx.create_proxy::<LuaChangedQuery>()?)?;
|
||||
globals.set("HasQuery", ctx.create_proxy::<LuaHasQuery>()?)?;
|
||||
globals.set("NotQuery", ctx.create_proxy::<LuaNotQuery>()?)?;
|
||||
|
||||
expose_comp_table_wrapper::<LuaCamera>(&ctx, &globals, "Camera")?;
|
||||
expose_comp_table_wrapper::<LuaFreeFlyCamera>(&ctx, &globals, "FreeFlyCamera")?;
|
||||
|
|
Loading…
Reference in New Issue