Compare commits
No commits in common. "20a36795dc90d76a913e72d02e3549ddf9c0d22b" and "82c13a7dd2b043e02cf8a6cd4f15bb187f9638f7" have entirely different histories.
20a36795dc
...
82c13a7dd2
|
@ -1,3 +0,0 @@
|
||||||
[submodule "lyra-scripting/elua"]
|
|
||||||
path = lyra-scripting/elua
|
|
||||||
url = git@git.seanomik.net:SeanOMik/elua.git
|
|
|
@ -432,6 +432,16 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.14.0"
|
version = "3.14.0"
|
||||||
|
@ -732,14 +742,6 @@ version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "elua"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"mlua-sys",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -1606,13 +1608,13 @@ name = "lyra-scripting"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"elua",
|
|
||||||
"itertools 0.12.0",
|
"itertools 0.12.0",
|
||||||
"lyra-ecs",
|
"lyra-ecs",
|
||||||
"lyra-game",
|
"lyra-game",
|
||||||
"lyra-reflect",
|
"lyra-reflect",
|
||||||
"lyra-resource",
|
"lyra-resource",
|
||||||
"lyra-scripting-derive",
|
"lyra-scripting-derive",
|
||||||
|
"mlua",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -1712,10 +1714,23 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mlua-sys"
|
name = "mlua"
|
||||||
version = "0.5.1"
|
version = "0.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2847b42764435201d8cbee1f517edb79c4cca4181877b90047587c89e1b7bce4"
|
checksum = "7c81f8ac20188feb5461a73eabb22a34dd09d6d58513535eb587e46bff6ba250"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"mlua-sys",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"rustc-hash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua-sys"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc29228347d6bdc9e613dc95c69df2817f755434ee0f7f3b27b57755fe238b7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
|
|
@ -15,24 +15,12 @@ end ]]
|
||||||
function on_update()
|
function on_update()
|
||||||
--print("Lua's update function was called")
|
--print("Lua's update function was called")
|
||||||
|
|
||||||
--[[ world:view(
|
|
||||||
---@param t Transform
|
|
||||||
function (t)
|
|
||||||
print("Found entity at a really cool place: " .. tostring(t))
|
|
||||||
t.translation:move_by(0, 0.001, 0)
|
|
||||||
|
|
||||||
return t
|
|
||||||
end,
|
|
||||||
Transform
|
|
||||||
) ]]
|
|
||||||
|
|
||||||
local dt = world:resource(DeltaTime)
|
local dt = world:resource(DeltaTime)
|
||||||
--print("DeltaTime was " .. tostring(dt) .. "s")
|
--print("DeltaTime was " .. tostring(dt) .. "s")
|
||||||
|
|
||||||
world:view(function (t)
|
world:view(function (t)
|
||||||
--print("Found entity at a really cool place: " .. tostring(t))
|
--print("Found entity at a really cool place: " .. tostring(t))
|
||||||
--t.translation = t.translation + (Vec3.new(0, 0.5, 0) * dt:get())
|
t.translation = t.translation + (Vec3.new(0, 0.5, 0) * dt:get())
|
||||||
t.translation:move_by(0, 0.5 * dt:get(), 0)
|
|
||||||
|
|
||||||
return t
|
return t
|
||||||
end, Transform)
|
end, Transform)
|
||||||
|
|
|
@ -84,16 +84,16 @@ async fn main() {
|
||||||
|
|
||||||
let mut resman = world.get_resource_mut::<ResourceManager>();
|
let mut resman = world.get_resource_mut::<ResourceManager>();
|
||||||
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
||||||
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
||||||
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
|
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
|
||||||
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
|
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
|
||||||
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
|
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
|
||||||
drop(resman);
|
drop(resman);
|
||||||
|
|
||||||
/* world.spawn((
|
world.spawn((
|
||||||
ModelComponent(antique_camera_model),
|
ModelComponent(antique_camera_model),
|
||||||
Transform::from_xyz(0.0, -5.0, -10.0),
|
Transform::from_xyz(0.0, -5.0, -10.0),
|
||||||
)); */
|
));
|
||||||
|
|
||||||
{
|
{
|
||||||
let cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0);
|
let cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0);
|
||||||
|
|
|
@ -342,7 +342,7 @@ impl Game {
|
||||||
.with(fmt::layer().with_writer(stdout_layer))
|
.with(fmt::layer().with_writer(stdout_layer))
|
||||||
.with(filter::Targets::new()
|
.with(filter::Targets::new()
|
||||||
// done by prefix, so it includes all lyra subpackages
|
// done by prefix, so it includes all lyra subpackages
|
||||||
.with_target("lyra", Level::TRACE)
|
.with_target("lyra", Level::DEBUG)
|
||||||
.with_target("wgpu", Level::WARN)
|
.with_target("wgpu", Level::WARN)
|
||||||
.with_default(Level::INFO))
|
.with_default(Level::INFO))
|
||||||
.init();
|
.init();
|
||||||
|
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["lua"]
|
default = ["lua"]
|
||||||
lua = ["dep:elua"]
|
lua = ["dep:mlua"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lyra-scripting-derive = { path = "lyra-scripting-derive" }
|
lyra-scripting-derive = { path = "lyra-scripting-derive" }
|
||||||
|
@ -20,8 +20,7 @@ anyhow = "1.0.77"
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
|
|
||||||
# enabled with lua feature
|
# enabled with lua feature
|
||||||
#mlua = { version = "0.9.2", features = ["lua54"], optional = true } # luajit maybe?
|
mlua = { version = "0.9.2", features = ["lua54"], optional = true } # luajit maybe?
|
||||||
elua = { path = "./elua", optional = true }
|
|
||||||
itertools = "0.12.0"
|
itertools = "0.12.0"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 2fe5dca6c4337f1528e4671d1f79464481739c61
|
|
|
@ -1,8 +1,3 @@
|
||||||
---@class Quat
|
|
||||||
---@field x number
|
|
||||||
---@field y number
|
|
||||||
---@field z number
|
|
||||||
---@field w number
|
|
||||||
Quat = { x = 0.0, y = 0.0, z = 0.0, w = 0.0 }
|
Quat = { x = 0.0, y = 0.0, z = 0.0, w = 0.0 }
|
||||||
Quat.__index = Quat
|
Quat.__index = Quat
|
||||||
Quat.__name = "Quat"
|
Quat.__name = "Quat"
|
||||||
|
@ -27,7 +22,7 @@ end
|
||||||
|
|
||||||
Quat.IDENTITY = Quat:new(0, 0, 0, 1)
|
Quat.IDENTITY = Quat:new(0, 0, 0, 1)
|
||||||
|
|
||||||
function Quat:clone()
|
function Quat:copy()
|
||||||
return Quat:new(self.x, self.y, self.z, self.w)
|
return Quat:new(self.x, self.y, self.z, self.w)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---@class Transform
|
--require("math.quat")
|
||||||
---@field translation Vec3
|
--require("math.vec3")
|
||||||
---@field rotation Quat
|
|
||||||
---@field Scale Vec3
|
|
||||||
Transform = { translation = Vec3.ZERO, rotation = Quat.IDENTITY, scale = Vec3.ONE }
|
Transform = { translation = Vec3.ZERO, rotation = Quat.IDENTITY, scale = Vec3.ONE }
|
||||||
Transform.__index = Transform
|
Transform.__index = Transform
|
||||||
Transform.__name = "Transform"
|
Transform.__name = "Transform"
|
||||||
|
@ -17,14 +16,14 @@ function Transform:new(translation, rotation, scale)
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function Transform:clone()
|
function Transform:copy()
|
||||||
return Transform:new(self.translation:clone(), self.rotation:clone(), self.scale:clone())
|
return Transform:new(self.translation:copy(), self.rotation:copy(), self.scale:copy())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a new Transform with the translation at the vec3
|
--- Creates a new Transform with the translation at the vec3
|
||||||
--- @param pos Vec3
|
--- @param pos Vec3
|
||||||
function Transform:from_vec3(pos)
|
function Transform:from_vec3(pos)
|
||||||
local t = Transform:clone() -- copy of default transform
|
local t = Transform:copy() -- copy of default transform
|
||||||
t.translation = pos
|
t.translation = pos
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
@ -82,7 +81,7 @@ end
|
||||||
--- @param alpha number
|
--- @param alpha number
|
||||||
--- @return Transform
|
--- @return Transform
|
||||||
function Transform:lerp(rhs, alpha)
|
function Transform:lerp(rhs, alpha)
|
||||||
local res = self:clone()
|
local res = self:copy()
|
||||||
res.translation = self.translation:lerp(rhs.translation, alpha)
|
res.translation = self.translation:lerp(rhs.translation, alpha)
|
||||||
res.rotation = self.rotation:lerp(rhs.rotation, alpha)
|
res.rotation = self.rotation:lerp(rhs.rotation, alpha)
|
||||||
res.scale = self.scale:lerp(rhs.scale, alpha)
|
res.scale = self.scale:lerp(rhs.scale, alpha)
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
---@class Vec3
|
|
||||||
---@field x number
|
|
||||||
---@field y number
|
|
||||||
---@field z number
|
|
||||||
Vec3 = { x = 0.0, y = 0.0, z = 0.0 }
|
Vec3 = { x = 0.0, y = 0.0, z = 0.0 }
|
||||||
Vec3.__index = Vec3
|
Vec3.__index = Vec3
|
||||||
Vec3.__name = "Vec3"
|
Vec3.__name = "Vec3"
|
||||||
|
@ -22,9 +18,7 @@ function Vec3:new(x, y, z)
|
||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
|
|
||||||
---Creates a copy of self
|
function Vec3:copy()
|
||||||
---@return Vec3
|
|
||||||
function Vec3:clone()
|
|
||||||
return Vec3:new(self.x, self.y, self.z)
|
return Vec3:new(self.x, self.y, self.z)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -55,10 +49,9 @@ Vec3.ZERO = Vec3:new(0, 0, 0)
|
||||||
Vec3.ONE = Vec3:new(1, 1, 1)
|
Vec3.ONE = Vec3:new(1, 1, 1)
|
||||||
|
|
||||||
--- Computes the absolute value of `self`.
|
--- Computes the absolute value of `self`.
|
||||||
|
---@return Vec3
|
||||||
function Vec3:abs()
|
function Vec3:abs()
|
||||||
self.x = math.abs(self.x)
|
return Vec3:new(math.abs(self.x), math.abs(self.y), math.abs(self.z))
|
||||||
self.y = math.abs(self.y)
|
|
||||||
self.z = math.abs(self.z)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Computes the length of `self`.
|
--- Computes the length of `self`.
|
||||||
|
@ -67,16 +60,6 @@ function Vec3:length()
|
||||||
return math.sqrt(self:dot(self))
|
return math.sqrt(self:dot(self))
|
||||||
end
|
end
|
||||||
|
|
||||||
---Moves `self` by the provided coordinates
|
|
||||||
---@param x number
|
|
||||||
---@param y number
|
|
||||||
---@param z number
|
|
||||||
function Vec3:move_by(x, y, z)
|
|
||||||
self.x = self.x + x
|
|
||||||
self.y = self.y + y
|
|
||||||
self.z = self.z + z
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Computes the dot product of `self` and `rhs`.
|
--- Computes the dot product of `self` and `rhs`.
|
||||||
---@param rhs Vec3
|
---@param rhs Vec3
|
||||||
---@return number
|
---@return number
|
||||||
|
@ -97,12 +80,11 @@ function Vec3:min(rhs)
|
||||||
return Vec3:new(x, y, z)
|
return Vec3:new(x, y, z)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Modifies `self` to be normalized to a length 1.
|
--- Returns `self` normalized to a length 1.
|
||||||
|
---@return unknown
|
||||||
function Vec3:normalize()
|
function Vec3:normalize()
|
||||||
local len_recip = 1.0 / self:length()
|
local len_recip = 1.0 / self:length()
|
||||||
self.x = self.x * len_recip
|
return self * len_recip
|
||||||
self.y = self.y * len_recip
|
|
||||||
self.z = self.z * len_recip
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Calculates the linear iterpolation between `self` and `rhs` based on the `alpha`.
|
--- Calculates the linear iterpolation between `self` and `rhs` based on the `alpha`.
|
||||||
|
@ -115,48 +97,40 @@ function Vec3:lerp(rhs, alpha)
|
||||||
-- ensure alpha is [0, 1]
|
-- ensure alpha is [0, 1]
|
||||||
local alpha = math.max(0, math.min(1, alpha))
|
local alpha = math.max(0, math.min(1, alpha))
|
||||||
|
|
||||||
local res = self:clone()
|
local res = self:copy()
|
||||||
res = res + ((rhs - res) * alpha)
|
res = res + ((rhs - res) * alpha)
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
function Vec3:__add(rhs)
|
function Vec3:__add(rhs)
|
||||||
if type(rhs) == "Vec3" then
|
return Vec3:new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
|
||||||
return Vec3:new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
|
|
||||||
else
|
|
||||||
return Vec3:new(self.x + rhs, self.y + rhs, self.z + rhs)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Vec3:__sub(rhs)
|
function Vec3:__sub(rhs)
|
||||||
if type(rhs) == "Vec3" then
|
return Vec3:new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
|
||||||
return Vec3:new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
|
|
||||||
else
|
|
||||||
return Vec3:new(self.x - rhs, self.y - rhs, self.z - rhs)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Vec3:__mul(rhs)
|
function Vec3:__mul(rhs)
|
||||||
if type(rhs) == "Vec3" then
|
if type(rhs) == "number" then
|
||||||
return Vec3:new(self.x * rhs.x, self.y * rhs.y, self.z * rhs.z)
|
|
||||||
else
|
|
||||||
return Vec3:new(self.x * rhs, self.y * rhs, self.z * rhs)
|
return Vec3:new(self.x * rhs, self.y * rhs, self.z * rhs)
|
||||||
|
else
|
||||||
|
return Vec3:new(self.x * rhs.x, self.y * rhs.y, self.z * rhs.z)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Vec3:__div(rhs)
|
function Vec3:__div(rhs)
|
||||||
if type(rhs) == "Vec3" then
|
if type(rhs) == "number" then
|
||||||
return Vec3:new(self.x / rhs.x, self.y / rhs.y, self.z / rhs.z)
|
|
||||||
else
|
|
||||||
return Vec3:new(self.x / rhs, self.y / rhs, self.z / rhs)
|
return Vec3:new(self.x / rhs, self.y / rhs, self.z / rhs)
|
||||||
|
else
|
||||||
|
return Vec3:new(self.x / rhs.x, self.y / rhs.y, self.z / rhs.z)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Vec3:__idiv(rhs)
|
function Vec3:__idiv(rhs)
|
||||||
if type(rhs) == "Vec3" then
|
if type(rhs) == "number" then
|
||||||
return Vec3:new(self.x // rhs.x, self.y // rhs.y, self.z // rhs.z)
|
|
||||||
else
|
|
||||||
return Vec3:new(self.x // rhs, self.y // rhs, self.z // rhs)
|
return Vec3:new(self.x // rhs, self.y // rhs, self.z // rhs)
|
||||||
|
else
|
||||||
|
return Vec3:new(self.x // rhs.x, self.y // rhs.y, self.z // rhs.z)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@ use crate::ScriptWorldPtr;
|
||||||
pub enum ScriptError {
|
pub enum ScriptError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
MluaError(elua::Error),
|
MluaError(mlua::Error),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(anyhow::Error),
|
Other(anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
impl From<elua::Error> for ScriptError {
|
impl From<mlua::Error> for ScriptError {
|
||||||
fn from(value: elua::Error) -> Self {
|
fn from(value: mlua::Error) -> Self {
|
||||||
ScriptError::MluaError(value)
|
ScriptError::MluaError(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,9 +134,9 @@ impl Iterator for DynamicViewIter {
|
||||||
|
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
pub struct ReflectedItem<'a> {
|
pub struct ReflectedItem<'a> {
|
||||||
//pub proxy: &'a ReflectLuaProxy,
|
pub proxy: &'a ReflectLuaProxy,
|
||||||
pub comp_ptr: NonNull<u8>,
|
pub comp_ptr: NonNull<u8>,
|
||||||
pub comp_val: elua::Value<'a>,
|
pub comp_ud: mlua::AnyUserData<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
|
@ -153,11 +153,7 @@ pub struct ReflectedIterator {
|
||||||
|
|
||||||
impl ReflectedIterator {
|
impl ReflectedIterator {
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
pub fn next_lua<'a>(&mut self, lua: &'a elua::State) -> Option<ReflectedRow<'a>> {
|
pub fn next_lua<'a>(&mut self, lua: &'a mlua::Lua) -> Option<ReflectedRow<'a>> {
|
||||||
use elua::AsLua;
|
|
||||||
|
|
||||||
use super::ReflectedLuaTableProxy;
|
|
||||||
|
|
||||||
|
|
||||||
let n = self.dyn_view.next();
|
let n = self.dyn_view.next();
|
||||||
|
|
||||||
|
@ -176,20 +172,17 @@ impl ReflectedIterator {
|
||||||
|
|
||||||
let reg_type = reflected_components.get_type(id)
|
let reg_type = reflected_components.get_type(id)
|
||||||
.expect("Requested type was not found in TypeRegistry");
|
.expect("Requested type was not found in TypeRegistry");
|
||||||
let value = if let Some(proxy) = reg_type.get_data::<ReflectLuaProxy>() {
|
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
||||||
(proxy.fn_as_uservalue)(lua, d.ptr).unwrap()
|
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
||||||
.as_lua(lua).unwrap()
|
|
||||||
} else if let Some(proxy) = reg_type.get_data::<ReflectedLuaTableProxy>() {
|
let userdata = (proxy.fn_as_uservalue)(lua, d.ptr).unwrap();
|
||||||
(proxy.fn_as_table)(lua, d.ptr.cast()).unwrap()
|
|
||||||
.as_lua(lua).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("Type does not have ReflectLuaProxy or ReflectedLuaTableProxy as a TypeData");
|
|
||||||
};
|
|
||||||
|
|
||||||
dynamic_row.push(ReflectedItem {
|
dynamic_row.push(ReflectedItem {
|
||||||
|
proxy,
|
||||||
comp_ptr: d.ptr,
|
comp_ptr: d.ptr,
|
||||||
comp_val: value
|
comp_ud: userdata
|
||||||
});
|
});
|
||||||
|
//dynamic_row.push(( (proxy, d.ptr), userdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
let row = ReflectedRow {
|
let row = ReflectedRow {
|
||||||
|
|
|
@ -2,7 +2,6 @@ pub mod dynamic_iter;
|
||||||
pub use dynamic_iter::*;
|
pub use dynamic_iter::*;
|
||||||
|
|
||||||
pub mod world;
|
pub mod world;
|
||||||
use elua::FromLua;
|
|
||||||
pub use world::*;
|
pub use world::*;
|
||||||
|
|
||||||
pub mod script;
|
pub mod script;
|
||||||
|
@ -20,14 +19,19 @@ pub use proxy::*;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
pub use system::*;
|
pub use system::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
use std::{any::TypeId, sync::Mutex};
|
use std::{any::TypeId, sync::Mutex};
|
||||||
|
|
||||||
use lyra_ecs::{
|
use lyra_ecs::{
|
||||||
Component, ComponentInfo, DynamicBundle, World
|
DynamicBundle, World,
|
||||||
};
|
};
|
||||||
use lyra_reflect::{FromType, Reflect, TypeRegistry};
|
use lyra_reflect::{FromType, Reflect, TypeRegistry};
|
||||||
|
|
||||||
pub type LuaContext = Mutex<elua::State>;
|
use mlua::{AnyUserDataExt, Lua};
|
||||||
|
|
||||||
|
pub type LuaContext = Mutex<mlua::Lua>;
|
||||||
|
|
||||||
pub const FN_NAME_INTERNAL_REFLECT_TYPE: &str = "__lyra_internal_reflect_type";
|
pub const FN_NAME_INTERNAL_REFLECT_TYPE: &str = "__lyra_internal_reflect_type";
|
||||||
pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect";
|
pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect";
|
||||||
|
@ -36,28 +40,21 @@ use crate::{ScriptBorrow, ScriptDynamicBundle};
|
||||||
|
|
||||||
/// A trait used for registering a Lua type with the world.
|
/// A trait used for registering a Lua type with the world.
|
||||||
pub trait RegisterLuaType {
|
pub trait RegisterLuaType {
|
||||||
/// Register a type to Lua that **is not wrapped**.
|
/// Register a type to lua that **is not wrapped**.
|
||||||
fn register_lua_type<'a, T>(&mut self)
|
fn register_lua_type<'a, T>(&mut self)
|
||||||
where
|
where
|
||||||
T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata;
|
T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData;
|
||||||
|
|
||||||
/// Registers a type to Lua that is wrapped another type.
|
/// Registers a wrapped lua type.
|
||||||
/// This would be used for something like `UserdataRef<T>`.
|
|
||||||
fn register_lua_wrapper<'a, W>(&mut self)
|
fn register_lua_wrapper<'a, W>(&mut self)
|
||||||
where
|
where
|
||||||
W: Reflect + LuaProxy + LuaWrapper + Clone + elua::FromLua<'a> + elua::Userdata;
|
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData;
|
||||||
|
|
||||||
/// Registers a type to Lua that implements [`elua::TableProxy`]
|
|
||||||
fn register_lua_table_proxy<'a, T, W>(&mut self)
|
|
||||||
where
|
|
||||||
T: elua::TableProxy + 'static,
|
|
||||||
W: Component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterLuaType for World {
|
impl RegisterLuaType for World {
|
||||||
fn register_lua_type<'a, T>(&mut self)
|
fn register_lua_type<'a, T>(&mut self)
|
||||||
where
|
where
|
||||||
T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata
|
T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData
|
||||||
{
|
{
|
||||||
let mut registry = self.get_resource_mut::<TypeRegistry>();
|
let mut registry = self.get_resource_mut::<TypeRegistry>();
|
||||||
|
|
||||||
|
@ -70,64 +67,44 @@ impl RegisterLuaType for World {
|
||||||
|
|
||||||
fn register_lua_wrapper<'a, W>(&mut self)
|
fn register_lua_wrapper<'a, W>(&mut self)
|
||||||
where
|
where
|
||||||
W: Reflect + LuaProxy + LuaWrapper + Clone + elua::FromLua<'a> + elua::Userdata
|
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData
|
||||||
{
|
{
|
||||||
let mut registry = self.get_resource_mut::<TypeRegistry>();
|
let mut registry = self.get_resource_mut::<TypeRegistry>();
|
||||||
|
|
||||||
let reg_type = registry.get_type_or_default(W::wrapped_type_id());
|
let reg_type = registry.get_type_or_default(W::wrapped_type_id());
|
||||||
reg_type.add_data(<ReflectLuaProxy as FromType<W>>::from_type());
|
reg_type.add_data(<ReflectLuaProxy as FromType<W>>::from_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_lua_table_proxy<'a, T, C>(&mut self)
|
|
||||||
where
|
|
||||||
T: elua::TableProxy + 'static,
|
|
||||||
C: Component
|
|
||||||
{
|
|
||||||
let mut registry = self.get_resource_mut::<TypeRegistry>();
|
|
||||||
|
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
let reg_type = registry.get_type_or_default(TypeId::of::<C>());
|
|
||||||
reg_type.add_data(<ReflectedLuaTableProxy as FromType<T>>::from_type());
|
|
||||||
drop(registry);
|
|
||||||
|
|
||||||
let mut lookup = self.get_resource_or_else::<LuaTableProxyLookup, _>(LuaTableProxyLookup::default);
|
|
||||||
lookup.typeid_from_name.insert(T::table_name(), TypeId::of::<C>());
|
|
||||||
|
|
||||||
let mut info = ComponentInfo::new::<C>();
|
|
||||||
lookup.comp_info_from_name.insert(T::table_name(), info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for ScriptBorrow {
|
impl<'lua> mlua::FromLua<'lua> for ScriptBorrow {
|
||||||
fn from_lua(_: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result<Self> {
|
fn from_lua(value: mlua::Value<'lua>, _lua: &'lua Lua) -> mlua::Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
elua::Value::Userdata(ud) => Ok(ud.as_ref::<Self>()?.clone()),
|
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLuaVec<'lua> for ScriptBorrow {
|
impl mlua::UserData for ScriptBorrow {}
|
||||||
fn from_lua_value_vec(state: &'lua elua::State, mut values: elua::ValueVec<'lua>) -> elua::Result<Self> {
|
|
||||||
if let Some(v) = values.pop_front() {
|
|
||||||
ScriptBorrow::from_lua(state, v)
|
|
||||||
} else {
|
|
||||||
Err(elua::Error::Nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl elua::Userdata for ScriptBorrow {
|
pub fn reflect_user_data(ud: &mlua::AnyUserData) -> ScriptBorrow {
|
||||||
fn name() -> String {
|
ud.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
|
||||||
"ScriptBorrow".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reflect_user_data(ud: &elua::AnyUserdata) -> ScriptBorrow {
|
|
||||||
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
|
|
||||||
.expect("Type does not implement '__internal_reflect' properly")
|
.expect("Type does not implement '__internal_reflect' properly")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl mlua::UserData for ScriptDynamicBundle {
|
||||||
|
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new())));
|
||||||
|
|
||||||
|
methods.add_method_mut("push", |_, this, (comp,): (mlua::AnyUserData,)| {
|
||||||
|
let script_brw = comp.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
||||||
|
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
||||||
|
|
||||||
|
let refl_data = script_brw.data.unwrap();
|
||||||
|
let refl_data = refl_data.as_ref();
|
||||||
|
reflect.bundle_insert(&mut this.0, refl_data);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
let ctx = ctx.lock().unwrap();
|
let ctx = ctx.lock().unwrap();
|
||||||
|
|
||||||
let globals = ctx.globals()?;
|
let globals = ctx.globals();
|
||||||
globals.set("World", ctx.create_proxy::<ScriptWorldPtr>()?)?;
|
globals.set("World", ctx.create_proxy::<ScriptWorldPtr>()?)?;
|
||||||
globals.set("DynamicBundle", ctx.create_proxy::<ScriptDynamicBundle>()?)?;
|
globals.set("DynamicBundle", ctx.create_proxy::<ScriptDynamicBundle>()?)?;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use elua::{TableProxy, Userdata};
|
|
||||||
use lyra_ecs::World;
|
use lyra_ecs::World;
|
||||||
use lyra_game::math::{self, Quat, Transform, Vec3};
|
use lyra_game::math;
|
||||||
use crate::ScriptData;
|
use crate::ScriptData;
|
||||||
use crate::lua::RegisterLuaType;
|
use crate::lua::RegisterLuaType;
|
||||||
|
use crate::lua::wrappers::{LuaVec3, LuaTransform};
|
||||||
|
|
||||||
use crate::{ScriptApiProvider, lua::LuaContext};
|
use crate::{ScriptApiProvider, lua::LuaContext};
|
||||||
|
|
||||||
|
@ -13,31 +13,26 @@ impl ScriptApiProvider for LyraMathApiProvider {
|
||||||
type ScriptContext = LuaContext;
|
type ScriptContext = LuaContext;
|
||||||
|
|
||||||
fn prepare_world(&mut self, world: &mut World) {
|
fn prepare_world(&mut self, world: &mut World) {
|
||||||
// TODO
|
world.register_lua_wrapper::<LuaVec3>();
|
||||||
/* world.register_lua_wrapper::<LuaVec3>();
|
world.register_lua_wrapper::<LuaTransform>();
|
||||||
world.register_lua_wrapper::<LuaTransform>(); */
|
|
||||||
world.register_lua_table_proxy::<LuaVec3, Vec3>();
|
|
||||||
world.register_lua_table_proxy::<LuaQuat, Quat>();
|
|
||||||
world.register_lua_table_proxy::<LuaTransform, Transform>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_api(&mut self, _data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
let ctx = ctx.lock().unwrap();
|
let ctx = ctx.lock().unwrap();
|
||||||
|
|
||||||
let bytes = include_bytes!("../../../scripts/lua/math/vec3.lua");
|
/* let bytes = include_bytes!("../../../scripts/lua/math/vec3.lua");
|
||||||
ctx.load("lyra/math/vec2.lua", bytes.as_slice())?.execute(())?;
|
ctx.load(bytes.to_vec()).exec()?;
|
||||||
|
|
||||||
let bytes = include_bytes!("../../../scripts/lua/math/quat.lua");
|
let bytes = include_bytes!("../../../scripts/lua/math/quat.lua");
|
||||||
ctx.load("lyra/math/quat.lua", bytes.as_slice())?.execute(())?;
|
ctx.load(bytes.to_vec()).exec()?;
|
||||||
|
|
||||||
let bytes = include_bytes!("../../../scripts/lua/math/transform.lua");
|
let bytes = include_bytes!("../../../scripts/lua/math/transform.lua");
|
||||||
ctx.load("lyra/math/transform.lua", bytes.as_slice())?.execute(())?;
|
ctx.load(bytes.to_vec()).exec()?; */
|
||||||
|
|
||||||
// TODO
|
let globals = ctx.globals();
|
||||||
//let globals = ctx.globals()?;
|
globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
|
||||||
//globals.set("Vec3", elua::Proxy::<LuaVec3>::from(LuaVec3(Vec3::ZERO)))?;
|
globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
|
||||||
//globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
|
//globals.set("Vec3", LuaVec3(math::Vec3::ZERO).into_lua(&ctx)?)?;
|
||||||
//globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -51,94 +46,6 @@ impl ScriptApiProvider for LyraMathApiProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct LuaVec3(Vec3);
|
|
||||||
|
|
||||||
impl TableProxy for LuaVec3 {
|
|
||||||
fn from_table<'a>(_: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
|
|
||||||
let x: f32 = table.get("x")?;
|
|
||||||
let y: f32 = table.get("y")?;
|
|
||||||
let z: f32 = table.get("z")?;
|
|
||||||
|
|
||||||
Ok(LuaVec3(Vec3 {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
z,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
|
|
||||||
let globals = state.globals()?;
|
|
||||||
let vec3: elua::Table = globals.get("Vec3")?;
|
|
||||||
let new_fn: elua::Function = vec3.get("new")?;
|
|
||||||
new_fn.exec((vec3, self.0.x, self.0.y, self.0.z))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_name() -> String {
|
|
||||||
"Vec3".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct LuaQuat(Quat);
|
|
||||||
|
|
||||||
impl TableProxy for LuaQuat {
|
|
||||||
fn from_table<'a>(_: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
|
|
||||||
let x: f32 = table.get("x")?;
|
|
||||||
let y: f32 = table.get("y")?;
|
|
||||||
let z: f32 = table.get("z")?;
|
|
||||||
let w: f32 = table.get("w")?;
|
|
||||||
|
|
||||||
Ok(LuaQuat(Quat::from_xyzw(x, y, z, w)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
|
|
||||||
let globals = state.globals()?;
|
|
||||||
let quat: elua::Table = globals.get("Quat")?;
|
|
||||||
let new_fn: elua::Function = quat.get("new")?;
|
|
||||||
new_fn.exec((quat, self.0.x, self.0.y, self.0.z, self.0.w))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_name() -> String {
|
|
||||||
"Quat".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct LuaTransform(Transform);
|
|
||||||
|
|
||||||
impl TableProxy for LuaTransform {
|
|
||||||
fn from_table<'a>(lua: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
|
|
||||||
let translation: elua::Table = table.get("translation")?;
|
|
||||||
let rotation: elua::Table = table.get("rotation")?;
|
|
||||||
let scale: elua::Table = table.get("scale")?;
|
|
||||||
|
|
||||||
let translation = LuaVec3::from_table(lua, translation)?;
|
|
||||||
let rotation = LuaQuat::from_table(lua, rotation)?;
|
|
||||||
let scale = LuaVec3::from_table(lua, scale)?;
|
|
||||||
|
|
||||||
Ok(LuaTransform(Transform::new(translation.0, rotation.0, scale.0)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
|
|
||||||
let globals = state.globals()?;
|
|
||||||
let transform: elua::Table = globals.get("Transform")?;
|
|
||||||
let new_fn: elua::Function = transform.get("new")?;
|
|
||||||
|
|
||||||
let translation = LuaVec3(self.0.translation).as_table(state)?;
|
|
||||||
let rotation = LuaQuat(self.0.rotation).as_table(state)?;
|
|
||||||
let scale = LuaVec3(self.0.scale).as_table(state)?;
|
|
||||||
|
|
||||||
new_fn.exec((transform, translation, rotation, scale))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_name() -> String {
|
|
||||||
"Transform".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #[derive(Clone, Copy, PartialEq, Debug, lyra_reflect::Reflect)]
|
/* #[derive(Clone, Copy, PartialEq, Debug, lyra_reflect::Reflect)]
|
||||||
pub struct LuaVec3(#[reflect(skip)] math::Vec3);
|
pub struct LuaVec3(#[reflect(skip)] math::Vec3);
|
||||||
|
|
||||||
|
|
|
@ -17,46 +17,47 @@ use crate::{ScriptApiProvider, ScriptData};
|
||||||
pub struct UtilityApiProvider;
|
pub struct UtilityApiProvider;
|
||||||
|
|
||||||
impl ScriptApiProvider for UtilityApiProvider {
|
impl ScriptApiProvider for UtilityApiProvider {
|
||||||
type ScriptContext = Mutex<elua::State>;
|
type ScriptContext = Mutex<mlua::Lua>;
|
||||||
|
|
||||||
fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
let ctx = ctx.lock().unwrap();
|
let ctx = ctx.lock().unwrap();
|
||||||
|
|
||||||
//fn printf(lua: &elua::State, (mut text, formats): (String, elua::Variadic<elua::Value>)) -> elua::Result<()> {
|
fn printf(lua: &mlua::Lua, (mut text, formats): (String, mlua::Variadic<mlua::Value>)) -> mlua::Result<()> {
|
||||||
let printf = |lua: &elua::State, (mut text, formats): (String, elua::Variadic<elua::Value>)| {
|
|
||||||
let mut formatted = String::new();
|
let mut formatted = String::new();
|
||||||
let mut arg_num = 0;
|
let mut arg_num = 0;
|
||||||
|
|
||||||
while let Some(start) = text.find("{}") {
|
while let Some(start) = text.find("{}") {
|
||||||
let val_str = match formats.get(arg_num) {
|
let val_str = match formats.get(arg_num) {
|
||||||
Some(v) => match v {
|
Some(v) => match v {
|
||||||
elua::Value::Nil => "nil".to_string(),
|
mlua::Value::Nil => "nil".to_string(),
|
||||||
elua::Value::Boolean(b) => b.to_string(),
|
mlua::Value::Boolean(b) => b.to_string(),
|
||||||
elua::Value::Number(n) => n.to_string(),
|
mlua::Value::LightUserData(_) => {
|
||||||
elua::Value::String(s) => s.clone(),
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of LightUserData")));
|
||||||
elua::Value::Table(_) => {
|
|
||||||
return Err(elua::Error::runtime("unable to get string representation of Table"));
|
|
||||||
},
|
},
|
||||||
elua::Value::Function(_) => {
|
mlua::Value::Integer(i) => i.to_string(),
|
||||||
return Err(elua::Error::runtime("unable to get string representation of Function"));
|
mlua::Value::Number(n) => n.to_string(),
|
||||||
|
mlua::Value::String(s) => s.to_str().unwrap().to_string(),
|
||||||
|
mlua::Value::Table(_) => {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Table")));
|
||||||
},
|
},
|
||||||
elua::Value::Thread(_) => {
|
mlua::Value::Function(_) => {
|
||||||
return Err(elua::Error::runtime("unable to get string representation of Thread"));
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Function")));
|
||||||
},
|
},
|
||||||
elua::Value::Userdata(ud) => {
|
mlua::Value::Thread(_) => {
|
||||||
if let Ok(tos) = ud.get::<_, elua::Function>(elua::MetaMethod::ToString) {
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Thread")));
|
||||||
tos.exec::<_, String>(())?
|
},
|
||||||
|
mlua::Value::UserData(ud) => {
|
||||||
|
let metatable = ud.get_metatable()?;
|
||||||
|
if let Ok(tos) = metatable.get::<mlua::Function>(mlua::MetaMethod::ToString) {
|
||||||
|
tos.call::<_, String>((ud.clone(),))?
|
||||||
} else {
|
} else {
|
||||||
return Err(elua::Error::runtime("UserData does not implement MetaMethod '__tostring'"));
|
return Err(mlua::Error::RuntimeError(format!("UserData does not implement MetaMethod '__tostring'")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elua::Value::None => "None".to_string(),
|
mlua::Value::Error(e) => e.to_string(),
|
||||||
elua::Value::Multi(v) => {
|
|
||||||
return Err(elua::Error::runtime("unable to get string representation of ValueVec"));
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let got_args = arg_num;// - 1;
|
let got_args = arg_num;
|
||||||
|
|
||||||
// continue searching for {} to get the number of format spots for the error message.
|
// continue searching for {} to get the number of format spots for the error message.
|
||||||
while let Some(start) = text.find("{}") {
|
while let Some(start) = text.find("{}") {
|
||||||
|
@ -64,15 +65,13 @@ impl ScriptApiProvider for UtilityApiProvider {
|
||||||
arg_num += 1;
|
arg_num += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(elua::Error::BadArgument {
|
return Err(mlua::Error::BadArgument {
|
||||||
func: Some("printf".to_string()),
|
to: Some("printf".to_string()),
|
||||||
arg_index: 2,
|
pos: 2,
|
||||||
arg_name: Some("fmt...".to_string()),
|
name: Some("...".to_string()),
|
||||||
error: Arc::new(elua::Error::Runtime(format!(
|
cause: Arc::new(mlua::Error::RuntimeError(format!("not enough args \
|
||||||
"not enough args \
|
|
||||||
given for the amount of format areas in the string. Expected {}, \
|
given for the amount of format areas in the string. Expected {}, \
|
||||||
got {}.", arg_num, got_args
|
got {}.", arg_num, got_args)))
|
||||||
)))
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -85,31 +84,29 @@ impl ScriptApiProvider for UtilityApiProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg_num < formats.len() {
|
if arg_num < formats.len() {
|
||||||
return Err(elua::Error::BadArgument {
|
return Err(mlua::Error::BadArgument {
|
||||||
func: Some("printf".to_string()),
|
to: Some("printf".to_string()),
|
||||||
arg_index: 2,
|
pos: 2,
|
||||||
arg_name: Some("fmt...".to_string()),
|
name: Some("...".to_string()),
|
||||||
error: Arc::new(elua::Error::Runtime(format!(
|
cause: Arc::new(mlua::Error::RuntimeError(format!("got more args \
|
||||||
"got more args \
|
than format areas in the string. Expected {}, got {}.", formats.len(), arg_num)))
|
||||||
than format areas in the string. Expected {}, got {}.", formats.len(), arg_num
|
|
||||||
)))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted = format!("{}{}", formatted, text);
|
formatted = format!("{}{}", formatted, text);
|
||||||
|
|
||||||
lua.globals()?
|
lua.globals()
|
||||||
.get::<_, elua::Function>("print")?
|
.get::<_, mlua::Function>("print")?
|
||||||
.exec::<_, ()>(formatted)?;
|
.call::<_, ()>(formatted)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
}
|
||||||
|
|
||||||
let script_name_reg = ctx.registry_insert(data.name.clone())?;
|
let script_name_reg = ctx.create_registry_value(data.name.clone())?;
|
||||||
|
|
||||||
let printf_func = ctx.create_function(printf)?;
|
let printf_func = ctx.create_function(printf)?;
|
||||||
let print_func = ctx.create_function(move |lua, text: String| {
|
let print_func = ctx.create_function(move |lua, text: String| {
|
||||||
let name = lua.registry_get::<String>(script_name_reg)?;
|
let name = lua.registry_value::<String>(&script_name_reg)?;
|
||||||
let _span = debug_span!("lua", script = &name).entered();
|
let _span = debug_span!("lua", script = &name).entered();
|
||||||
|
|
||||||
debug!(target: "lyra_scripting::lua", "{}", text);
|
debug!(target: "lyra_scripting::lua", "{}", text);
|
||||||
|
@ -117,7 +114,7 @@ impl ScriptApiProvider for UtilityApiProvider {
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let globals = ctx.globals()?;
|
let globals = ctx.globals();
|
||||||
globals.set("printf", printf_func)?;
|
globals.set("printf", printf_func)?;
|
||||||
globals.set("print", print_func)?;
|
globals.set("print", print_func)?;
|
||||||
|
|
||||||
|
|
|
@ -1,51 +1,46 @@
|
||||||
use std::{any::TypeId, collections::HashMap, ptr::NonNull};
|
use std::{any::TypeId, ptr::NonNull};
|
||||||
|
|
||||||
use elua::{FromLua, TableProxy};
|
|
||||||
use lyra_ecs::{ComponentInfo, DynamicBundle};
|
|
||||||
use lyra_reflect::{Reflect, FromType};
|
use lyra_reflect::{Reflect, FromType};
|
||||||
|
|
||||||
use crate::{ScriptBorrow, ScriptDynamicBundle};
|
use crate::ScriptDynamicBundle;
|
||||||
|
|
||||||
use super::FN_NAME_INTERNAL_REFLECT;
|
|
||||||
|
|
||||||
pub trait LuaWrapper {
|
pub trait LuaWrapper {
|
||||||
/// The type id of the wrapped type.
|
/// The type id of the wrapped type.
|
||||||
fn wrapped_type_id() -> TypeId;
|
fn wrapped_type_id() -> TypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<'lua>(
|
fn as_lua_value<'lua>(
|
||||||
lua: &'lua elua::State,
|
lua: &'lua mlua::Lua,
|
||||||
this: &dyn Reflect,
|
this: &dyn Reflect,
|
||||||
) -> elua::Result<elua::AnyUserdata<'lua>>;
|
) -> mlua::Result<mlua::AnyUserData<'lua>>;
|
||||||
|
|
||||||
fn apply(
|
fn apply(
|
||||||
lua: &elua::State,
|
lua: &mlua::Lua,
|
||||||
this: &mut dyn Reflect,
|
this: &mut dyn Reflect,
|
||||||
apply: &elua::AnyUserdata,
|
apply: &mlua::AnyUserData,
|
||||||
) -> elua::Result<()>;
|
) -> mlua::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> LuaProxy for T
|
impl<'a, T> LuaProxy for T
|
||||||
where
|
where
|
||||||
T: Reflect + Clone + elua::FromLua<'a> + elua::Userdata
|
T: Reflect + Clone + mlua::FromLua<'a> + mlua::UserData
|
||||||
{
|
{
|
||||||
fn as_lua_value<'lua>(
|
fn as_lua_value<'lua>(
|
||||||
lua: &'lua elua::State,
|
lua: &'lua mlua::Lua,
|
||||||
this: &dyn Reflect,
|
this: &dyn Reflect,
|
||||||
) -> elua::Result<elua::AnyUserdata<'lua>> {
|
) -> mlua::Result<mlua::AnyUserData<'lua>> {
|
||||||
let this = this.as_any().downcast_ref::<T>().unwrap();
|
let this = this.as_any().downcast_ref::<T>().unwrap();
|
||||||
lua.create_userdata(this.clone())
|
lua.create_userdata(this.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(
|
fn apply(
|
||||||
_: &elua::State,
|
_lua: &mlua::Lua,
|
||||||
this: &mut dyn Reflect,
|
this: &mut dyn Reflect,
|
||||||
apply: &elua::AnyUserdata,
|
apply: &mlua::AnyUserData,
|
||||||
) -> elua::Result<()> {
|
) -> mlua::Result<()> {
|
||||||
let this = this.as_any_mut().downcast_mut::<T>().unwrap();
|
let this = this.as_any_mut().downcast_mut::<T>().unwrap();
|
||||||
let apply = apply.as_ref::<T>()?;
|
let apply = apply.borrow::<T>()?;
|
||||||
|
|
||||||
*this = apply.clone();
|
*this = apply.clone();
|
||||||
|
|
||||||
|
@ -53,66 +48,24 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that is used for retrieving rust type ids of types that implement `TableProxy`.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LuaTableProxyLookup {
|
|
||||||
pub(crate) typeid_from_name: HashMap<String, TypeId>,
|
|
||||||
pub(crate) comp_info_from_name: HashMap<String, ComponentInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A struct used for converting types that implement `TableProxy` to and from Lua.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ReflectedLuaTableProxy {
|
|
||||||
pub table_name: String,
|
|
||||||
pub fn_as_table:
|
|
||||||
for<'a> fn(lua: &'a elua::State, this_ptr: NonNull<()>) -> elua::Result<elua::Table<'a>>,
|
|
||||||
pub fn_apply: for<'a> fn(
|
|
||||||
lua: &'a elua::State,
|
|
||||||
this_ptr: NonNull<()>,
|
|
||||||
table: &'a elua::Table<'a>,
|
|
||||||
) -> elua::Result<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> FromType<T> for ReflectedLuaTableProxy
|
|
||||||
where
|
|
||||||
T: TableProxy
|
|
||||||
{
|
|
||||||
fn from_type() -> Self {
|
|
||||||
Self {
|
|
||||||
table_name: T::table_name(),
|
|
||||||
fn_as_table: |lua, this| -> elua::Result<elua::Table> {
|
|
||||||
let this = unsafe { this.cast::<T>().as_ref() };
|
|
||||||
this.as_table(lua)
|
|
||||||
},
|
|
||||||
fn_apply: |lua, ptr, table| {
|
|
||||||
let this = unsafe { ptr.cast::<T>().as_mut() };
|
|
||||||
let tbl = T::from_table(lua, table.clone())?;
|
|
||||||
*this = tbl;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A struct used for converting types that implement `LuaProxy` to and from Lua.
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ReflectLuaProxy {
|
pub struct ReflectLuaProxy {
|
||||||
pub fn_as_uservalue:
|
pub fn_as_uservalue:
|
||||||
for<'a> fn(lua: &'a elua::State, this_ptr: NonNull<u8>) -> elua::Result<elua::AnyUserdata<'a>>,
|
for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<u8>) -> mlua::Result<mlua::AnyUserData<'a>>,
|
||||||
pub fn_apply: for<'a> fn(
|
pub fn_apply: for<'a> fn(
|
||||||
lua: &'a elua::State,
|
lua: &'a mlua::Lua,
|
||||||
this_ptr: NonNull<u8>,
|
this_ptr: NonNull<u8>,
|
||||||
apply: &'a elua::AnyUserdata<'a>,
|
apply: &'a mlua::AnyUserData<'a>,
|
||||||
) -> elua::Result<()>,
|
) -> mlua::Result<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> FromType<T> for ReflectLuaProxy
|
impl<'a, T> FromType<T> for ReflectLuaProxy
|
||||||
where
|
where
|
||||||
T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata
|
T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData
|
||||||
{
|
{
|
||||||
fn from_type() -> Self {
|
fn from_type() -> Self {
|
||||||
Self {
|
Self {
|
||||||
fn_as_uservalue: |lua, this| -> elua::Result<elua::AnyUserdata> {
|
fn_as_uservalue: |lua, this| -> mlua::Result<mlua::AnyUserData> {
|
||||||
let this = unsafe { this.cast::<T>().as_ref() };
|
let this = unsafe { this.cast::<T>().as_ref() };
|
||||||
<T as LuaProxy>::as_lua_value(lua, this)
|
<T as LuaProxy>::as_lua_value(lua, this)
|
||||||
},
|
},
|
||||||
|
@ -124,45 +77,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for ScriptDynamicBundle {
|
impl<'lua> mlua::FromLua<'lua> for ScriptDynamicBundle {
|
||||||
fn from_lua(_: &'lua elua::State, val: elua::Value<'lua>) -> elua::Result<Self> {
|
fn from_lua(value: mlua::Value<'lua>, _lua: &'lua mlua::Lua) -> mlua::Result<Self> {
|
||||||
match val {
|
match value {
|
||||||
elua::Value::Userdata(ud) => Ok(ud.as_ref::<Self>()?.clone()),
|
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||||
elua::Value::Nil => Err(elua::Error::Nil),
|
mlua::Value::Nil => Err(mlua::Error::FromLuaConversionError {
|
||||||
_ => unreachable!(),
|
from: "Nil",
|
||||||
|
to: "DynamicBundle",
|
||||||
|
message: Some("Value was nil".to_string()),
|
||||||
|
}),
|
||||||
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLuaVec<'lua> for ScriptDynamicBundle {
|
|
||||||
fn from_lua_value_vec(state: &'lua elua::State, mut values: elua::ValueVec<'lua>) -> elua::Result<Self> {
|
|
||||||
if let Some(v) = values.pop_front() {
|
|
||||||
Ok(ScriptDynamicBundle::from_lua(state, v)?)
|
|
||||||
} else {
|
|
||||||
Err(elua::Error::Nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl elua::Userdata for ScriptDynamicBundle {
|
|
||||||
fn name() -> String {
|
|
||||||
"Bundle".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build<'a>(_: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> {
|
|
||||||
builder
|
|
||||||
.function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new())))
|
|
||||||
.method_mut("push", |_, this, comp: elua::AnyUserdata| {
|
|
||||||
let script_brw = comp.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
|
||||||
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
|
||||||
|
|
||||||
let refl_data = script_brw.data.unwrap();
|
|
||||||
let refl_data = refl_data.as_ref();
|
|
||||||
reflect.bundle_insert(&mut this.0, refl_data);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use elua::{AsLua, StdLibraries, StdLibrary};
|
use mlua::IntoLua;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity};
|
use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity};
|
||||||
|
@ -8,37 +8,40 @@ use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity};
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LuaHost;
|
pub struct LuaHost;
|
||||||
|
|
||||||
fn try_call_lua_function(lua: &elua::State, fn_name: &str) -> Result<(), ScriptError> {
|
fn try_call_lua_function(lua: &mlua::Lua, fn_name: &str) -> Result<(), ScriptError> {
|
||||||
let globals = lua.globals()?;
|
let globals = lua.globals();
|
||||||
|
|
||||||
if globals.has_key(fn_name)? {
|
match globals.get::<_, mlua::Function>(fn_name) {
|
||||||
let lua_fn = globals.get::<_, elua::Function>(fn_name)?;
|
Ok(init_fn) => {
|
||||||
lua_fn.exec(())
|
init_fn.call(())
|
||||||
.map_err(ScriptError::MluaError)?;
|
.map_err(ScriptError::MluaError)?;
|
||||||
|
},
|
||||||
|
Err(mlua::Error::FromLuaConversionError { from: "nil", to: "function", message: None }) => {
|
||||||
|
trace!("Function '{}' was not found, ignoring...", fn_name)
|
||||||
|
// ignore
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return Err(ScriptError::MluaError(e));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptHost for LuaHost {
|
impl ScriptHost for LuaHost {
|
||||||
type ScriptContext = Mutex<elua::State>;
|
type ScriptContext = Mutex<mlua::Lua>;
|
||||||
|
|
||||||
fn load_script(&mut self, script: &[u8], script_data: &crate::ScriptData, providers: &mut crate::ScriptApiProviders<Self>) -> Result<Self::ScriptContext, crate::ScriptError> {
|
fn load_script(&mut self, script: &[u8], script_data: &crate::ScriptData, providers: &mut crate::ScriptApiProviders<Self>) -> Result<Self::ScriptContext, crate::ScriptError> {
|
||||||
let mut ctx = Mutex::new({
|
let mut ctx = Mutex::new(mlua::Lua::new());
|
||||||
let s = elua::State::new();
|
|
||||||
s.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
|
||||||
s
|
|
||||||
});
|
|
||||||
|
|
||||||
//Mutex::new(elua::State::new_with_libraries(StdLibraries::all()));
|
|
||||||
|
|
||||||
for provider in providers.apis.iter_mut() {
|
for provider in providers.apis.iter_mut() {
|
||||||
provider.expose_api(script_data, &mut ctx)?;
|
provider.expose_api(script_data, &mut ctx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lua = ctx.lock().unwrap();
|
let lua = ctx.lock().unwrap();
|
||||||
lua.load(&script_data.name, script)?
|
lua.load(script)
|
||||||
.execute(())
|
.set_name(&script_data.name)
|
||||||
|
.exec()
|
||||||
.map_err(|e| ScriptError::MluaError(e))?;
|
.map_err(|e| ScriptError::MluaError(e))?;
|
||||||
drop(lua);
|
drop(lua);
|
||||||
|
|
||||||
|
@ -68,9 +71,9 @@ impl ScriptHost for LuaHost {
|
||||||
|
|
||||||
let ctx = ctx.lock().expect("Failure to get Lua ScriptContext");
|
let ctx = ctx.lock().expect("Failure to get Lua ScriptContext");
|
||||||
|
|
||||||
let globals = ctx.globals()?;
|
let globals = ctx.globals();
|
||||||
globals.set("world", world.as_lua(&ctx)?)?;
|
globals.set("world", world.into_lua(&ctx)?)?;
|
||||||
globals.set("entity", ScriptEntity(script_data.entity).as_lua(&ctx)?)?;
|
globals.set("entity", ScriptEntity(script_data.entity).into_lua(&ctx)?)?;
|
||||||
|
|
||||||
try_call_lua_function(&ctx, function_name)?;
|
try_call_lua_function(&ctx, function_name)?;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
use std::{sync::{Mutex, Arc}, ptr::NonNull};
|
||||||
|
|
||||||
|
use lyra_ecs::{World, system::{GraphExecutor, IntoSystem}};
|
||||||
|
use lyra_resource::ResourceManager;
|
||||||
|
use mlua::{IntoLua, AnyUserDataExt};
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, fmt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
use crate::{ScriptData, ScriptApiProvider, ScriptApiProviders, ScriptError, ScriptList, Script, ScriptContexts};
|
||||||
|
|
||||||
|
use super::{LuaHost, LuaLoader, LuaScript, lua_script_update_stage_system, lua_scripts_create_contexts, LuaContext};
|
||||||
|
|
||||||
|
fn enable_tracing() {
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(fmt::layer().with_writer(std::io::stdout))
|
||||||
|
.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct PrintfProvider;
|
||||||
|
|
||||||
|
impl ScriptApiProvider for PrintfProvider {
|
||||||
|
type ScriptContext = Mutex<mlua::Lua>;
|
||||||
|
|
||||||
|
fn expose_api(&mut self, script_data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
|
let ctx = ctx.lock().unwrap();
|
||||||
|
|
||||||
|
fn printf(lua: &mlua::Lua, (mut text, formats): (String, mlua::Variadic<mlua::Value>)) -> mlua::Result<()> {
|
||||||
|
let mut formatted = String::new();
|
||||||
|
let mut arg_num = 0;
|
||||||
|
|
||||||
|
while let Some(start) = text.find("{}") {
|
||||||
|
let val_str = match formats.get(arg_num) {
|
||||||
|
Some(v) => match v {
|
||||||
|
mlua::Value::Nil => "nil".to_string(),
|
||||||
|
mlua::Value::Boolean(b) => b.to_string(),
|
||||||
|
mlua::Value::LightUserData(_) => {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of LightUserData")));
|
||||||
|
},
|
||||||
|
mlua::Value::Integer(i) => i.to_string(),
|
||||||
|
mlua::Value::Number(n) => n.to_string(),
|
||||||
|
mlua::Value::String(s) => s.to_str().unwrap().to_string(),
|
||||||
|
mlua::Value::Table(_) => {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Table")));
|
||||||
|
},
|
||||||
|
mlua::Value::Function(_) => {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Function")));
|
||||||
|
},
|
||||||
|
mlua::Value::Thread(_) => {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("unable to get string representation of Thread")));
|
||||||
|
},
|
||||||
|
mlua::Value::UserData(ud) => {
|
||||||
|
if let Ok(tos) = ud.get::<_, mlua::Function>(mlua::MetaMethod::ToString.to_string()) {
|
||||||
|
tos.call::<_, String>(())?
|
||||||
|
} else {
|
||||||
|
return Err(mlua::Error::RuntimeError(format!("UserData does not implement MetaMethod '__tostring'")));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mlua::Value::Error(e) => e.to_string(),
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let got_args = arg_num;// - 1;
|
||||||
|
|
||||||
|
// continue searching for {} to get the number of format spots for the error message.
|
||||||
|
while let Some(start) = text.find("{}") {
|
||||||
|
text = text[start + 2..].to_string();
|
||||||
|
arg_num += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(mlua::Error::BadArgument {
|
||||||
|
to: Some("printf".to_string()),
|
||||||
|
pos: 2,
|
||||||
|
name: Some("...".to_string()),
|
||||||
|
cause: Arc::new(mlua::Error::RuntimeError(format!("not enough args \
|
||||||
|
given for the amount of format areas in the string. Expected {}, \
|
||||||
|
got {}.", arg_num, got_args)))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
formatted = format!("{}{}{}", formatted, &text[0..start], val_str);
|
||||||
|
|
||||||
|
text = text[start + 2..].to_string();
|
||||||
|
|
||||||
|
arg_num += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg_num < formats.len() {
|
||||||
|
return Err(mlua::Error::BadArgument {
|
||||||
|
to: Some("printf".to_string()),
|
||||||
|
pos: 2,
|
||||||
|
name: Some("...".to_string()),
|
||||||
|
cause: Arc::new(mlua::Error::RuntimeError(format!("got more args \
|
||||||
|
than format areas in the string. Expected {}, got {}.", formats.len(), arg_num)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
formatted = format!("{}{}", formatted, text);
|
||||||
|
|
||||||
|
lua.globals()
|
||||||
|
.get::<_, mlua::Function>("print")
|
||||||
|
.unwrap()
|
||||||
|
.call::<_, ()>(formatted)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let printf_func = ctx.create_function(printf).unwrap();
|
||||||
|
|
||||||
|
let globals = ctx.globals();
|
||||||
|
globals.set("printf", printf_func).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_script(&mut self, _data: &ScriptData, _ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_script_environment(&mut self, world: crate::ScriptWorldPtr, _data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
|
let ctx = ctx.lock().unwrap();
|
||||||
|
let globals = ctx.globals();
|
||||||
|
|
||||||
|
let world_lua = world.into_lua(&ctx)
|
||||||
|
.map_err(ScriptError::MluaError)?;
|
||||||
|
globals.set("world", world_lua)
|
||||||
|
.map_err(ScriptError::MluaError)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tests a simple lua script that just prints some test
|
||||||
|
#[test]
|
||||||
|
pub fn lua_print() {
|
||||||
|
enable_tracing();
|
||||||
|
|
||||||
|
let mut world = World::new();
|
||||||
|
|
||||||
|
let test_provider = PrintfProvider::default();
|
||||||
|
let mut providers = ScriptApiProviders::<LuaHost>::default();
|
||||||
|
providers.add_provider(test_provider);
|
||||||
|
|
||||||
|
let host = LuaHost::default();
|
||||||
|
|
||||||
|
world.add_resource(host);
|
||||||
|
world.add_resource(providers);
|
||||||
|
world.add_resource(ScriptContexts::<LuaContext>::default());
|
||||||
|
|
||||||
|
let mut res_loader = ResourceManager::new();
|
||||||
|
res_loader.register_loader::<LuaLoader>();
|
||||||
|
|
||||||
|
let script =
|
||||||
|
r#"
|
||||||
|
print("Hello World")
|
||||||
|
|
||||||
|
function update()
|
||||||
|
print("updated")
|
||||||
|
printf("I love to eat formatted {}!", "food")
|
||||||
|
--printf("World is {}", world)
|
||||||
|
end
|
||||||
|
"#;
|
||||||
|
let script = script.as_bytes();
|
||||||
|
|
||||||
|
let script = res_loader.load_bytes::<LuaScript>("test_script.lua",
|
||||||
|
"text/lua", script.to_vec(), 0, script.len()).unwrap();
|
||||||
|
let script = Script::new("text_script.lua", script);
|
||||||
|
|
||||||
|
let scripts = ScriptList::new(vec![script]);
|
||||||
|
|
||||||
|
world.spawn((scripts,));
|
||||||
|
|
||||||
|
let mut exec = GraphExecutor::new();
|
||||||
|
exec.insert_system("lua_create_contexts", lua_scripts_create_contexts.into_system(), &[]);
|
||||||
|
exec.insert_system("lua_update_scripts", lua_script_update_stage_system.into_system(), &["lua_create_contexts"]);
|
||||||
|
exec.execute(NonNull::from(&world), true).unwrap();
|
||||||
|
}
|
|
@ -1,33 +1,28 @@
|
||||||
use std::{any::Any, ptr::NonNull, sync::Arc};
|
use std::{sync::{Arc, RwLock}, ptr::NonNull, any::Any, ops::Deref};
|
||||||
|
|
||||||
use elua::AsLua;
|
|
||||||
use lyra_ecs::query::dynamic::QueryDynamicType;
|
use lyra_ecs::query::dynamic::QueryDynamicType;
|
||||||
use lyra_reflect::{TypeRegistry, ReflectWorldExt, RegisteredType};
|
use lyra_reflect::{TypeRegistry, ReflectWorldExt, RegisteredType};
|
||||||
|
use mlua::{AnyUserDataExt, IntoLua, IntoLuaMulti};
|
||||||
|
|
||||||
use crate::{ScriptWorldPtr, ScriptEntity, ScriptDynamicBundle, ScriptBorrow};
|
use crate::{ScriptWorldPtr, ScriptEntity, ScriptDynamicBundle, ScriptBorrow};
|
||||||
|
|
||||||
use super::{reflect_user_data, DynamicViewIter, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, ReflectedLuaTableProxy, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE};
|
use super::{ReflectedIterator, DynamicViewIter, FN_NAME_INTERNAL_REFLECT_TYPE, reflect_user_data, ReflectLuaProxy, FN_NAME_INTERNAL_REFLECT};
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for ScriptEntity {
|
impl<'lua> mlua::FromLua<'lua> for ScriptEntity {
|
||||||
fn from_lua(_: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result<Self> {
|
fn from_lua(value: mlua::Value<'lua>, _lua: &'lua mlua::Lua) -> mlua::Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
elua::Value::Userdata(ud) => Ok(ud.as_ref::<Self>()?.clone()),
|
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||||
elua::Value::Nil => Err(elua::Error::type_mismatch("ScriptEntity", "Nil")),
|
mlua::Value::Nil => Err(mlua::Error::FromLuaConversionError { from: "Nil", to: "ScriptEntity", message: Some("Value was nil".to_string()) }),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl elua::Userdata for ScriptEntity {
|
impl mlua::UserData for ScriptEntity {
|
||||||
fn name() -> String {
|
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
"Entity".to_string()
|
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, ()| {
|
||||||
}
|
|
||||||
|
|
||||||
fn build<'a>(state: &elua::State, builder: &mut elua::userdata::UserdataBuilder<'a, Self>) -> elua::Result<()> {
|
|
||||||
builder.meta_method(elua::MetaMethod::ToString, |_, this, ()| {
|
|
||||||
Ok(format!("{:?}", this.0))
|
Ok(format!("{:?}", this.0))
|
||||||
});
|
})
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,177 +32,153 @@ pub enum WorldError {
|
||||||
LuaInvalidUsage(String),
|
LuaInvalidUsage(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> elua::FromLua<'a> for ScriptWorldPtr {
|
impl mlua::UserData for ScriptWorldPtr {
|
||||||
fn from_lua(lua: &'a elua::State, val: elua::Value<'a>) -> elua::Result<Self> {
|
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
match val {
|
methods.add_method_mut("spawn", |_, this, (bundle,): (ScriptDynamicBundle,)| {
|
||||||
elua::Value::Userdata(ud) => Ok(ud.as_ref::<Self>()?.clone()),
|
let world = unsafe { this.inner.as_mut() };
|
||||||
elua::Value::Nil => Err(elua::Error::type_mismatch("ScriptWorldPtr", "Nil")),
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl elua::Userdata for ScriptWorldPtr {
|
Ok(ScriptEntity(world.spawn(bundle.0)))
|
||||||
fn name() -> String {
|
});
|
||||||
"World".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> {
|
methods.add_method("view_iter", |lua, this, queries: mlua::Variadic<mlua::AnyUserData>| {
|
||||||
builder
|
let world = unsafe { this.inner.as_ref() };
|
||||||
.method_mut("spawn", |_, this, bundle: ScriptDynamicBundle| {
|
let mut view = world.dynamic_view();
|
||||||
let world = this.as_mut();
|
|
||||||
|
|
||||||
Ok(ScriptEntity(world.spawn(bundle.0)))
|
for comp in queries.into_iter() {
|
||||||
})
|
let script_brw = comp.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
.method_mut("view", |lua, this, (system, queries): (elua::Function, elua::ValueVec)| {
|
.expect("Type does not implement '__internal_reflect_type' properly");
|
||||||
if queries.is_empty() {
|
let refl_comp = script_brw.reflect_branch.as_component_unchecked();
|
||||||
return Err(
|
|
||||||
elua::Error::BadArgument { func: Some("World:view".to_string()), arg_index: 2, arg_name: Some("query...".to_string()),
|
let dyn_type = QueryDynamicType::from_info(refl_comp.info);
|
||||||
error: Arc::new(elua::Error::other(WorldError::LuaInvalidUsage("no component types provided".to_string())))
|
view.push(dyn_type);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
let iter = view.into_iter();
|
||||||
|
let mut reflected_iter = ReflectedIterator {
|
||||||
|
world: this.clone(),
|
||||||
|
dyn_view: DynamicViewIter::from(iter),
|
||||||
|
reflected_components: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let f = lua.create_function_mut(move |lua, ()| {
|
||||||
|
if let Some(row) = reflected_iter.next_lua(lua) {
|
||||||
|
let row = row.row.into_iter().map(|i| i.comp_ud.into_lua(lua))
|
||||||
|
.collect::<mlua::Result<Vec<mlua::Value>>>()?;
|
||||||
|
Ok(mlua::MultiValue::from_vec(row))
|
||||||
|
} else {
|
||||||
|
Ok(mlua::Value::Nil.into_lua_multi(lua)?)
|
||||||
}
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
let world = unsafe { this.inner.as_ref() };
|
Ok(f)
|
||||||
let mut view = world.dynamic_view();
|
});
|
||||||
|
|
||||||
for (idx, comp) in queries.into_iter().enumerate() {
|
methods.add_method_mut("view", |lua, this, (system, queries): (mlua::Function, mlua::Variadic<mlua::AnyUserData>)| {
|
||||||
match comp {
|
if queries.is_empty() {
|
||||||
elua::Value::Table(t) => {
|
return Err(mlua::Error::BadArgument { to: Some("world:view".to_string()), pos: 2, name: Some("...".to_string()), cause:
|
||||||
let name: String = t.get("__name")?;
|
Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage("no component types provided".to_string())))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let lookup = world.get_resource::<LuaTableProxyLookup>();
|
let world = unsafe { this.inner.as_ref() };
|
||||||
let info = lookup.comp_info_from_name.get(&name)
|
let mut view = world.dynamic_view();
|
||||||
.ok_or_else(||
|
|
||||||
elua::Error::BadArgument {
|
|
||||||
func: Some("World:view".to_string()),
|
|
||||||
arg_index: 2 + idx as i32,
|
|
||||||
arg_name: Some("query...".to_string()),
|
|
||||||
error: Arc::new(
|
|
||||||
elua::Error::Runtime(format!("the 'Table' with name {} is unknown to the engine!", name))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let dyn_type = QueryDynamicType::from_info(info.clone());
|
for comp in queries.into_iter() {
|
||||||
view.push(dyn_type);
|
let reflect = comp.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
},
|
.expect("Type does not implement 'reflect_type' properly");
|
||||||
elua::Value::Userdata(ud) => {
|
let refl_comp = reflect.reflect_branch.as_component_unchecked();
|
||||||
let reflect = ud.execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
|
||||||
.expect("Type does not implement 'reflect_type' properly");
|
|
||||||
let refl_comp = reflect.reflect_branch.as_component_unchecked();
|
|
||||||
|
|
||||||
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);
|
||||||
},
|
}
|
||||||
_ => todo!()
|
|
||||||
|
let iter = view.into_iter();
|
||||||
|
let mut reflected_iter = ReflectedIterator {
|
||||||
|
world: this.clone(),
|
||||||
|
dyn_view: DynamicViewIter::from(iter),
|
||||||
|
reflected_components: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut current = world.current_tick();
|
||||||
|
let mut has_ticked = false;
|
||||||
|
|
||||||
|
while let Some(row) = reflected_iter.next_lua(lua) {
|
||||||
|
|
||||||
|
let r = row.row.into_iter()
|
||||||
|
.map(|r| (r.proxy, r.comp_ud, r.comp_ptr))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let (reflects, values, ptrs):
|
||||||
|
(Vec<&ReflectLuaProxy>, Vec<mlua::AnyUserData>, Vec<NonNull<u8>>)
|
||||||
|
= itertools::multiunzip(r);
|
||||||
|
let value_row: Vec<_> = values.into_iter().map(|ud| ud.into_lua(lua)).collect::<mlua::Result<Vec<mlua::Value>>>()?;
|
||||||
|
let mult_val = mlua::MultiValue::from_vec(value_row);
|
||||||
|
let res: mlua::MultiValue = system.call(mult_val)?;
|
||||||
|
|
||||||
|
// if values were returned, find the type in the type registry, and apply the new values
|
||||||
|
if res.len() <= reflects.len() {
|
||||||
|
// we only want to tick one time per system
|
||||||
|
if !has_ticked {
|
||||||
|
current = world.tick();
|
||||||
|
has_ticked = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let iter = view.into_iter();
|
for (i, comp) in res.into_iter().enumerate() {
|
||||||
let mut reflected_iter = ReflectedIterator {
|
let ptr = ptrs[i];
|
||||||
world: this.clone(),
|
|
||||||
dyn_view: DynamicViewIter::from(iter),
|
|
||||||
reflected_components: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut current = world.current_tick();
|
match comp.as_userdata() {
|
||||||
let mut has_ticked = false;
|
Some(ud) => {
|
||||||
|
let lua_comp = reflect_user_data(ud);
|
||||||
|
let refl_comp = lua_comp.reflect_branch.as_component_unchecked();
|
||||||
|
let lua_typeid = refl_comp.info.type_id.as_rust();
|
||||||
|
|
||||||
while let Some(row) = reflected_iter.next_lua(lua) {
|
// update the component tick
|
||||||
let r = row.row.into_iter()
|
let world = unsafe { this.inner.as_mut() };
|
||||||
.map(|r| (r.comp_val, r.comp_ptr))
|
let arch = world.entity_archetype_mut(row.entity).unwrap();
|
||||||
.collect::<Vec<_>>();
|
let idx = arch.entities().get(&row.entity).unwrap().clone();
|
||||||
let (values, ptrs) = itertools::multiunzip::<(Vec<elua::Value>, Vec<NonNull<u8>>), _>(r);
|
let c = arch.get_column_mut(refl_comp.type_id.into()).unwrap();
|
||||||
let mult_val = elua::ValueVec::from(values);
|
c.entity_ticks[idx.0 as usize] = current;
|
||||||
let res: elua::ValueVec = system.exec(mult_val)?;
|
|
||||||
|
|
||||||
// if values were returned, find the type in the type registry, and apply the new values
|
// apply the new component data
|
||||||
if res.len() <= ptrs.len() {
|
let reg = this.as_ref().get_resource::<TypeRegistry>();
|
||||||
// we only want to tick one time per system
|
let reg_type = reg.get_type(lua_typeid).unwrap();
|
||||||
if !has_ticked {
|
|
||||||
current = world.tick();
|
|
||||||
has_ticked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, comp) in res.into_iter().enumerate() {
|
let proxy = reg_type.get_data::<ReflectLuaProxy>().unwrap();
|
||||||
let ptr = ptrs[i];
|
(proxy.fn_apply)(lua, ptr, ud)?;
|
||||||
|
}
|
||||||
match comp {
|
None => {
|
||||||
elua::Value::Userdata(ud) => {
|
panic!("A userdata value was not returned!");
|
||||||
let lua_comp = reflect_user_data(&ud);
|
|
||||||
let refl_comp = lua_comp.reflect_branch.as_component_unchecked();
|
|
||||||
let lua_typeid = refl_comp.info.type_id.as_rust();
|
|
||||||
|
|
||||||
// update the component tick
|
|
||||||
let world = unsafe { this.inner.as_mut() };
|
|
||||||
let arch = world.entity_archetype_mut(row.entity).unwrap();
|
|
||||||
let idx = arch.entities().get(&row.entity).unwrap().clone();
|
|
||||||
let c = arch.get_column_mut(refl_comp.type_id.into()).unwrap();
|
|
||||||
c.entity_ticks[idx.0 as usize] = current;
|
|
||||||
|
|
||||||
// apply the new component data
|
|
||||||
let reg = this.as_ref().get_resource::<TypeRegistry>();
|
|
||||||
let reg_type = reg.get_type(lua_typeid).unwrap();
|
|
||||||
|
|
||||||
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
|
||||||
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
|
||||||
(proxy.fn_apply)(lua, ptr, &ud)?;
|
|
||||||
},
|
|
||||||
elua::Value::Table(tbl) => {
|
|
||||||
let name: String = tbl.get("__name")?;
|
|
||||||
|
|
||||||
let lookup = world.get_resource::<LuaTableProxyLookup>();
|
|
||||||
let tyid = lookup.typeid_from_name.get(&name).unwrap();
|
|
||||||
|
|
||||||
// update the component tick
|
|
||||||
let world = unsafe { this.inner.as_mut() };
|
|
||||||
let arch = world.entity_archetype_mut(row.entity).unwrap();
|
|
||||||
let idx = arch.entities().get(&row.entity).unwrap().clone();
|
|
||||||
let c = arch.get_column_mut(tyid.clone().into()).unwrap();
|
|
||||||
c.entity_ticks[idx.0 as usize] = current;
|
|
||||||
|
|
||||||
// apply the new component data
|
|
||||||
let reg = this.as_ref().get_resource::<TypeRegistry>();
|
|
||||||
let reg_type = reg.get_type(*tyid).unwrap();
|
|
||||||
|
|
||||||
let proxy = reg_type.get_data::<ReflectedLuaTableProxy>()
|
|
||||||
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
|
||||||
(proxy.fn_apply)(lua, ptr.cast(), &tbl)?;
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
panic!("A userdata or table value was not returned!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let msg = format!("Too many arguments were returned from the World view!
|
|
||||||
At most, the expected number of results is {}.", ptrs.len());
|
|
||||||
return Err(elua::Error::Runtime(msg));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.method_mut("resource", |lua, this, (ty,): (elua::AnyUserdata,)| {
|
|
||||||
let reflect = ty
|
|
||||||
.execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
|
||||||
.expect("Type does not implement 'reflect_type' properly");
|
|
||||||
|
|
||||||
let res = reflect.reflect_branch.as_resource_unchecked();
|
|
||||||
if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) {
|
|
||||||
let reg_type = this.as_ref().get_type::<RegisteredType>(reflect.reflect_branch.reflect_type_id())
|
|
||||||
.unwrap();
|
|
||||||
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
|
||||||
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
|
||||||
|
|
||||||
(proxy.fn_as_uservalue)(lua, res_ptr)
|
|
||||||
.and_then(|ud| ud.as_lua(lua))
|
|
||||||
} else {
|
} else {
|
||||||
// if the resource is not found in the world, return nil
|
let msg = format!("Too many arguments were returned from the World view!
|
||||||
Ok(elua::Value::Nil)
|
At most, the expected number of results is {}.", reflects.len());
|
||||||
|
return Err(mlua::Error::external(WorldError::LuaInvalidUsage(msg)));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_method_mut("resource", |lua, this, (ty,): (mlua::AnyUserData,)| {
|
||||||
|
let reflect = ty
|
||||||
|
.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
|
.expect("Type does not implement 'reflect_type' properly");
|
||||||
|
|
||||||
|
let res = reflect.reflect_branch.as_resource_unchecked();
|
||||||
|
if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) {
|
||||||
|
//.expect("Failed to find resource pointer in world!");
|
||||||
|
let reg_type = this.as_ref().get_type::<RegisteredType>(reflect.reflect_branch.reflect_type_id())
|
||||||
|
.unwrap();
|
||||||
|
let proxy = reg_type.get_data::<ReflectLuaProxy>()
|
||||||
|
.expect("Type does not have ReflectLuaProxy as a TypeData");
|
||||||
|
|
||||||
|
(proxy.fn_as_uservalue)(lua, res_ptr)
|
||||||
|
.and_then(|ud| ud.into_lua(lua))
|
||||||
|
} else {
|
||||||
|
// if the resource is not found in the world, return nil
|
||||||
|
Ok(mlua::Value::Nil)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use std::any::TypeId;
|
use std::{ops::Deref, any::TypeId};
|
||||||
|
|
||||||
use lyra_game::DeltaTime;
|
use lyra_game::DeltaTime;
|
||||||
use crate::{lyra_engine, lua::{FN_NAME_INTERNAL_REFLECT_TYPE, LuaWrapper}, ScriptBorrow};
|
use crate::{lyra_engine, lua::{FN_NAME_INTERNAL_REFLECT_TYPE, LuaWrapper}, ScriptBorrow};
|
||||||
|
@ -20,33 +20,28 @@ impl std::ops::DerefMut for LuaDeltaTime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for LuaDeltaTime {
|
impl<'lua> mlua::FromLua<'lua> for LuaDeltaTime {
|
||||||
fn from_lua(lua: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result<Self> {
|
fn from_lua(value: mlua::prelude::LuaValue<'lua>, lua: &'lua mlua::prelude::Lua) -> mlua::prelude::LuaResult<Self> {
|
||||||
match value {
|
match value {
|
||||||
elua::Value::Userdata(ud) => Ok(ud.as_ref::<Self>()?.clone()),
|
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl elua::Userdata for LuaDeltaTime {
|
impl mlua::UserData for LuaDeltaTime {
|
||||||
fn name() -> String {
|
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
"DeltaTime".to_string()
|
methods.add_method("get", |_, this, ()| {
|
||||||
}
|
Ok(*this.0.deref())
|
||||||
|
});
|
||||||
|
|
||||||
fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> {
|
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, ()| {
|
||||||
builder
|
Ok(format!("{}", this.0.deref()))
|
||||||
.method("get", |_, this, ()| {
|
});
|
||||||
Ok(*this.0)
|
|
||||||
})
|
|
||||||
.meta_method(elua::MetaMethod::ToString, |_, this, ()| {
|
|
||||||
Ok(format!("{}", *this.0))
|
|
||||||
})
|
|
||||||
.function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
|
||||||
Ok(ScriptBorrow::from_resource::<DeltaTime>(None))
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
methods.add_function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
||||||
|
Ok(ScriptBorrow::from_resource::<DeltaTime>(None))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use lyra_scripting_derive::wrap_math_vec_copy;
|
||||||
use crate as lyra_scripting;
|
use crate as lyra_scripting;
|
||||||
|
|
||||||
// f32 types
|
// f32 types
|
||||||
/* wrap_math_vec_copy!(
|
wrap_math_vec_copy!(
|
||||||
math::Vec2,
|
math::Vec2,
|
||||||
derives(PartialEq),
|
derives(PartialEq),
|
||||||
fields(x, y),
|
fields(x, y),
|
||||||
|
@ -32,11 +32,7 @@ wrap_math_vec_copy!(
|
||||||
Mod(LuaVec3, f32),
|
Mod(LuaVec3, f32),
|
||||||
Eq, Unm, ToString
|
Eq, Unm, ToString
|
||||||
)
|
)
|
||||||
); */
|
);
|
||||||
|
|
||||||
|
|
||||||
// =================================================
|
|
||||||
|
|
||||||
|
|
||||||
/* wrap_math_vec_copy!(
|
/* wrap_math_vec_copy!(
|
||||||
math::Vec3A,
|
math::Vec3A,
|
||||||
|
@ -383,20 +379,7 @@ wrap_math_vec_copy!(
|
||||||
)
|
)
|
||||||
); */
|
); */
|
||||||
|
|
||||||
|
wrap_math_vec_copy!(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* wrap_math_vec_copy!(
|
|
||||||
math::Quat,
|
math::Quat,
|
||||||
derives(PartialEq),
|
derives(PartialEq),
|
||||||
no_new,
|
no_new,
|
||||||
|
@ -576,4 +559,3 @@ wrap_math_vec_copy!(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
*/
|
|
Loading…
Reference in New Issue