Improve Lua ECS #30
|
@ -77,22 +77,14 @@ end
|
|||
end ]]
|
||||
|
||||
function on_update()
|
||||
--[[ ---@type number
|
||||
local dt = world:resource(DeltaTime)
|
||||
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.
|
||||
-- Although WorldTransform isn't used, I only want to
|
||||
-- modify entities with that component.
|
||||
local view = View.new(Transform, WorldTransform, Res(DeltaTime))
|
||||
local res = world:view_query(view)
|
||||
|
||||
---@param transform Transform
|
||||
---@param _wt WorldTransform
|
||||
---@param dt DeltaTime
|
||||
for entity, transform, _wt, dt in res:iter() do
|
||||
transform:translate(0, 0.15 * dt, 0)
|
||||
entity:update(transform)
|
||||
|
@ -100,8 +92,9 @@ function on_update()
|
|||
|
||||
local changed_view = View.new(Changed(Transform))
|
||||
local changed_res = world:view_query(changed_view)
|
||||
---@param transform Transform
|
||||
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
|
||||
|
||||
|
|
|
@ -72,6 +72,12 @@ impl TickTracker {
|
|||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default, PartialOrd, Ord)]
|
||||
pub struct Tick(u64);
|
||||
|
||||
impl From<u64> for Tick {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Tick {
|
||||
type Target = u64;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ function Res(resource)
|
|||
return ResQuery.new(resource)
|
||||
end
|
||||
|
||||
---Create a Changed Query of a resource or component.
|
||||
---@param resource table|userdata
|
||||
---Create a `ChangedQuery` of a resource or component.
|
||||
---@param val table|userdata
|
||||
---@return ChangedQuery
|
||||
function Changed(val)
|
||||
return ChangedQuery.new(val)
|
||||
|
|
|
@ -1,4 +1,29 @@
|
|||
---@meta
|
||||
|
||||
---An entity handle.
|
||||
---@class Entity: userdata
|
||||
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
|
||||
---@return Handle asset An asset handle to the requested resource type.
|
||||
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.vec3"
|
||||
require "math.vec4"
|
||||
require "math.quat"
|
||||
require "math.transform"
|
||||
|
||||
require "ecs.window"
|
||||
require "ecs.delta_time"
|
||||
require "math.init"
|
||||
require "ecs.init"
|
||||
|
||||
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_table_wrapper::<LuaDeviceEvent>(&ctx, &globals, "DeviceEvent")?;
|
||||
|
||||
let dt_table = create_reflect_table::<lyra_game::DeltaTime>(&ctx)?;
|
||||
globals.set("DeltaTime", dt_table)?;
|
||||
expose_resource_table_wrapper::<lyra_game::DeltaTime>(&ctx, &globals, "DeltaTime")?;
|
||||
|
||||
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()?;
|
||||
table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| {
|
||||
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>
|
||||
|
|
|
@ -10,7 +10,7 @@ use lyra_resource::ResourceManager;
|
|||
use mlua::{IntoLua, ObjectLike};
|
||||
|
||||
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 {
|
||||
|
@ -352,5 +352,9 @@ impl mlua::UserData for ScriptWorldPtr {
|
|||
methods.add_method("view_query", |_, this, view: mlua::UserDataRef<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;
|
||||
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