Improve Lua ECS #30
|
@ -77,22 +77,14 @@ end
|
||||||
end ]]
|
end ]]
|
||||||
|
|
||||||
function on_update()
|
function on_update()
|
||||||
--[[ ---@type number
|
-- Although WorldTransform isn't used, I only want to
|
||||||
local dt = world:resource(DeltaTime)
|
-- modify entities with that component.
|
||||||
local act = world:resource(ActionHandler)
|
|
||||||
---@type number
|
|
||||||
local move_objs = act:get_axis("ObjectsMoveUpDown")
|
|
||||||
|
|
||||||
world:view(function (t)
|
|
||||||
if move_objs ~= nil then
|
|
||||||
t:translate(0, move_objs * 0.35 * dt, 0)
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
end, Transform) ]]
|
|
||||||
|
|
||||||
-- although WorldTransform isn't used, I only want to modify entities with that component.
|
|
||||||
local view = View.new(Transform, WorldTransform, Res(DeltaTime))
|
local view = View.new(Transform, WorldTransform, Res(DeltaTime))
|
||||||
local res = world:view_query(view)
|
local res = world:view_query(view)
|
||||||
|
|
||||||
|
---@param transform Transform
|
||||||
|
---@param _wt WorldTransform
|
||||||
|
---@param dt DeltaTime
|
||||||
for entity, transform, _wt, dt in res:iter() do
|
for entity, transform, _wt, dt in res:iter() do
|
||||||
transform:translate(0, 0.15 * dt, 0)
|
transform:translate(0, 0.15 * dt, 0)
|
||||||
entity:update(transform)
|
entity:update(transform)
|
||||||
|
@ -100,8 +92,9 @@ function on_update()
|
||||||
|
|
||||||
local changed_view = View.new(Changed(Transform))
|
local changed_view = View.new(Changed(Transform))
|
||||||
local changed_res = world:view_query(changed_view)
|
local changed_res = world:view_query(changed_view)
|
||||||
|
---@param transform Transform
|
||||||
for _, transform in changed_res:iter() do
|
for _, transform in changed_res:iter() do
|
||||||
print("Entity transform changed to: " .. tostring(transform))
|
print("Entity transform changed to: '" .. tostring(transform) .. "' on tick " .. tostring(world:get_tick()))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,12 @@ impl TickTracker {
|
||||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default, PartialOrd, Ord)]
|
||||||
pub struct Tick(u64);
|
pub struct Tick(u64);
|
||||||
|
|
||||||
|
impl From<u64> for Tick {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for Tick {
|
impl std::ops::Deref for Tick {
|
||||||
type Target = u64;
|
type Target = u64;
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ function Res(resource)
|
||||||
return ResQuery.new(resource)
|
return ResQuery.new(resource)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Create a Changed Query of a resource or component.
|
---Create a `ChangedQuery` of a resource or component.
|
||||||
---@param resource table|userdata
|
---@param val table|userdata
|
||||||
---@return ChangedQuery
|
---@return ChangedQuery
|
||||||
function Changed(val)
|
function Changed(val)
|
||||||
return ChangedQuery.new(val)
|
return ChangedQuery.new(val)
|
||||||
|
|
|
@ -1,4 +1,29 @@
|
||||||
---@meta
|
---@meta
|
||||||
|
|
||||||
|
---An entity handle.
|
||||||
---@class Entity: userdata
|
---@class Entity: userdata
|
||||||
Entity = {}
|
Entity = {}
|
||||||
|
|
||||||
|
---Get the id of the Entity.
|
||||||
|
---@return number
|
||||||
|
function Entity:id() end
|
||||||
|
|
||||||
|
---Get the generation number of the Entity.
|
||||||
|
---
|
||||||
|
---Entity handles are reused by the ECS World, the generation is used to tell reused Entity
|
||||||
|
---id's apart from previous generations.
|
||||||
|
---
|
||||||
|
---@return number
|
||||||
|
function Entity:generation() end
|
||||||
|
|
||||||
|
---A reference to an entity in the world.
|
||||||
|
---
|
||||||
|
---Can be used to insert and update components on the entity.
|
||||||
|
---
|
||||||
|
---@class EntityRef: userdata
|
||||||
|
EntityRef = {}
|
||||||
|
|
||||||
|
---Update components that are **already** on an Entity.
|
||||||
|
---
|
||||||
|
---@param ... any The components to update on the entity.
|
||||||
|
function EntityRef:update(...) end
|
|
@ -0,0 +1,9 @@
|
||||||
|
---@meta
|
||||||
|
|
||||||
|
---@class EventReader<T>: userdata
|
||||||
|
EventReader = {}
|
||||||
|
|
||||||
|
---Get an iterator for reading the event.
|
||||||
|
---@generic T
|
||||||
|
---@return fun(): T? iterator An iterator for reading the events.
|
||||||
|
function EventReader:read() end
|
|
@ -0,0 +1,9 @@
|
||||||
|
require "action_handler"
|
||||||
|
require "camera"
|
||||||
|
require "delta_time"
|
||||||
|
require "entity"
|
||||||
|
require "event_reader"
|
||||||
|
require "free_fly_camera"
|
||||||
|
require "window"
|
||||||
|
require "world_transform"
|
||||||
|
require "world"
|
|
@ -0,0 +1,22 @@
|
||||||
|
---@meta
|
||||||
|
|
||||||
|
---An ECS query used for obtaining **changed** resources or components from the world.
|
||||||
|
---
|
||||||
|
---Use the utility function `Changed(...)` to create a new query since its faster to
|
||||||
|
---write than this.
|
||||||
|
---
|
||||||
|
---This query will not return if the resource or component has not changed since the last tick.
|
||||||
|
---
|
||||||
|
---@class ChangedQuery: userdata
|
||||||
|
ChangedQuery = {}
|
||||||
|
|
||||||
|
---Create a new ChangedQuery.
|
||||||
|
---
|
||||||
|
---Use the utility function `Changed(...)` to create a new query since its faster to
|
||||||
|
---write than this.
|
||||||
|
---
|
||||||
|
---@param val table|userdata The component or resource to detect changed of.
|
||||||
|
function ChangedQuery:new(val) end
|
||||||
|
|
||||||
|
---An internal function used by the engine to retrieve the query result.
|
||||||
|
function ChangedQuery:__lyra_internal_ecs_query_result(world, entity) end
|
|
@ -0,0 +1,3 @@
|
||||||
|
require "view"
|
||||||
|
require "changed"
|
||||||
|
require "res"
|
|
@ -0,0 +1,16 @@
|
||||||
|
---@meta
|
||||||
|
|
||||||
|
---An ECS query used for obtaining Resources from the `World`.
|
||||||
|
---@class ResQuery: userdata
|
||||||
|
ResQuery = {}
|
||||||
|
|
||||||
|
---Create a new ResQuery for getting a Resource from the `World`.
|
||||||
|
---
|
||||||
|
---Use the utility function `Res(...)` to create a new query since its faster to
|
||||||
|
---write than this.
|
||||||
|
---
|
||||||
|
---@param val table|userdata The resource type to obtain.
|
||||||
|
function ResQuery:new(val) end
|
||||||
|
|
||||||
|
---An internal function used by the engine to retrieve the query result.
|
||||||
|
function ResQuery:__lyra_internal_ecs_query_result(world, entity) end
|
|
@ -0,0 +1,23 @@
|
||||||
|
---@meta
|
||||||
|
|
||||||
|
---@class View: userdata
|
||||||
|
View = {}
|
||||||
|
|
||||||
|
---Create a new view to query for components and world resources.
|
||||||
|
---
|
||||||
|
---Each parameter is a query. If you want to query entities with components, you would just use
|
||||||
|
---the component names.
|
||||||
|
---There are other queries, like `Changed` for querying for changed resources and components,
|
||||||
|
---and `Res` for querying for resources.
|
||||||
|
---
|
||||||
|
---@return View
|
||||||
|
function View.new(...) end
|
||||||
|
|
||||||
|
---@class ViewResult: userdata
|
||||||
|
ViewResult = {}
|
||||||
|
|
||||||
|
---Returns an interator over the results of the View.
|
||||||
|
---
|
||||||
|
---@generic T...
|
||||||
|
---@return fun(): EntityRef, T... iterator An iterator over the results. In the same order of the created View.
|
||||||
|
function ViewResult:iter() end
|
|
@ -73,3 +73,28 @@ function World:add_resource(resource) end
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return Handle asset An asset handle to the requested resource type.
|
---@return Handle asset An asset handle to the requested resource type.
|
||||||
function World:request_asset(path) end
|
function World:request_asset(path) end
|
||||||
|
|
||||||
|
---Get the current tick of the world.
|
||||||
|
---
|
||||||
|
---The tick is used to drive changed detection of resources and components.
|
||||||
|
---The world tick is iterated every frame.
|
||||||
|
---
|
||||||
|
---@return number
|
||||||
|
function World:get_tick() end
|
||||||
|
|
||||||
|
---Get an event reader of a specific event.
|
||||||
|
---
|
||||||
|
---@generic T
|
||||||
|
---@param event T
|
||||||
|
---@return EventReader<T>
|
||||||
|
function World:read_event(event) end
|
||||||
|
|
||||||
|
---View the world using the queries contained in a View.
|
||||||
|
---
|
||||||
|
---@param view View
|
||||||
|
---@return ViewResult
|
||||||
|
function World:view_query(view) end
|
||||||
|
|
||||||
|
--World global
|
||||||
|
---@type World
|
||||||
|
world = nil
|
|
@ -1,10 +1,4 @@
|
||||||
require "math.vec2"
|
require "math.init"
|
||||||
require "math.vec3"
|
require "ecs.init"
|
||||||
require "math.vec4"
|
|
||||||
require "math.quat"
|
|
||||||
require "math.transform"
|
|
||||||
|
|
||||||
require "ecs.window"
|
|
||||||
require "ecs.delta_time"
|
|
||||||
|
|
||||||
require "asset.handle"
|
require "asset.handle"
|
|
@ -0,0 +1,6 @@
|
||||||
|
require "math.vec2"
|
||||||
|
require "math.vec3"
|
||||||
|
require "math.vec4"
|
||||||
|
require "math.quat"
|
||||||
|
require "math.transform"
|
||||||
|
require "math.angle"
|
|
@ -53,8 +53,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
expose_comp_table_wrapper::<LuaWorldTransform>(&ctx, &globals, "WorldTransform")?;
|
expose_comp_table_wrapper::<LuaWorldTransform>(&ctx, &globals, "WorldTransform")?;
|
||||||
expose_table_wrapper::<LuaDeviceEvent>(&ctx, &globals, "DeviceEvent")?;
|
expose_table_wrapper::<LuaDeviceEvent>(&ctx, &globals, "DeviceEvent")?;
|
||||||
|
|
||||||
let dt_table = create_reflect_table::<lyra_game::DeltaTime>(&ctx)?;
|
expose_resource_table_wrapper::<lyra_game::DeltaTime>(&ctx, &globals, "DeltaTime")?;
|
||||||
globals.set("DeltaTime", dt_table)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -68,13 +67,14 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_reflect_table<T: Reflect + ResourceObject + Default + 'static>(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
|
fn expose_resource_table_wrapper<T: Reflect + ResourceObject + Default + 'static>(lua: &mlua::Lua, globals: &mlua::Table, name: &str) -> mlua::Result<()> {
|
||||||
let table = lua.create_table()?;
|
let table = lua.create_table()?;
|
||||||
table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| {
|
table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| {
|
||||||
Ok(ScriptBorrow::from_resource::<T>(None))
|
Ok(ScriptBorrow::from_resource::<T>(None))
|
||||||
})?)?;
|
})?)?;
|
||||||
|
|
||||||
Ok(table)
|
globals.set(name, table)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_reflect_comp_table<T>(lua: &mlua::Lua, name: &str) -> mlua::Result<mlua::Table>
|
fn create_reflect_comp_table<T>(lua: &mlua::Lua, name: &str) -> mlua::Result<mlua::Table>
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lyra_resource::ResourceManager;
|
||||||
use mlua::{IntoLua, ObjectLike};
|
use mlua::{IntoLua, ObjectLike};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
reflect_user_data, wrappers::{LuaResHandleToComponent, LuaWrappedEventProxy}, Error, ReflectLuaProxy, ReflectedIterator, TypeLookup, ecs::{View, ViewResult}, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
impl mlua::FromLua for ScriptEntity {
|
impl mlua::FromLua for ScriptEntity {
|
||||||
|
@ -352,5 +352,9 @@ impl mlua::UserData for ScriptWorldPtr {
|
||||||
methods.add_method("view_query", |_, this, view: mlua::UserDataRef<View>| {
|
methods.add_method("view_query", |_, this, view: mlua::UserDataRef<View>| {
|
||||||
ViewResult::new(this.clone(), &view)
|
ViewResult::new(this.clone(), &view)
|
||||||
});
|
});
|
||||||
|
methods.add_method("get_tick", |_, this, ()| {
|
||||||
|
let w = this.read();
|
||||||
|
Ok(LuaTick(w.current_tick()))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,6 @@ pub use events::*;
|
||||||
|
|
||||||
mod world_transform;
|
mod world_transform;
|
||||||
pub use world_transform::*;
|
pub use world_transform::*;
|
||||||
|
|
||||||
|
mod tick;
|
||||||
|
pub use tick::*;
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
use lyra_ecs::Tick;
|
||||||
|
use crate::lua::LuaWrapper;
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct LuaTick(pub(crate) Tick);
|
||||||
|
|
||||||
|
impl std::ops::Deref for LuaTick {
|
||||||
|
type Target = Tick;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for LuaTick {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mlua::FromLua for LuaTick {
|
||||||
|
fn from_lua(v: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
|
||||||
|
let tyname = v.type_name();
|
||||||
|
let num = v.as_number()
|
||||||
|
.ok_or(mlua::Error::FromLuaConversionError { from: tyname, to: "Tick".into(), message: None })?;
|
||||||
|
Ok(Self(Tick::from(num as u64)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mlua::IntoLua for LuaTick {
|
||||||
|
fn into_lua(self, _: &mlua::Lua) -> mlua::Result<mlua::Value> {
|
||||||
|
Ok(mlua::Value::Number(*self.0 as f64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaWrapper for LuaTick {
|
||||||
|
type Wrap = Tick;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapped_type_id() -> std::any::TypeId {
|
||||||
|
TypeId::of::<Tick>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_wrapped(self) -> Self::Wrap {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_wrapped(wrap: Self::Wrap) -> Option<Self> {
|
||||||
|
Some(Self(wrap))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue