Compare commits
No commits in common. "b90e19161d36bb056ee004ac865c518886caada1" and "49dfb38da3268991f3a97e01e49e1254c62af137" have entirely different histories.
b90e19161d
...
49dfb38da3
|
@ -69,24 +69,13 @@ function on_update()
|
||||||
---@type number
|
---@type number
|
||||||
local dt = world:resource(DeltaTime)
|
local dt = world:resource(DeltaTime)
|
||||||
|
|
||||||
--[[ world:view(
|
world:view(
|
||||||
---@param t Transform
|
---@param t Transform
|
||||||
function (t)
|
function (t)
|
||||||
t:translate(0, 0.15 * dt, 0)
|
t:translate(0, 0.15 * dt, 0)
|
||||||
return t
|
return t
|
||||||
end, Transform
|
end, Transform
|
||||||
) ]]
|
)
|
||||||
|
|
||||||
--[[ world:view(
|
|
||||||
---@param c Camera
|
|
||||||
function (c)
|
|
||||||
c.transform:translate(0, 0.15 * dt, 0)
|
|
||||||
|
|
||||||
print("Moving camera to: " .. tostring(c.transform))
|
|
||||||
|
|
||||||
return c
|
|
||||||
end, Camera
|
|
||||||
) ]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ function on_post_update()
|
--[[ function on_post_update()
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use lyra_reflect::Reflect;
|
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX}, scene::CameraComponent};
|
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX}, scene::CameraComponent};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum CameraProjectionMode {
|
pub enum CameraProjectionMode {
|
||||||
/// 3d camera projection
|
/// 3d camera projection
|
||||||
Perspective,
|
Perspective,
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use lyra_ecs::Component;
|
use lyra_ecs::Component;
|
||||||
use lyra_reflect::Reflect;
|
|
||||||
|
|
||||||
use crate::{math::{Angle, Transform}, render::camera::CameraProjectionMode};
|
use crate::{math::{Angle, Transform}, render::camera::CameraProjectionMode};
|
||||||
|
|
||||||
#[derive(Clone, Component, Reflect)]
|
#[derive(Clone, Component)]
|
||||||
pub struct CameraComponent {
|
pub struct CameraComponent {
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub fov: Angle,
|
pub fov: Angle,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use glam::{EulerRot, Quat, Vec3};
|
use glam::{EulerRot, Quat, Vec3};
|
||||||
use lyra_ecs::{query::{Res, View}, Component};
|
use lyra_ecs::{query::{Res, View}, Component};
|
||||||
use lyra_reflect::Reflect;
|
|
||||||
|
|
||||||
use crate::{game::App, input::ActionHandler, plugin::Plugin, DeltaTime};
|
use crate::{game::App, input::ActionHandler, plugin::Plugin, DeltaTime};
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ pub const ACTLBL_LOOK_LEFT_RIGHT: &str = "LookLeftRight";
|
||||||
pub const ACTLBL_LOOK_UP_DOWN: &str = "LookUpDown";
|
pub const ACTLBL_LOOK_UP_DOWN: &str = "LookUpDown";
|
||||||
pub const ACTLBL_LOOK_ROLL: &str = "LookRoll";
|
pub const ACTLBL_LOOK_ROLL: &str = "LookRoll";
|
||||||
|
|
||||||
#[derive(Clone, Component, Reflect)]
|
#[derive(Clone, Component)]
|
||||||
pub struct FreeFlyCamera {
|
pub struct FreeFlyCamera {
|
||||||
pub speed: f32,
|
pub speed: f32,
|
||||||
pub slow_speed_factor: f32,
|
pub slow_speed_factor: f32,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use lyra_math::Angle;
|
|
||||||
use lyra_reflect_derive::{impl_reflect_simple_struct, impl_reflect_trait_value};
|
use lyra_reflect_derive::{impl_reflect_simple_struct, impl_reflect_trait_value};
|
||||||
|
|
||||||
use crate::{lyra_engine, Enum, Method, Reflect, ReflectMut, ReflectRef};
|
use crate::{lyra_engine, Method, Reflect};
|
||||||
|
|
||||||
impl_reflect_simple_struct!(lyra_math::Vec2, fields(x = f32, y = f32));
|
impl_reflect_simple_struct!(lyra_math::Vec2, fields(x = f32, y = f32));
|
||||||
impl_reflect_simple_struct!(lyra_math::Vec3, fields(x = f32, y = f32, z = f32));
|
impl_reflect_simple_struct!(lyra_math::Vec3, fields(x = f32, y = f32, z = f32));
|
||||||
|
@ -18,131 +17,3 @@ impl_reflect_simple_struct!(
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_reflect_trait_value!(lyra_math::Mat4);
|
impl_reflect_trait_value!(lyra_math::Mat4);
|
||||||
|
|
||||||
impl Reflect for Angle {
|
|
||||||
fn name(&self) -> String {
|
|
||||||
"Angle".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_id(&self) -> std::any::TypeId {
|
|
||||||
std::any::TypeId::of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply(&mut self, val: &dyn Reflect) {
|
|
||||||
if let ReflectRef::Enum(e) = val.reflect_ref() {
|
|
||||||
let s = e.as_any().downcast_ref::<Self>()
|
|
||||||
.expect("cannot apply mismatched reflected enum");
|
|
||||||
*self = *s;
|
|
||||||
} else {
|
|
||||||
panic!("Provided value was not an enum!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clone_inner(&self) -> Box<dyn Reflect> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reflect_ref(&self) -> crate::ReflectRef {
|
|
||||||
ReflectRef::Enum(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reflect_mut(&mut self) -> crate::ReflectMut {
|
|
||||||
ReflectMut::Enum(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reflect_val(&self) -> &dyn Reflect {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reflect_val_mut(&mut self) -> &mut dyn Reflect {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Enum for Angle {
|
|
||||||
fn field(&self, _: &str) -> Option<&dyn Reflect> {
|
|
||||||
// no struct variants
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_mut(&mut self, _: &str) -> Option<&mut dyn Reflect> {
|
|
||||||
// no struct variants
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_at(&self, idx: usize) -> Option<&dyn Reflect> {
|
|
||||||
// all variants only have one tuple field
|
|
||||||
if idx != 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Angle::Degrees(v) => Some(v),
|
|
||||||
Angle::Radians(v) => Some(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_at_mut(&mut self, idx: usize) -> Option<&mut dyn Reflect> {
|
|
||||||
// all variants only have one tuple field
|
|
||||||
if idx != 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Angle::Degrees(v) => Some(v),
|
|
||||||
Angle::Radians(v) => Some(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_name_at(&self, _: usize) -> Option<String> {
|
|
||||||
// no struct variants
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_field(&self, _: &str) -> bool {
|
|
||||||
// no struct variants
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fields_len(&self) -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn variants_len(&self) -> usize {
|
|
||||||
2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn variant_name(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Angle::Degrees(_) => "degrees".into(),
|
|
||||||
Angle::Radians(_) => "radians".into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn variant_index(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
Angle::Degrees(_) => 0,
|
|
||||||
Angle::Radians(_) => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_variant_name(&self, name: &str) -> bool {
|
|
||||||
self.variant_name() == name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn variant_type(&self) -> crate::EnumType {
|
|
||||||
crate::EnumType::Tuple
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
use syn::{parenthesized, token, Token};
|
|
||||||
|
|
||||||
pub(crate) enum FieldType {
|
|
||||||
Unknown,
|
|
||||||
Type(syn::Path),
|
|
||||||
Wrapped(syn::Path),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FieldType {
|
|
||||||
pub fn is_unknown(&self) -> bool {
|
|
||||||
matches!(self, FieldType::Unknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_wrapped(&self) -> bool {
|
|
||||||
matches!(self, FieldType::Wrapped(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_type_path(&self) -> Option<&syn::Path> {
|
|
||||||
match self {
|
|
||||||
FieldType::Unknown => None,
|
|
||||||
FieldType::Type(path) => Some(path),
|
|
||||||
FieldType::Wrapped(path) => Some(path),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct Field {
|
|
||||||
pub field: syn::Ident,
|
|
||||||
pub field_ty: FieldType,
|
|
||||||
pub skip_setter: bool,
|
|
||||||
pub setter: Option<syn::Block>,
|
|
||||||
pub getter: Option<syn::Block>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Field {
|
|
||||||
fn parse_extended(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
||||||
let field_name = input.parse()?;
|
|
||||||
|
|
||||||
let fty = if input.peek(Token![:]) {
|
|
||||||
let _col: Token![:] = input.parse()?;
|
|
||||||
let s: syn::Path = input.parse()?;
|
|
||||||
let mut fty = FieldType::Type(s.clone());
|
|
||||||
|
|
||||||
if let Some(ident) = s.get_ident() {
|
|
||||||
if ident.to_string() == "wrap" {
|
|
||||||
let content;
|
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
|
||||||
fty = FieldType::Wrapped(content.parse()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fty
|
|
||||||
} else {
|
|
||||||
FieldType::Unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut s = Self {
|
|
||||||
field: field_name,
|
|
||||||
field_ty: fty,
|
|
||||||
skip_setter: false,
|
|
||||||
setter: None,
|
|
||||||
getter: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
while input.peek(Token![,]) {
|
|
||||||
let _: Token![,] = input.parse()?;
|
|
||||||
|
|
||||||
if input.peek(syn::Ident) {
|
|
||||||
let ident: syn::Ident = input.parse()?;
|
|
||||||
let ident_str = ident.to_string();
|
|
||||||
let ident_str = ident_str.as_str();
|
|
||||||
|
|
||||||
match ident_str {
|
|
||||||
"skip_set" => {
|
|
||||||
s.skip_setter = true;
|
|
||||||
}
|
|
||||||
"set" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
|
|
||||||
s.setter = Some(input.parse()?);
|
|
||||||
}
|
|
||||||
"get" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
|
|
||||||
s.getter = Some(input.parse()?);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(syn::Error::new_spanned(ident, "unknown wrapper command"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.getter.is_some() || s.setter.is_some()) && s.field_ty.is_wrapped() {
|
|
||||||
return Err(syn::Error::new(
|
|
||||||
input.span(),
|
|
||||||
"cannot specify custom getter or setter \
|
|
||||||
with wrapped type",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl syn::parse::Parse for Field {
|
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
||||||
if input.peek(token::Paren) {
|
|
||||||
let content;
|
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
|
||||||
|
|
||||||
Self::parse_extended(&content)
|
|
||||||
} else {
|
|
||||||
let field_name = input.parse()?;
|
|
||||||
|
|
||||||
let fty = if input.peek(Token![:]) {
|
|
||||||
let _col: Token![:] = input.parse()?;
|
|
||||||
let s: syn::Path = input.parse()?;
|
|
||||||
let mut fty = FieldType::Type(s.clone());
|
|
||||||
|
|
||||||
if let Some(ident) = s.get_ident() {
|
|
||||||
if ident.to_string() == "wrap" {
|
|
||||||
let content;
|
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
|
||||||
fty = FieldType::Wrapped(content.parse()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fty
|
|
||||||
} else {
|
|
||||||
FieldType::Unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
field: field_name,
|
|
||||||
field_ty: fty,
|
|
||||||
skip_setter: false,
|
|
||||||
setter: None,
|
|
||||||
getter: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -247,15 +247,9 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaWrapper for #wrapper_name {
|
impl LuaWrapper for #wrapper_name {
|
||||||
type Wrap = ResHandle<#handle_path>;
|
|
||||||
|
|
||||||
fn wrapped_type_id() -> std::any::TypeId {
|
fn wrapped_type_id() -> std::any::TypeId {
|
||||||
TypeId::of::<ResHandle<#handle_path>>()
|
TypeId::of::<ResHandle<#handle_path>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_wrapped(self) -> Self::Wrap {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.into()
|
}.into()
|
||||||
}
|
}
|
|
@ -5,12 +5,9 @@ use syn::{parse_macro_input, Token};
|
||||||
|
|
||||||
mod mat_wrapper;
|
mod mat_wrapper;
|
||||||
mod vec_wrapper;
|
mod vec_wrapper;
|
||||||
use to_lua_macro::to_lua_struct_impl;
|
|
||||||
use vec_wrapper::VecWrapper;
|
use vec_wrapper::VecWrapper;
|
||||||
|
|
||||||
mod lua_macro;
|
mod lua_macro;
|
||||||
mod to_lua_macro;
|
|
||||||
mod field;
|
|
||||||
|
|
||||||
mod handle_macro;
|
mod handle_macro;
|
||||||
|
|
||||||
|
@ -27,11 +24,6 @@ pub fn lua_wrap_handle(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
||||||
lua_wrap_handle_impl(input)
|
lua_wrap_handle_impl(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn to_lua_convert(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
||||||
to_lua_struct_impl(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct VecExtensionInputs {
|
pub(crate) struct VecExtensionInputs {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub type_path: syn::Path,
|
pub type_path: syn::Path,
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{
|
use syn::{braced, parenthesized, parse_macro_input, punctuated::Punctuated, token, Ident, Path, Token};
|
||||||
braced, parenthesized, parse_macro_input, punctuated::Punctuated, token, Ident, Path, Token,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{field::{Field, FieldType}, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE};
|
use crate::{handle_macro::FieldGetter, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum SkipType {
|
enum SkipType {
|
||||||
/// Skips implementing
|
/// Skips implementing
|
||||||
LuaReflect,
|
LuaReflect
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::parse::Parse for SkipType {
|
impl syn::parse::Parse for SkipType {
|
||||||
|
@ -19,7 +17,9 @@ impl syn::parse::Parse for SkipType {
|
||||||
|
|
||||||
match name_str.as_str() {
|
match name_str.as_str() {
|
||||||
"lua_reflect" => Ok(Self::LuaReflect),
|
"lua_reflect" => Ok(Self::LuaReflect),
|
||||||
_ => Err(syn::Error::new_spanned(name, "unknown skip type")),
|
_ => {
|
||||||
|
Err(syn::Error::new_spanned(name, "unknown skip type"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,21 +43,22 @@ impl MetaMethod {
|
||||||
let mm_str = mm_str.as_str();
|
let mm_str = mm_str.as_str();
|
||||||
match mm_str {
|
match mm_str {
|
||||||
"Add" | "Sub" | "Div" | "Mul" | "Mod" | "Eq" | "Shl" | "Shr" | "BAnd" | "BOr"
|
"Add" | "Sub" | "Div" | "Mul" | "Mod" | "Eq" | "Shl" | "Shr" | "BAnd" | "BOr"
|
||||||
| "BXor" => true,
|
| "BXor" => {
|
||||||
"Unm" | "BNot" | "ToString" => false,
|
true
|
||||||
|
},
|
||||||
|
"Unm" | "BNot" | "ToString" => {
|
||||||
|
false
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the tokens of the body of the metamethod
|
/// returns the tokens of the body of the metamethod
|
||||||
///
|
///
|
||||||
/// Parameters
|
/// Parameters
|
||||||
/// * `metamethod` - The ident of the metamethod that is being implemented.
|
/// * `metamethod` - The ident of the metamethod that is being implemented.
|
||||||
/// * `other` - The tokens of the argument used in the metamethod.
|
/// * `other` - The tokens of the argument used in the metamethod.
|
||||||
fn get_method_body(
|
fn get_method_body(metamethod: &Ident, other: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
metamethod: &Ident,
|
|
||||||
other: proc_macro2::TokenStream,
|
|
||||||
) -> proc_macro2::TokenStream {
|
|
||||||
let mm_str = metamethod.to_string();
|
let mm_str = metamethod.to_string();
|
||||||
let mm_str = mm_str.as_str();
|
let mm_str = mm_str.as_str();
|
||||||
match mm_str {
|
match mm_str {
|
||||||
|
@ -74,17 +75,17 @@ impl MetaMethod {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(this.0 #symbol #other))
|
Ok(Self(this.0 #symbol #other))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"Unm" => {
|
"Unm" => {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(-this.0))
|
Ok(Self(-this.0))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"Eq" => {
|
"Eq" => {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(this.0 == #other)
|
Ok(this.0 == #other)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"Shl" => {
|
"Shl" => {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(this.0 << #other))
|
Ok(Self(this.0 << #other))
|
||||||
|
@ -94,47 +95,41 @@ impl MetaMethod {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(this.0 >> #other))
|
Ok(Self(this.0 >> #other))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"BAnd" | "BOr" | "BXor" => {
|
"BAnd" | "BOr" | "BXor" => {
|
||||||
let symbol = match mm_str {
|
let symbol = match mm_str {
|
||||||
"BAnd" => {
|
"BAnd" => {
|
||||||
quote!(&)
|
quote!(&)
|
||||||
}
|
},
|
||||||
"BOr" => {
|
"BOr" => {
|
||||||
quote!(|)
|
quote!(|)
|
||||||
}
|
},
|
||||||
"BXor" => {
|
"BXor" => {
|
||||||
quote!(^)
|
quote!(^)
|
||||||
}
|
},
|
||||||
_ => unreachable!(), // the string was just checked to be one of these
|
_ => unreachable!() // the string was just checked to be one of these
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(this.0 #symbol #other))
|
Ok(Self(this.0 #symbol #other))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"BNot" => {
|
"BNot" => {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(Self(!this.0))
|
Ok(Self(!this.0))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"ToString" => {
|
"ToString" => {
|
||||||
quote! {
|
quote! {
|
||||||
Ok(format!("{:?}", this.0))
|
Ok(format!("{:?}", this.0))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {
|
_ => syn::Error::new_spanned(metamethod,
|
||||||
syn::Error::new_spanned(metamethod, "unsupported auto implementation of metamethod")
|
"unsupported auto implementation of metamethod").to_compile_error(),
|
||||||
.to_compile_error()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_body_for_arg(
|
fn get_body_for_arg(mt_ident: &Ident, arg_ident: &Ident, arg_param: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
mt_ident: &Ident,
|
|
||||||
arg_ident: &Ident,
|
|
||||||
arg_param: proc_macro2::TokenStream,
|
|
||||||
) -> proc_macro2::TokenStream {
|
|
||||||
let other: proc_macro2::TokenStream = if Self::is_arg_wrapper(arg_ident) {
|
let other: proc_macro2::TokenStream = if Self::is_arg_wrapper(arg_ident) {
|
||||||
// Lua wrappers must be dereferenced
|
// Lua wrappers must be dereferenced
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -172,6 +167,7 @@ impl MetaMethod {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if self.arg.len() == 1 {
|
} else if self.arg.len() == 1 {
|
||||||
let first = self.arg.iter().next().unwrap();
|
let first = self.arg.iter().next().unwrap();
|
||||||
let body = Self::get_body_for_arg(&self.name, first, quote!(v));
|
let body = Self::get_body_for_arg(&self.name, first, quote!(v));
|
||||||
|
@ -188,41 +184,38 @@ impl MetaMethod {
|
||||||
let is = i.to_string();
|
let is = i.to_string();
|
||||||
let is = is.as_str();
|
let is = is.as_str();
|
||||||
match is {
|
match is {
|
||||||
"u8" | "u16" | "u32" | "u64" | "u128" | "i8" | "i16" | "i32" | "i64"
|
"u8" | "u16" | "u32" | "u64" | "u128"
|
||||||
| "i128" | "f32" | "f64" => true,
|
| "i8" | "i16" | "i32" | "i64" | "i128"
|
||||||
|
| "f32" | "f64" => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(num_ident) = num_ident {
|
if let Some(num_ident) = num_ident {
|
||||||
let body =
|
let body = Self::get_body_for_arg(&self.name, num_ident, quote!(n as #num_ident));
|
||||||
Self::get_body_for_arg(&self.name, num_ident, quote!(n as #num_ident));
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
mlua::Value::Number(n) => {
|
mlua::Value::Number(n) => {
|
||||||
#body
|
#body
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else { quote!() }
|
||||||
quote!()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let userdata_arm = {
|
let userdata_arm = {
|
||||||
let wrappers: Vec<&Ident> = self
|
let wrappers: Vec<&Ident> = self.arg.iter()
|
||||||
.arg
|
|
||||||
.iter()
|
|
||||||
.filter(|i| Self::is_arg_wrapper(i))
|
.filter(|i| Self::is_arg_wrapper(i))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let if_statements = wrappers.iter().map(|i| {
|
let if_statements = wrappers.iter().map(|i| {
|
||||||
let body = Self::get_method_body(&self.name, quote!(other.0));
|
let body = Self::get_method_body(&self.name, quote!(other.0));
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
if let Ok(other) = ud.borrow::<#i>() {
|
if let Ok(other) = ud.borrow::<#i>() {
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -233,7 +226,7 @@ impl MetaMethod {
|
||||||
// try to get the name of the userdata for the error message
|
// try to get the name of the userdata for the error message
|
||||||
if let Ok(mt) = ud.metatable() {
|
if let Ok(mt) = ud.metatable() {
|
||||||
if let Ok(name) = mt.get::<String>("__name") {
|
if let Ok(name) = mt.get::<String>("__name") {
|
||||||
return Err(mlua::Error::BadArgument {
|
return Err(mlua::Error::BadArgument {
|
||||||
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
||||||
pos: 2,
|
pos: 2,
|
||||||
name: Some("rhs".to_string()),
|
name: Some("rhs".to_string()),
|
||||||
|
@ -243,8 +236,8 @@ impl MetaMethod {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(mlua::Error::BadArgument {
|
Err(mlua::Error::BadArgument {
|
||||||
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
||||||
pos: 2,
|
pos: 2,
|
||||||
name: Some("rhs".to_string()),
|
name: Some("rhs".to_string()),
|
||||||
|
@ -256,13 +249,13 @@ impl MetaMethod {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (mlua::Value,)| {
|
methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (mlua::Value,)| {
|
||||||
match v {
|
match v {
|
||||||
#number_arm
|
#number_arm
|
||||||
#userdata_arm
|
#userdata_arm
|
||||||
_ => Err(mlua::Error::BadArgument {
|
_ => Err(mlua::Error::BadArgument {
|
||||||
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
|
||||||
pos: 2,
|
pos: 2,
|
||||||
name: Some("rhs".to_string()),
|
name: Some("rhs".to_string()),
|
||||||
|
@ -281,15 +274,17 @@ impl syn::parse::Parse for MetaMethod {
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
let name: Ident = input.parse()?;
|
let name: Ident = input.parse()?;
|
||||||
|
|
||||||
let mut s = Self { name, arg: vec![] };
|
let mut s = Self {
|
||||||
|
name,
|
||||||
|
arg: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
// try to parse args
|
// try to parse args
|
||||||
if input.peek(syn::token::Paren) {
|
if input.peek(syn::token::Paren) {
|
||||||
let content;
|
let content;
|
||||||
let _parens: syn::token::Paren = parenthesized!(content in input);
|
let _parens: syn::token::Paren = parenthesized!(content in input);
|
||||||
|
|
||||||
let arg: Punctuated<Ident, Token![,]> =
|
let arg: Punctuated<Ident, Token![,]> = content.parse_terminated(Ident::parse, Token![,])?;
|
||||||
content.parse_terminated(Ident::parse, Token![,])?;
|
|
||||||
s.arg = arg.into_iter().collect(); // convert to Vec<Ident>
|
s.arg = arg.into_iter().collect(); // convert to Vec<Ident>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +296,8 @@ struct WrapUsage {
|
||||||
type_path: syn::Path,
|
type_path: syn::Path,
|
||||||
/// The extra derives of the type.
|
/// The extra derives of the type.
|
||||||
override_name: Option<Ident>,
|
override_name: Option<Ident>,
|
||||||
auto_fields: Vec<Field>,
|
auto_fields: Vec<Ident>,
|
||||||
|
manual_field_getters: Vec<FieldGetter>,
|
||||||
auto_derives: Vec<Ident>,
|
auto_derives: Vec<Ident>,
|
||||||
auto_new: bool,
|
auto_new: bool,
|
||||||
meta_methods: Vec<MetaMethod>,
|
meta_methods: Vec<MetaMethod>,
|
||||||
|
@ -319,6 +315,7 @@ impl syn::parse::Parse for WrapUsage {
|
||||||
override_name: None,
|
override_name: None,
|
||||||
auto_fields: vec![],
|
auto_fields: vec![],
|
||||||
auto_derives: vec![],
|
auto_derives: vec![],
|
||||||
|
manual_field_getters: vec![],
|
||||||
extra_fields: None,
|
extra_fields: None,
|
||||||
extra_methods: None,
|
extra_methods: None,
|
||||||
auto_new: false,
|
auto_new: false,
|
||||||
|
@ -327,7 +324,7 @@ impl syn::parse::Parse for WrapUsage {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_ident = None;
|
let mut new_ident = None;
|
||||||
|
|
||||||
while input.peek(Token![,]) {
|
while input.peek(Token![,]) {
|
||||||
let _: Token![,] = input.parse()?;
|
let _: Token![,] = input.parse()?;
|
||||||
|
|
||||||
|
@ -342,72 +339,73 @@ impl syn::parse::Parse for WrapUsage {
|
||||||
|
|
||||||
let name: Ident = input.parse()?;
|
let name: Ident = input.parse()?;
|
||||||
s.override_name = Some(name);
|
s.override_name = Some(name);
|
||||||
}
|
},
|
||||||
"new" => {
|
"new" => {
|
||||||
s.auto_new = true;
|
s.auto_new = true;
|
||||||
new_ident = Some(ident.clone());
|
new_ident = Some(ident.clone());
|
||||||
}
|
},
|
||||||
"skip" => {
|
"skip" => {
|
||||||
let content;
|
let content;
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
let _parens: token::Paren = parenthesized!(content in input);
|
||||||
|
|
||||||
let terminated = content.parse_terminated(SkipType::parse, Token![,])?;
|
let terminated = content.parse_terminated(SkipType::parse, Token![,])?;
|
||||||
s.skips = terminated.into_iter().collect();
|
s.skips = terminated.into_iter().collect();
|
||||||
}
|
},
|
||||||
"derives" => {
|
"derives" => {
|
||||||
if input.peek(token::Paren) {
|
if input.peek(token::Paren) {
|
||||||
let content;
|
let content;
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
let _parens: token::Paren = parenthesized!(content in input);
|
||||||
|
|
||||||
let derives: Punctuated<Ident, Token![,]> =
|
let derives: Punctuated<Ident, Token![,]> = content.parse_terminated(Ident::parse, Token![,])?;
|
||||||
content.parse_terminated(Ident::parse, Token![,])?;
|
|
||||||
s.auto_derives = derives.into_iter().collect();
|
s.auto_derives = derives.into_iter().collect();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
"fields" => {
|
"fields" => {
|
||||||
|
if input.peek(token::Paren) {
|
||||||
|
let content;
|
||||||
|
let _parens: token::Paren = parenthesized!(content in input);
|
||||||
|
|
||||||
|
let fields: Punctuated<Ident, Token![,]> = content.parse_terminated(Ident::parse, Token![,])?;
|
||||||
|
s.auto_fields = fields.into_iter().collect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metamethods" => {
|
||||||
|
if input.peek(token::Paren) {
|
||||||
|
let content;
|
||||||
|
let _bracket: token::Paren = parenthesized!(content in input);
|
||||||
|
|
||||||
|
let meta_methods: Punctuated<MetaMethod, Token![,]> = content.parse_terminated(MetaMethod::parse, Token![,])?;
|
||||||
|
s.meta_methods = meta_methods.into_iter().collect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_fields" => {
|
||||||
|
let _eq: Token![=] = input.parse()?;
|
||||||
|
s.extra_fields = Some(input.parse::<syn::Block>()?);
|
||||||
|
},
|
||||||
|
"extra_methods" => {
|
||||||
|
let _eq: Token![=] = input.parse()?;
|
||||||
|
s.extra_methods = Some(input.parse::<syn::Block>()?);
|
||||||
|
},
|
||||||
|
"field_getters" => {
|
||||||
let _eq: Token![=] = input.parse()?;
|
let _eq: Token![=] = input.parse()?;
|
||||||
|
|
||||||
if input.peek(token::Brace) {
|
if input.peek(token::Brace) {
|
||||||
let content;
|
let content;
|
||||||
let _braced: token::Brace = braced!(content in input);
|
let _braced: token::Brace = braced!(content in input);
|
||||||
|
|
||||||
let terminated = content.parse_terminated(Field::parse, Token![,])?;
|
let terminated = content.parse_terminated(FieldGetter::parse, Token![,])?;
|
||||||
s.auto_fields.extend(terminated.into_iter());
|
s.manual_field_getters = terminated.into_iter().collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"metamethods" => {
|
|
||||||
if input.peek(token::Paren) {
|
|
||||||
let content;
|
|
||||||
let _bracket: token::Paren = parenthesized!(content in input);
|
|
||||||
|
|
||||||
let meta_methods: Punctuated<MetaMethod, Token![,]> =
|
|
||||||
content.parse_terminated(MetaMethod::parse, Token![,])?;
|
|
||||||
s.meta_methods = meta_methods.into_iter().collect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"extra_fields" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
s.extra_fields = Some(input.parse::<syn::Block>()?);
|
|
||||||
}
|
|
||||||
"extra_methods" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
s.extra_methods = Some(input.parse::<syn::Block>()?);
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(ident, format!("unknown wrapper command: '{}'", ident_str)));
|
||||||
ident,
|
|
||||||
format!("unknown wrapper command: '{}'", ident_str),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.auto_new && s.auto_fields.is_empty() {
|
if s.auto_new && s.auto_fields.is_empty() {
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(new_ident.unwrap(), "must specify 'fields' when auto creating new function"));
|
||||||
new_ident.unwrap(),
|
|
||||||
"must specify 'fields' when auto creating new function",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(s)
|
Ok(s)
|
||||||
|
@ -419,50 +417,51 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
let input = parse_macro_input!(input as WrapUsage);
|
let input = parse_macro_input!(input as WrapUsage);
|
||||||
|
|
||||||
let path: Path = input.type_path;
|
let path: Path = input.type_path;
|
||||||
let type_name = &path
|
let type_name = &path.segments.last()
|
||||||
.segments
|
|
||||||
.last()
|
|
||||||
.expect("Failure to find typename in macro usage!")
|
.expect("Failure to find typename in macro usage!")
|
||||||
.ident;
|
.ident;
|
||||||
let wrapper_typename = input
|
let wrapper_typename = input.override_name
|
||||||
.override_name
|
|
||||||
.unwrap_or_else(|| Ident::new(&format!("Lua{}", type_name), Span::call_site()));
|
.unwrap_or_else(|| Ident::new(&format!("Lua{}", type_name), Span::call_site()));
|
||||||
|
|
||||||
let derive_idents_iter = input.auto_derives.iter();
|
let derive_idents_iter = input.auto_derives.iter();
|
||||||
let extra_fields = input.extra_fields;
|
let extra_fields = input.extra_fields;
|
||||||
let extra_methods = input.extra_methods;
|
let extra_methods = input.extra_methods;
|
||||||
|
|
||||||
|
let field_get_set_pairs = input.auto_fields.iter().map(|i| {
|
||||||
|
let is = i.to_string();
|
||||||
|
quote! {
|
||||||
|
fields.add_field_method_get(#is, |_, this| {
|
||||||
|
Ok(this.#i)
|
||||||
|
});
|
||||||
|
fields.add_field_method_set(#is, |_, this, #i| {
|
||||||
|
this.#i = #i;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// the tokens for the new function
|
// the tokens for the new function
|
||||||
let new_func_tokens = if input.auto_new {
|
let new_func_tokens = if input.auto_new {
|
||||||
let arg_names = input
|
let arg_names = input.auto_fields.iter().map(|i| {
|
||||||
.auto_fields
|
Ident::new(&i.to_string().to_lowercase(), Span::call_site())
|
||||||
.iter()
|
});
|
||||||
.map(|i| Ident::new(&i.field.to_string().to_lowercase(), Span::call_site()));
|
|
||||||
|
|
||||||
let arg_types = input
|
|
||||||
.auto_fields
|
|
||||||
.iter()
|
|
||||||
.map(|i| i.field_ty.get_type_path().unwrap());
|
|
||||||
|
|
||||||
let arg_names_clone = arg_names.clone();
|
let arg_names_clone = arg_names.clone();
|
||||||
let arg_types_clone = arg_types.clone();
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
// arguments for function are not specified since they can be implied from the call
|
// arguments for function are not specified since they can be implied from the call
|
||||||
// to new(...)
|
// to new(...)
|
||||||
methods.add_function("new", |_, ( #(#arg_names_clone),* ): ( #(#arg_types_clone),* ) | {
|
methods.add_function("new", |_, ( #(#arg_names_clone),* )| {
|
||||||
Ok(#wrapper_typename(#path::new( #(#arg_names),* )))
|
Ok(#wrapper_typename(#path::new( #(#arg_names),* )))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
quote!()
|
} else { quote!() };
|
||||||
};
|
|
||||||
|
|
||||||
let meta_methods_tokens = {
|
let meta_methods_tokens = {
|
||||||
let method_tokens = input
|
let method_tokens = input.meta_methods.iter().map(|mm| {
|
||||||
.meta_methods
|
mm.to_tokens(&wrapper_typename)
|
||||||
.iter()
|
});
|
||||||
.map(|mm| mm.to_tokens(&wrapper_typename));
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#(#method_tokens)*
|
#(#method_tokens)*
|
||||||
|
@ -476,80 +475,34 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
methods.add_method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
|
methods.add_method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
|
||||||
Ok(crate::ScriptBorrow::from_component::<#path>(Some(this.0.clone())))
|
Ok(crate::ScriptBorrow::from_component::<#path>(Some(this.0.clone())))
|
||||||
});
|
});
|
||||||
|
|
||||||
methods.add_function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
methods.add_function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
||||||
Ok(crate::ScriptBorrow::from_component::<#path>(None))
|
Ok(crate::ScriptBorrow::from_component::<#path>(None))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for field in input.auto_fields.iter() {
|
let custom_getters = input.manual_field_getters.iter().map(|g| {
|
||||||
if field.field_ty.is_unknown() && !field.skip_setter {
|
|
||||||
return syn::Error::new(
|
|
||||||
field.field.span(),
|
|
||||||
"missing type of field, must be specified to generate setters",
|
|
||||||
)
|
|
||||||
.to_compile_error()
|
|
||||||
.into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fields = input.auto_fields.iter().map(|g| {
|
|
||||||
let field = &g.field;
|
let field = &g.field;
|
||||||
|
|
||||||
let field_getter = match &g.field_ty {
|
let field_creator = match &g.wrapper_type {
|
||||||
FieldType::Wrapped(wrap) => {
|
Some(wrap) => {
|
||||||
quote!(#wrap(this.#field.clone()).into_lua(lua))
|
quote!(#wrap(this.#field).into_lua(lua))
|
||||||
}
|
},
|
||||||
_ => match &g.getter {
|
None => match &g.body {
|
||||||
Some(body) => {
|
Some(body) => {
|
||||||
quote!(#body)
|
quote!(#body)
|
||||||
}
|
},
|
||||||
None => {
|
None => {
|
||||||
quote!(this.#field.clone().into_lua(lua))
|
quote!(this.#field.clone().into_lua(lua))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_setter = if g.skip_setter {
|
|
||||||
quote! {}
|
|
||||||
} else {
|
|
||||||
let fty = g
|
|
||||||
.field_ty
|
|
||||||
.get_type_path()
|
|
||||||
// should be unreachable due to the checks right before this closure
|
|
||||||
.expect("no field type specified");
|
|
||||||
let s = if g.field_ty.is_wrapped() {
|
|
||||||
quote! {
|
|
||||||
this.#field = #field.0.clone();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match &g.setter {
|
|
||||||
Some(body) => {
|
|
||||||
quote!(#body)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
quote! {
|
|
||||||
this.#field = #field.clone();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fields.add_field_method_set(stringify!(#field), |_, this, #field: #fty| {
|
|
||||||
#s
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
fields.add_field_method_get(stringify!(#field), |lua, this| {
|
fields.add_field_method_get(stringify!($field), |lua, this| {
|
||||||
#field_getter
|
#field_creator
|
||||||
});
|
});
|
||||||
#field_setter
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -559,12 +512,12 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
|
|
||||||
impl std::ops::Deref for #wrapper_typename {
|
impl std::ops::Deref for #wrapper_typename {
|
||||||
type Target = #path;
|
type Target = #path;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::DerefMut for #wrapper_typename {
|
impl std::ops::DerefMut for #wrapper_typename {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
|
@ -582,16 +535,13 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
|
|
||||||
impl mlua::UserData for #wrapper_typename {
|
impl mlua::UserData for #wrapper_typename {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||||
use mlua::IntoLua;
|
#(#field_get_set_pairs)*
|
||||||
|
#(#custom_getters)*
|
||||||
#(#fields)*
|
|
||||||
|
|
||||||
#extra_fields
|
#extra_fields
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||||
use mlua::IntoLua;
|
|
||||||
|
|
||||||
#lua_reflects
|
#lua_reflects
|
||||||
|
|
||||||
#new_func_tokens
|
#new_func_tokens
|
||||||
|
@ -601,15 +551,9 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
}
|
}
|
||||||
|
|
||||||
impl lyra_scripting::lua::LuaWrapper for #wrapper_typename {
|
impl lyra_scripting::lua::LuaWrapper for #wrapper_typename {
|
||||||
type Wrap = #path;
|
|
||||||
|
|
||||||
fn wrapped_type_id() -> std::any::TypeId {
|
fn wrapped_type_id() -> std::any::TypeId {
|
||||||
std::any::TypeId::of::<#path>()
|
std::any::TypeId::of::<#path>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_wrapped(self) -> Self::Wrap {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,326 +0,0 @@
|
||||||
use proc_macro2::Span;
|
|
||||||
use syn::{braced, parenthesized, parse_macro_input, punctuated::Punctuated, token, Token};
|
|
||||||
use quote::{quote, ToTokens};
|
|
||||||
use crate::{field::Field, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE};
|
|
||||||
|
|
||||||
fn field_table_setter(field: &Field) -> proc_macro2::TokenStream {
|
|
||||||
let ident = &field.field;
|
|
||||||
|
|
||||||
match &field.setter {
|
|
||||||
Some(set) => {
|
|
||||||
quote! {
|
|
||||||
table.set(stringify!(#ident), #set)?;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
let ty = field.field_ty.get_type_path()
|
|
||||||
.expect("no field type specified");
|
|
||||||
|
|
||||||
let arg = if field.field_ty.is_wrapped() {
|
|
||||||
quote!(#ty(self.#ident))
|
|
||||||
} else { quote!(self.#ident) };
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
table.set(stringify!(#ident), #arg)?;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_table_getter(field: &Field) -> proc_macro2::TokenStream {
|
|
||||||
let ident = &field.field;
|
|
||||||
|
|
||||||
match &field.getter {
|
|
||||||
Some(get) => {
|
|
||||||
quote! {
|
|
||||||
let #ident = #get;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
let ty = field.field_ty.get_type_path()
|
|
||||||
.expect("no field type specified");
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
let #ident: #ty = table.get(stringify!(#ident))?;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wrapper_creation(wrapper: &syn::Ident, type_path: &syn::Path, create: Option<&syn::Block>, fields: &Vec<Field>) -> proc_macro2::TokenStream {
|
|
||||||
|
|
||||||
match create {
|
|
||||||
Some(b) => quote!(#b),
|
|
||||||
None => {
|
|
||||||
/* let field_iter = fields.iter().map(|f| match &f.field_ty {
|
|
||||||
crate::field::FieldType::Type(path) => quote!(#path),
|
|
||||||
crate::field::FieldType::Wrapped(path) => quote!(*#path),
|
|
||||||
_ => todo!()
|
|
||||||
}); */
|
|
||||||
let field_iter = fields.iter().map(|f| {
|
|
||||||
let ident = &f.field;
|
|
||||||
if f.field_ty.is_wrapped() {
|
|
||||||
quote!(#ident: (*#ident).clone())
|
|
||||||
} else {
|
|
||||||
quote!(#ident)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#wrapper(#type_path {
|
|
||||||
#(
|
|
||||||
#field_iter
|
|
||||||
),*
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_reflect_lua_functions(ty: &ReflectType, type_path: &syn::Path, set_data: bool) -> proc_macro2::TokenStream {
|
|
||||||
let data = if set_data {
|
|
||||||
quote!(Some(this.into_wrapped()))
|
|
||||||
} else { quote!(None) };
|
|
||||||
|
|
||||||
match ty {
|
|
||||||
ReflectType::Component => {
|
|
||||||
quote! {
|
|
||||||
Ok(ScriptBorrow::from_component::<#type_path>(#data))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ReflectType::Resource => {
|
|
||||||
quote! {
|
|
||||||
Ok(ScriptBorrow::from_component::<#type_path>(#data))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
enum ReflectType {
|
|
||||||
//Unknown,
|
|
||||||
Component,
|
|
||||||
Resource,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IntoLuaUsage {
|
|
||||||
type_path: syn::Path,
|
|
||||||
override_name: Option<syn::Ident>,
|
|
||||||
table_name: String,
|
|
||||||
derives: Vec<syn::Ident>,
|
|
||||||
fields: Vec<Field>,
|
|
||||||
create: Option<syn::Block>,
|
|
||||||
reflection_type: Option<ReflectType>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl syn::parse::Parse for IntoLuaUsage {
|
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
||||||
let type_path: syn::Path = input.parse()?;
|
|
||||||
let type_ident = &type_path
|
|
||||||
.segments
|
|
||||||
.last()
|
|
||||||
.expect("Failure to find typename in macro usage!")
|
|
||||||
.ident;
|
|
||||||
let lua_name = type_ident.to_string();
|
|
||||||
|
|
||||||
let mut s = Self {
|
|
||||||
type_path,
|
|
||||||
override_name: None,
|
|
||||||
table_name: lua_name,
|
|
||||||
derives: vec![],
|
|
||||||
fields: vec![],
|
|
||||||
create: None,
|
|
||||||
reflection_type: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
while input.peek(Token![,]) {
|
|
||||||
let _: Token![,] = input.parse()?;
|
|
||||||
|
|
||||||
if input.peek(syn::Ident) {
|
|
||||||
let ident: syn::Ident = input.parse()?;
|
|
||||||
let ident_str = ident.to_string();
|
|
||||||
let ident_str = ident_str.as_str();
|
|
||||||
|
|
||||||
match ident_str {
|
|
||||||
"name" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
|
|
||||||
let name: syn::Ident = input.parse()?;
|
|
||||||
s.override_name = Some(name);
|
|
||||||
},
|
|
||||||
"lua_name" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
s.table_name = input.parse::<syn::LitStr>()?.value();
|
|
||||||
},
|
|
||||||
"derives" => {
|
|
||||||
if input.peek(token::Paren) {
|
|
||||||
let content;
|
|
||||||
let _parens: token::Paren = parenthesized!(content in input);
|
|
||||||
|
|
||||||
let derives: Punctuated<syn::Ident, Token![,]> =
|
|
||||||
content.parse_terminated(syn::Ident::parse, Token![,])?;
|
|
||||||
s.derives = derives.into_iter().collect();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fields" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
|
|
||||||
if input.peek(token::Brace) {
|
|
||||||
let content;
|
|
||||||
let _braced: token::Brace = braced!(content in input);
|
|
||||||
|
|
||||||
let terminated = content.parse_terminated(Field::parse, Token![,])?;
|
|
||||||
s.fields.extend(terminated.into_iter());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"create" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
s.create = Some(input.parse()?);
|
|
||||||
},
|
|
||||||
"reflect" => {
|
|
||||||
let _eq: Token![=] = input.parse()?;
|
|
||||||
let ty: syn::Ident = input.parse()?;
|
|
||||||
let ty_str = ty.to_string();
|
|
||||||
let ty_str = ty_str.as_str();
|
|
||||||
|
|
||||||
let ty = match ty_str {
|
|
||||||
"component" => ReflectType::Component,
|
|
||||||
"resource" => ReflectType::Resource,
|
|
||||||
_ => return Err(syn::Error::new_spanned(
|
|
||||||
ident,
|
|
||||||
format!("unknown wrapper type: '{}', expected 'component' or 'resource'", ty_str),
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
|
|
||||||
s.reflection_type = Some(ty);
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
ident,
|
|
||||||
format!("unknown wrapper command: '{}'", ident_str),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.reflection_type.is_none() {
|
|
||||||
return Err(syn::Error::new(
|
|
||||||
input.span(),
|
|
||||||
format!("Wrapper type not specified! Expected 'type=component' or 'type=resource'"),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.table_name.is_empty() {
|
|
||||||
return Err(syn::Error::new(
|
|
||||||
input.span(),
|
|
||||||
format!("No lua table specified. Use 'lua_name=\"Camera\"'"),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
||||||
let input = parse_macro_input!(input as IntoLuaUsage);
|
|
||||||
|
|
||||||
// unwrap is fine since `Some` is ensured in parse impl
|
|
||||||
let reflect_type = input.reflection_type.as_ref().unwrap();
|
|
||||||
let type_path = &input.type_path;
|
|
||||||
let type_name = &type_path
|
|
||||||
.segments
|
|
||||||
.last()
|
|
||||||
.expect("Failure to find typename in macro usage!")
|
|
||||||
.ident;
|
|
||||||
let wrapper = input.override_name
|
|
||||||
.unwrap_or_else(|| syn::Ident::new(&format!("Lua{}", type_name), Span::call_site()));
|
|
||||||
|
|
||||||
let derives_iter = input.derives.into_iter();
|
|
||||||
|
|
||||||
let lua_name = &input.table_name;
|
|
||||||
let field_getters_iter = input.fields.iter().map(|f| field_table_getter(f));
|
|
||||||
let field_setters_iter = input.fields.iter().map(|f| field_table_setter(f));
|
|
||||||
let struct_creator = wrapper_creation(&wrapper, type_path, input.create.as_ref(), &input.fields);
|
|
||||||
let reflect_fn = get_reflect_lua_functions(reflect_type, &input.type_path, true);
|
|
||||||
let reflect_type_fn = get_reflect_lua_functions(reflect_type, &input.type_path, false);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[derive(Clone, #(#derives_iter),*)]
|
|
||||||
pub struct #wrapper(pub(crate) #type_path);
|
|
||||||
|
|
||||||
impl std::ops::Deref for #wrapper {
|
|
||||||
type Target = #type_path;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::DerefMut for #wrapper {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl mlua::FromLua for #wrapper {
|
|
||||||
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
|
|
||||||
let ty = val.type_name();
|
|
||||||
let table = val.as_table().ok_or(mlua::Error::FromLuaConversionError {
|
|
||||||
from: ty,
|
|
||||||
to: "Table".into(),
|
|
||||||
message: Some("expected Table".into()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
#(
|
|
||||||
#field_getters_iter
|
|
||||||
)*
|
|
||||||
|
|
||||||
Ok(#struct_creator)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl mlua::IntoLua for #wrapper {
|
|
||||||
fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
|
|
||||||
let table = lua.create_table()?;
|
|
||||||
#(
|
|
||||||
#field_setters_iter
|
|
||||||
)*
|
|
||||||
|
|
||||||
table.set(
|
|
||||||
#FN_NAME_INTERNAL_REFLECT,
|
|
||||||
lua.create_function(|_, this: Self| {
|
|
||||||
#reflect_fn
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
table.set(
|
|
||||||
#FN_NAME_INTERNAL_REFLECT_TYPE,
|
|
||||||
lua.create_function(|_, ()| {
|
|
||||||
#reflect_type_fn
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
table.set(mlua::MetaMethod::Type.name(), #lua_name)?;
|
|
||||||
|
|
||||||
Ok(mlua::Value::Table(table))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LuaWrapper for #wrapper {
|
|
||||||
type Wrap = #type_path;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn wrapped_type_id() -> std::any::TypeId {
|
|
||||||
std::any::TypeId::of::<#type_path>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_wrapped(self) -> Self::Wrap {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}.into_token_stream().into()
|
|
||||||
}
|
|
|
@ -60,10 +60,4 @@ WrappingMode = {
|
||||||
CLAMP_TO_EDGE = "clamp_to_edge",
|
CLAMP_TO_EDGE = "clamp_to_edge",
|
||||||
MIRRORED_REPEAT = "mirrored_repeat",
|
MIRRORED_REPEAT = "mirrored_repeat",
|
||||||
REPEAT = "repeat",
|
REPEAT = "repeat",
|
||||||
}
|
|
||||||
|
|
||||||
---@enum CameraProjectionMode
|
|
||||||
CameraProjectionMode = {
|
|
||||||
PERSPECTIVE = "perspective",
|
|
||||||
ORTHOGRAPHIC = "orthographic",
|
|
||||||
}
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
---@meta
|
|
||||||
|
|
||||||
---@class Camera: userdata
|
|
||||||
Camera = {
|
|
||||||
---The position of the camera
|
|
||||||
---@type Transform
|
|
||||||
transform = nil,
|
|
||||||
---The field of view of the camera
|
|
||||||
---@type Angle
|
|
||||||
fov = nil,
|
|
||||||
---The projection mode the camera.
|
|
||||||
---Can be used to specify if the camera is 2D (orthographic), or 3D (perspective).
|
|
||||||
---@type CameraProjectionMode
|
|
||||||
mode = nil,
|
|
||||||
---Flag to enable some debug rendering stuff.
|
|
||||||
---@type boolean
|
|
||||||
debug = nil,
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
---@meta
|
|
||||||
|
|
||||||
---@class Angle: userdata
|
|
||||||
Angle = {}
|
|
||||||
|
|
||||||
---Create a new angle in degrees.
|
|
||||||
---@param deg number
|
|
||||||
function Angle.new_degrees(deg) end
|
|
||||||
---Create a new angle in radians.
|
|
||||||
---@param rad number
|
|
||||||
function Angle.new_radians(rad) end
|
|
||||||
|
|
||||||
---Get the angle in radians.
|
|
||||||
---
|
|
||||||
---Will convert from degrees automatically.
|
|
||||||
---
|
|
||||||
---@return number radians
|
|
||||||
function Angle:radians() end
|
|
||||||
|
|
||||||
---Get the angle in degrees.
|
|
||||||
---
|
|
||||||
---Will convert from radians automatically.
|
|
||||||
---
|
|
||||||
---@return number degrees
|
|
||||||
function Angle:degrees() end
|
|
|
@ -131,11 +131,6 @@ pub trait RegisterLuaType {
|
||||||
fn register_lua_convert<T>(&mut self)
|
fn register_lua_convert<T>(&mut self)
|
||||||
where
|
where
|
||||||
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static;
|
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static;
|
||||||
|
|
||||||
fn register_lua_convert_component<T>(&mut self, name: &str)
|
|
||||||
where
|
|
||||||
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static,
|
|
||||||
T::Wrap: lyra_ecs::Component + Reflect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterLuaType for World {
|
impl RegisterLuaType for World {
|
||||||
|
@ -170,18 +165,6 @@ impl RegisterLuaType for World {
|
||||||
let reg_type = registry.get_type_or_default(T::wrapped_type_id());
|
let reg_type = registry.get_type_or_default(T::wrapped_type_id());
|
||||||
reg_type.add_data(ReflectLuaProxy::from_as_and_from_lua::<T>());
|
reg_type.add_data(ReflectLuaProxy::from_as_and_from_lua::<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_lua_convert_component<T>(&mut self, name: &str)
|
|
||||||
where
|
|
||||||
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static,
|
|
||||||
T::Wrap: lyra_ecs::Component + Reflect
|
|
||||||
{
|
|
||||||
self.register_lua_convert::<T>();
|
|
||||||
|
|
||||||
let mut lookup = self.get_resource_or_default::<LuaTableProxyLookup>();
|
|
||||||
lookup.comp_info_from_name.insert(name.into(), lyra_ecs::ComponentInfo::new::<T::Wrap>());
|
|
||||||
lookup.typeid_from_name.insert(name.into(), std::any::TypeId::of::<T::Wrap>());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl mlua::FromLua for ScriptBorrow {
|
impl mlua::FromLua for ScriptBorrow {
|
||||||
|
|
|
@ -4,9 +4,7 @@ use lyra_ecs::ResourceObject;
|
||||||
use lyra_reflect::{Reflect, TypeRegistry};
|
use lyra_reflect::{Reflect, TypeRegistry};
|
||||||
use lyra_resource::gltf::Gltf;
|
use lyra_resource::gltf::Gltf;
|
||||||
|
|
||||||
use crate::{lua::{wrappers::*, LuaContext, LuaWrapper, ReflectLuaProxy, RegisterLuaType, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptApiProvider, ScriptBorrow, ScriptData, ScriptDynamicBundle, ScriptWorldPtr};
|
use crate::{lua::{wrappers::{LuaActionHandler, LuaDeltaTime, LuaGltfHandle, LuaResHandleToComponent, LuaSceneHandle, LuaWindow}, LuaContext, ReflectLuaProxy, RegisterLuaType, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptApiProvider, ScriptBorrow, ScriptData, ScriptDynamicBundle, ScriptWorldPtr};
|
||||||
|
|
||||||
//fn register_lua_proxy::<T:
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LyraEcsApiProvider;
|
pub struct LyraEcsApiProvider;
|
||||||
|
@ -19,8 +17,6 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
world.register_lua_wrapper::<LuaSceneHandle>();
|
world.register_lua_wrapper::<LuaSceneHandle>();
|
||||||
world.register_lua_wrapper::<LuaActionHandler>();
|
world.register_lua_wrapper::<LuaActionHandler>();
|
||||||
world.register_lua_wrapper::<LuaWindow>();
|
world.register_lua_wrapper::<LuaWindow>();
|
||||||
world.register_lua_convert_component::<LuaCamera>("Camera");
|
|
||||||
world.register_lua_convert_component::<LuaFreeFlyCamera>("FreeFlyCamera");
|
|
||||||
|
|
||||||
let mut registry = world.get_resource_mut::<TypeRegistry>().unwrap();
|
let mut registry = world.get_resource_mut::<TypeRegistry>().unwrap();
|
||||||
|
|
||||||
|
@ -37,6 +33,8 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
reg_type.add_data(l);
|
reg_type.add_data(l);
|
||||||
|
|
||||||
|
//reg_type.add_data(ReflectLuaProxy::from_lua_proxy::<LuaGltfHandle>());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||||
|
@ -53,9 +51,6 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
||||||
globals.set("ActionHandler", ctx.create_proxy::<LuaActionHandler>()?)?;
|
globals.set("ActionHandler", ctx.create_proxy::<LuaActionHandler>()?)?;
|
||||||
globals.set("Window", ctx.create_proxy::<LuaWindow>()?)?;
|
globals.set("Window", ctx.create_proxy::<LuaWindow>()?)?;
|
||||||
|
|
||||||
expose_table_wrapper::<LuaCamera>(&ctx, &globals, "Camera")?;
|
|
||||||
expose_table_wrapper::<LuaFreeFlyCamera>(&ctx, &globals, "FreeFlyCamera")?;
|
|
||||||
|
|
||||||
let dt_table = create_reflect_table::<lyra_game::DeltaTime>(&ctx)?;
|
let dt_table = create_reflect_table::<lyra_game::DeltaTime>(&ctx)?;
|
||||||
globals.set("DeltaTime", dt_table)?;
|
globals.set("DeltaTime", dt_table)?;
|
||||||
|
|
||||||
|
@ -78,38 +73,4 @@ fn create_reflect_table<T: Reflect + ResourceObject + Default + 'static>(lua: &m
|
||||||
})?)?;
|
})?)?;
|
||||||
|
|
||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
|
||||||
|
|
||||||
fn create_reflect_comp_table<T>(lua: &mlua::Lua, name: &str) -> mlua::Result<mlua::Table>
|
|
||||||
where
|
|
||||||
T: LuaWrapper + mlua::FromLua,
|
|
||||||
T::Wrap: lyra_ecs::Component + Reflect
|
|
||||||
{
|
|
||||||
let table = lua.create_table()?;
|
|
||||||
table.set(FN_NAME_INTERNAL_REFLECT, lua.create_function(|_, this: T| {
|
|
||||||
Ok(ScriptBorrow::from_component::<T::Wrap>(Some(this.into_wrapped())))
|
|
||||||
})?)?;
|
|
||||||
|
|
||||||
table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| {
|
|
||||||
Ok(ScriptBorrow::from_component::<T::Wrap>(None))
|
|
||||||
})?)?;
|
|
||||||
|
|
||||||
table.set(mlua::MetaMethod::Type.name(), name)?;
|
|
||||||
|
|
||||||
|
|
||||||
Ok(table)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Expose a wrapper that converts to/from a lua type.
|
|
||||||
///
|
|
||||||
/// This creates the reflection functions on a table specified in globals.
|
|
||||||
/// The table name is set to `name`, which is also how the script will use the table.
|
|
||||||
fn expose_table_wrapper<T>(lua: &mlua::Lua, globals: &mlua::Table, name: &str) -> mlua::Result<()>
|
|
||||||
where
|
|
||||||
T: LuaWrapper + mlua::FromLua,
|
|
||||||
T::Wrap: lyra_ecs::Component + Reflect
|
|
||||||
{
|
|
||||||
let table = create_reflect_comp_table::<T>(&lua, name)?;
|
|
||||||
globals.set(name, table)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use lyra_ecs::World;
|
use lyra_ecs::World;
|
||||||
use crate::lua::wrappers::{LuaAngle, LuaQuat, LuaTransform, LuaVec2, LuaVec3};
|
use crate::lua::wrappers::{LuaQuat, LuaTransform, LuaVec3, LuaVec2};
|
||||||
use crate::ScriptData;
|
use crate::ScriptData;
|
||||||
use crate::lua::RegisterLuaType;
|
use crate::lua::RegisterLuaType;
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ impl ScriptApiProvider for LyraMathApiProvider {
|
||||||
world.register_lua_wrapper::<LuaVec3>();
|
world.register_lua_wrapper::<LuaVec3>();
|
||||||
world.register_lua_wrapper::<LuaQuat>();
|
world.register_lua_wrapper::<LuaQuat>();
|
||||||
world.register_lua_wrapper::<LuaTransform>();
|
world.register_lua_wrapper::<LuaTransform>();
|
||||||
world.register_lua_wrapper::<LuaAngle>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
|
@ -30,7 +29,6 @@ impl ScriptApiProvider for LyraMathApiProvider {
|
||||||
globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
|
globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
|
||||||
globals.set("Quat", ctx.create_proxy::<LuaQuat>()?)?;
|
globals.set("Quat", ctx.create_proxy::<LuaQuat>()?)?;
|
||||||
globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
|
globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
|
||||||
globals.set("Angle", ctx.create_proxy::<LuaAngle>()?)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,8 @@ use crate::{ScriptBorrow, ScriptDynamicBundle};
|
||||||
use super::{Error, FN_NAME_INTERNAL_REFLECT};
|
use super::{Error, FN_NAME_INTERNAL_REFLECT};
|
||||||
|
|
||||||
pub trait LuaWrapper {
|
pub trait LuaWrapper {
|
||||||
type Wrap: Reflect + 'static;
|
|
||||||
|
|
||||||
/// The type id of the wrapped type.
|
/// The type id of the wrapped type.
|
||||||
fn wrapped_type_id() -> TypeId;
|
fn wrapped_type_id() -> TypeId;
|
||||||
fn into_wrapped(self) -> Self::Wrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that used to convert something into lua, or to set something to a value from lua.
|
/// A trait that used to convert something into lua, or to set something to a value from lua.
|
||||||
|
|
|
@ -129,29 +129,28 @@ fn wrapping_mode_to_str(wm: WrappingMode) -> &'static str {
|
||||||
wrap_lua_struct!(lyra_resource::TextureSampler,
|
wrap_lua_struct!(lyra_resource::TextureSampler,
|
||||||
// this can be safely skipped since it wont be a component or resource.
|
// this can be safely skipped since it wont be a component or resource.
|
||||||
skip(lua_reflect),
|
skip(lua_reflect),
|
||||||
fields={
|
field_getters={
|
||||||
// don't need to specify field types since setters are skipped
|
(mag_filter, {
|
||||||
(mag_filter, skip_set, get={
|
|
||||||
this.mag_filter.map(|f| filter_mode_to_str(f))
|
this.mag_filter.map(|f| filter_mode_to_str(f))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
(min_filter, skip_set, get={
|
(min_filter, {
|
||||||
this.min_filter.map(|f| filter_mode_to_str(f))
|
this.min_filter.map(|f| filter_mode_to_str(f))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
(mipmap_filter, skip_set, get={
|
(mipmap_filter, {
|
||||||
this.mipmap_filter.map(|f| filter_mode_to_str(f))
|
this.mipmap_filter.map(|f| filter_mode_to_str(f))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
(wrap_u, skip_set, get={
|
(wrap_u, {
|
||||||
wrapping_mode_to_str(this.wrap_u)
|
wrapping_mode_to_str(this.wrap_u)
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
(wrap_v, skip_set, get={
|
(wrap_v, {
|
||||||
wrapping_mode_to_str(this.wrap_v)
|
wrapping_mode_to_str(this.wrap_v)
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
(wrap_w, skip_set, get={
|
(wrap_w, {
|
||||||
wrapping_mode_to_str(this.wrap_w)
|
wrapping_mode_to_str(this.wrap_w)
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
}),
|
||||||
|
@ -161,29 +160,31 @@ wrap_lua_struct!(lyra_resource::TextureSampler,
|
||||||
wrap_lua_struct!(lyra_resource::gltf::PbrGlossiness,
|
wrap_lua_struct!(lyra_resource::gltf::PbrGlossiness,
|
||||||
// this can be safely skipped since it wont be a component or resource.
|
// this can be safely skipped since it wont be a component or resource.
|
||||||
skip(lua_reflect),
|
skip(lua_reflect),
|
||||||
fields={
|
field_getters={
|
||||||
(diffuse_color: wrap(crate::lua::wrappers::LuaVec4), skip_set),
|
(diffuse_color, wrapper=crate::lua::wrappers::LuaVec4),
|
||||||
(specular: wrap(crate::lua::wrappers::LuaVec3), skip_set),
|
(specular, wrapper=crate::lua::wrappers::LuaVec3),
|
||||||
(glossiness, skip_set),
|
glossiness,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
wrap_lua_struct!(lyra_resource::gltf::Specular,
|
wrap_lua_struct!(lyra_resource::gltf::Specular,
|
||||||
// this can be safely skipped since it wont be a component or resource.
|
// this can be safely skipped since it wont be a component or resource.
|
||||||
skip(lua_reflect),
|
skip(lua_reflect),
|
||||||
fields={
|
field_getters={
|
||||||
(factor, skip_set),
|
factor,
|
||||||
(color_factor: wrap(crate::lua::wrappers::LuaVec3), skip_set),
|
(color_factor, wrapper=crate::lua::wrappers::LuaVec3),
|
||||||
(texture, skip_set, get={
|
},
|
||||||
|
extra_fields={
|
||||||
|
fields.add_field_method_get("texture", |lua, this| {
|
||||||
this.texture.clone()
|
this.texture.clone()
|
||||||
.map(|t| LuaTextureHandle(t))
|
.map(|t| LuaTextureHandle(t))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
}),
|
});
|
||||||
(color_texture, skip_set, get={
|
fields.add_field_method_get("color_texture", |lua, this| {
|
||||||
this.color_texture.clone()
|
this.color_texture.clone()
|
||||||
.map(|t| LuaTextureHandle(t))
|
.map(|t| LuaTextureHandle(t))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
use crate::{
|
|
||||||
lua::{
|
|
||||||
wrappers::{LuaAngle, LuaTransform},
|
|
||||||
LuaWrapper
|
|
||||||
},
|
|
||||||
ScriptBorrow,
|
|
||||||
};
|
|
||||||
use lyra_game::{render::camera::CameraProjectionMode, scene::CameraComponent};
|
|
||||||
use lyra_reflect::Enum;
|
|
||||||
use lyra_scripting_derive::to_lua_convert;
|
|
||||||
|
|
||||||
fn projection_mode_from_str(s: &str) -> Option<CameraProjectionMode> {
|
|
||||||
match s {
|
|
||||||
"perspective" => Some(CameraProjectionMode::Perspective),
|
|
||||||
"orthographic" => Some(CameraProjectionMode::Orthographic),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
to_lua_convert!(
|
|
||||||
// Struct that is being wrapped
|
|
||||||
CameraComponent,
|
|
||||||
// Name of wrapping struct
|
|
||||||
name=LuaCamera,
|
|
||||||
// The name of the type in Lua
|
|
||||||
lua_name="Camera",
|
|
||||||
// Reflection type, can be 'component' or 'resource'
|
|
||||||
reflect=component,
|
|
||||||
fields={
|
|
||||||
transform: wrap(LuaTransform),
|
|
||||||
fov: wrap(LuaAngle),
|
|
||||||
(
|
|
||||||
mode,
|
|
||||||
// Get the table from the value, result must be `CameraProjectionMode`
|
|
||||||
get={
|
|
||||||
let mode: String = table.get("mode")?;
|
|
||||||
projection_mode_from_str(&mode).unwrap()
|
|
||||||
},
|
|
||||||
// Get the value from self, result must be the type in Lua, here its `String`.
|
|
||||||
set={
|
|
||||||
self.mode.variant_name().to_lowercase()
|
|
||||||
}
|
|
||||||
),
|
|
||||||
debug: bool
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -34,15 +34,7 @@ impl mlua::IntoLua for LuaDeltaTime {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaWrapper for LuaDeltaTime {
|
impl LuaWrapper for LuaDeltaTime {
|
||||||
type Wrap = DeltaTime;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn wrapped_type_id() -> std::any::TypeId {
|
fn wrapped_type_id() -> std::any::TypeId {
|
||||||
TypeId::of::<DeltaTime>()
|
TypeId::of::<DeltaTime>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_wrapped(self) -> Self::Wrap {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
use crate::{lua::LuaWrapper, ScriptBorrow};
|
|
||||||
use lyra_game::scene::FreeFlyCamera;
|
|
||||||
use lyra_scripting_derive::to_lua_convert;
|
|
||||||
|
|
||||||
to_lua_convert!(
|
|
||||||
// Struct that is being wrapped
|
|
||||||
FreeFlyCamera,
|
|
||||||
// Reflection type, can be 'component' or 'resource'
|
|
||||||
reflect=component,
|
|
||||||
fields={
|
|
||||||
speed: f32,
|
|
||||||
slow_speed_factor: f32,
|
|
||||||
look_speed: f32,
|
|
||||||
mouse_sensitivity: f32,
|
|
||||||
look_with_keys: bool,
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -173,15 +173,9 @@ impl mlua::FromLua for LuaActionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaWrapper for LuaActionHandler {
|
impl LuaWrapper for LuaActionHandler {
|
||||||
type Wrap = ActionHandler;
|
|
||||||
|
|
||||||
fn wrapped_type_id() -> std::any::TypeId {
|
fn wrapped_type_id() -> std::any::TypeId {
|
||||||
std::any::TypeId::of::<ActionHandler>()
|
std::any::TypeId::of::<ActionHandler>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_wrapped(self) -> Self::Wrap {
|
|
||||||
self.handler
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_keyboard_string(key_name: &str) -> Option<ActionSource> {
|
fn process_keyboard_string(key_name: &str) -> Option<ActionSource> {
|
||||||
|
|
|
@ -11,7 +11,7 @@ wrap_lua_struct!(
|
||||||
math::Vec2,
|
math::Vec2,
|
||||||
derives(PartialEq, Copy),
|
derives(PartialEq, Copy),
|
||||||
new,
|
new,
|
||||||
fields={x: f32, y: f32},
|
fields(x, y),
|
||||||
metamethods(
|
metamethods(
|
||||||
Add(LuaVec2, f32),
|
Add(LuaVec2, f32),
|
||||||
Sub(LuaVec2, f32),
|
Sub(LuaVec2, f32),
|
||||||
|
@ -50,7 +50,7 @@ wrap_lua_struct!(
|
||||||
math::Vec3,
|
math::Vec3,
|
||||||
derives(PartialEq, Copy),
|
derives(PartialEq, Copy),
|
||||||
new,
|
new,
|
||||||
fields={x: f32, y: f32, z: f32},
|
fields(x, y, z),
|
||||||
metamethods(
|
metamethods(
|
||||||
Add(LuaVec3, f32),
|
Add(LuaVec3, f32),
|
||||||
Sub(LuaVec3, f32),
|
Sub(LuaVec3, f32),
|
||||||
|
@ -90,7 +90,7 @@ wrap_lua_struct!(
|
||||||
math::Vec4,
|
math::Vec4,
|
||||||
derives(PartialEq, Copy),
|
derives(PartialEq, Copy),
|
||||||
new,
|
new,
|
||||||
fields={x: f32, y: f32, z: f32, w: f32},
|
fields(x, y, z, w),
|
||||||
metamethods(
|
metamethods(
|
||||||
Add(LuaVec4, f32),
|
Add(LuaVec4, f32),
|
||||||
Sub(LuaVec4, f32),
|
Sub(LuaVec4, f32),
|
||||||
|
@ -108,7 +108,7 @@ wrap_lua_struct!(
|
||||||
math::Quat,
|
math::Quat,
|
||||||
derives(PartialEq, Copy),
|
derives(PartialEq, Copy),
|
||||||
//new,
|
//new,
|
||||||
fields={x: f32, y: f32, z: f32, w: f32},
|
fields(x, y, z, w),
|
||||||
metamethods(
|
metamethods(
|
||||||
Eq,
|
Eq,
|
||||||
Add,
|
Add,
|
||||||
|
@ -360,27 +360,4 @@ wrap_lua_struct!(
|
||||||
Ok(t)
|
Ok(t)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
wrap_lua_struct!(
|
|
||||||
math::Angle,
|
|
||||||
derives(Copy),
|
|
||||||
skip(lua_reflect),
|
|
||||||
extra_methods = {
|
|
||||||
methods.add_function("new_degrees", |_, deg: f32| {
|
|
||||||
Ok(Self(math::Angle::Degrees(deg)))
|
|
||||||
});
|
|
||||||
|
|
||||||
methods.add_function("new_radians", |_, rad: f32| {
|
|
||||||
Ok(Self(math::Angle::Radians(rad)))
|
|
||||||
});
|
|
||||||
|
|
||||||
methods.add_method("radians", |_, this, ()| {
|
|
||||||
Ok(this.to_radians())
|
|
||||||
});
|
|
||||||
|
|
||||||
methods.add_method("degrees", |_, this, ()| {
|
|
||||||
Ok(this.to_degrees())
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
);
|
|
@ -11,10 +11,4 @@ mod delta_time;
|
||||||
pub use delta_time::*;
|
pub use delta_time::*;
|
||||||
|
|
||||||
mod window;
|
mod window;
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|
||||||
mod camera;
|
|
||||||
pub use camera::*;
|
|
||||||
|
|
||||||
mod free_fly_camera;
|
|
||||||
pub use free_fly_camera::*;
|
|
|
@ -1,6 +1,7 @@
|
||||||
use lyra_scripting_derive::wrap_lua_struct;
|
use lyra_scripting_derive::wrap_lua_struct;
|
||||||
|
|
||||||
use lyra_game::winit::{WindowOptions, FullscreenMode, Theme, CursorGrabMode, WindowLevel};
|
use lyra_game::winit::{WindowOptions, FullscreenMode, Theme, CursorGrabMode, WindowLevel};
|
||||||
|
use mlua::IntoLua;
|
||||||
|
|
||||||
use crate::lyra_engine;
|
use crate::lyra_engine;
|
||||||
use crate as lyra_scripting;
|
use crate as lyra_scripting;
|
||||||
|
@ -14,9 +15,7 @@ wrap_lua_struct!(
|
||||||
WindowOptions,
|
WindowOptions,
|
||||||
//derives(Clone),
|
//derives(Clone),
|
||||||
name=LuaWindow,
|
name=LuaWindow,
|
||||||
fields={
|
fields(focused),
|
||||||
(focused, skip_set)
|
|
||||||
},
|
|
||||||
extra_fields={
|
extra_fields={
|
||||||
fields.add_field_method_get("window_mode", |lua, this| {
|
fields.add_field_method_get("window_mode", |lua, this| {
|
||||||
let s = match &this.fullscreen_mode {
|
let s = match &this.fullscreen_mode {
|
||||||
|
|
Loading…
Reference in New Issue