lua: expose fields on some types from lyra_resource
This commit is contained in:
parent
140ca506d6
commit
49dfb38da3
|
@ -1,10 +1,10 @@
|
|||
use quote::{format_ident, quote};
|
||||
use syn::{braced, parenthesized, parse_macro_input, token, Ident, Path, Token};
|
||||
|
||||
struct FieldGetter {
|
||||
field: Ident,
|
||||
body: Option<syn::Block>,
|
||||
wrapper_type: Option<syn::Path>,
|
||||
pub(crate) struct FieldGetter {
|
||||
pub field: Ident,
|
||||
pub body: Option<syn::Block>,
|
||||
pub wrapper_type: Option<syn::Path>,
|
||||
}
|
||||
|
||||
impl FieldGetter {
|
||||
|
@ -131,6 +131,7 @@ impl syn::parse::Parse for HandleWrapUsage {
|
|||
pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as HandleWrapUsage);
|
||||
|
||||
let handle_path = &input.type_path;
|
||||
let handle_name = &input.type_path.segments.last().unwrap().ident;
|
||||
|
||||
let base_name = input.override_name.unwrap_or_else(|| handle_name.clone());
|
||||
|
@ -145,7 +146,7 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
|
|||
|
||||
let field_creator = match &g.wrapper_type {
|
||||
Some(wrap) => {
|
||||
quote!(#wrap(data.#field).into_lua(lua))
|
||||
quote!(#wrap(data.#field.clone()).into_lua(lua))
|
||||
},
|
||||
None => match &g.body {
|
||||
Some(body) => {
|
||||
|
@ -170,18 +171,18 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
|
|||
|
||||
quote! {
|
||||
#[derive(Clone, Reflect)]
|
||||
pub struct #wrapper_name(pub ResHandle<#handle_name>);
|
||||
pub struct #wrapper_name(pub ResHandle<#handle_path>);
|
||||
|
||||
impl Deref for #wrapper_name {
|
||||
type Target = ResHandle<#handle_name>;
|
||||
type Target = ResHandle<#handle_path>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ResHandle<#handle_name>> for #wrapper_name {
|
||||
fn from(value: ResHandle<#handle_name>) -> Self {
|
||||
impl From<ResHandle<#handle_path>> for #wrapper_name {
|
||||
fn from(value: ResHandle<#handle_path>) -> Self {
|
||||
#wrapper_name(value)
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +225,7 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
|
|||
});
|
||||
|
||||
methods.add_function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
||||
Ok(ScriptBorrow::from_component::<ResHandle<#handle_name>>(None))
|
||||
Ok(ScriptBorrow::from_component::<ResHandle<#handle_path>>(None))
|
||||
});
|
||||
methods.add_method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
|
||||
Ok(ScriptBorrow::from_component(Some(this.0.clone())))
|
||||
|
@ -247,7 +248,7 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
|
|||
|
||||
impl LuaWrapper for #wrapper_name {
|
||||
fn wrapped_type_id() -> std::any::TypeId {
|
||||
TypeId::of::<ResHandle<#handle_name>>()
|
||||
TypeId::of::<ResHandle<#handle_path>>()
|
||||
}
|
||||
}
|
||||
}.into()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::{parenthesized, parse_macro_input, punctuated::Punctuated, token, Ident, Path, Token};
|
||||
use syn::{braced, parenthesized, parse_macro_input, punctuated::Punctuated, token, Ident, Path, Token};
|
||||
|
||||
use crate::{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)]
|
||||
enum SkipType {
|
||||
|
@ -297,6 +297,7 @@ struct WrapUsage {
|
|||
/// The extra derives of the type.
|
||||
override_name: Option<Ident>,
|
||||
auto_fields: Vec<Ident>,
|
||||
manual_field_getters: Vec<FieldGetter>,
|
||||
auto_derives: Vec<Ident>,
|
||||
auto_new: bool,
|
||||
meta_methods: Vec<MetaMethod>,
|
||||
|
@ -314,6 +315,7 @@ impl syn::parse::Parse for WrapUsage {
|
|||
override_name: None,
|
||||
auto_fields: vec![],
|
||||
auto_derives: vec![],
|
||||
manual_field_getters: vec![],
|
||||
extra_fields: None,
|
||||
extra_methods: None,
|
||||
auto_new: false,
|
||||
|
@ -384,6 +386,17 @@ impl syn::parse::Parse for WrapUsage {
|
|||
let _eq: Token![=] = input.parse()?;
|
||||
s.extra_methods = Some(input.parse::<syn::Block>()?);
|
||||
},
|
||||
"field_getters" => {
|
||||
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(FieldGetter::parse, Token![,])?;
|
||||
s.manual_field_getters = terminated.into_iter().collect();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(ident, format!("unknown wrapper command: '{}'", ident_str)));
|
||||
}
|
||||
|
@ -469,6 +482,30 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
|||
}
|
||||
};
|
||||
|
||||
let custom_getters = input.manual_field_getters.iter().map(|g| {
|
||||
let field = &g.field;
|
||||
|
||||
let field_creator = match &g.wrapper_type {
|
||||
Some(wrap) => {
|
||||
quote!(#wrap(this.#field).into_lua(lua))
|
||||
},
|
||||
None => match &g.body {
|
||||
Some(body) => {
|
||||
quote!(#body)
|
||||
},
|
||||
None => {
|
||||
quote!(this.#field.clone().into_lua(lua))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
fields.add_field_method_get(stringify!($field), |lua, this| {
|
||||
#field_creator
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
proc_macro::TokenStream::from(quote! {
|
||||
#[derive(Clone, lyra_reflect::Reflect, #(#derive_idents_iter),*)]
|
||||
pub struct #wrapper_typename(#[reflect(skip)] pub(crate) #path);
|
||||
|
@ -499,6 +536,7 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
|
|||
impl mlua::UserData for #wrapper_typename {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
#(#field_get_set_pairs)*
|
||||
#(#custom_getters)*
|
||||
|
||||
#extra_fields
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
---@enum ActionState
|
||||
ActionState = {
|
||||
IDLE = "idle",
|
||||
PRESSED = "pressed",
|
||||
JUST_PRESSED = "just_pressed",
|
||||
JUST_RELEASED = "just_released",
|
||||
AXIS = "axis",
|
||||
OTHER = "other",
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
---@enum HandleState
|
||||
HandleState = {
|
||||
LOADING = "loading",
|
||||
READY = "ready",
|
||||
ERROR = "error",
|
||||
}
|
||||
|
||||
---@enum ActionKind
|
||||
ActionKind = {
|
||||
BUTTON = "button",
|
||||
AXIS = "axis",
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
---@enum WindowMode
|
||||
WindowMode = {
|
||||
WNDOWED = "windowed",
|
||||
BORDERLESS_FULLSCREEN = "borderless_fullscreen",
|
||||
SIZED_FULLSCREEN = "sized_fullscreen",
|
||||
FULLSCREEN = "fullscreen",
|
||||
}
|
||||
|
||||
---@enum CursorGrabMode
|
||||
CursorGrabMode = {
|
||||
NONE = "none",
|
||||
CONFINED = "confined",
|
||||
LOCKED = "locked",
|
||||
}
|
||||
|
||||
---@enum WindowTheme
|
||||
WindowTheme = {
|
||||
LIGHT = "light",
|
||||
DARK = "dark",
|
||||
}
|
||||
|
||||
---@enum WindowLevel
|
||||
WindowLevel = {
|
||||
ALWAYS_ON_BOTTOM = "always_on_bottom",
|
||||
NORMAL = "normal",
|
||||
ALWAYS_ON_TOP = "always_on_top",
|
||||
}
|
||||
|
||||
---@enum HandleState
|
||||
HandleState = {
|
||||
LOADING = "loading",
|
||||
READY = "ready",
|
||||
ERROR = "error",
|
||||
}
|
||||
|
||||
---@enum ActionKind
|
||||
ActionKind = {
|
||||
BUTTON = "button",
|
||||
AXIS = "axis",
|
||||
}
|
||||
|
||||
---@enum ActionState
|
||||
ActionState = {
|
||||
IDLE = "idle",
|
||||
PRESSED = "pressed",
|
||||
JUST_PRESSED = "just_pressed",
|
||||
JUST_RELEASED = "just_released",
|
||||
AXIS = "axis",
|
||||
OTHER = "other",
|
||||
}
|
||||
|
||||
---@enum FilterMode
|
||||
FilterMode = {
|
||||
NEAREST = "nearest",
|
||||
LINEAR = "linear",
|
||||
}
|
||||
|
||||
---@enum WrappingMode
|
||||
WrappingMode = {
|
||||
CLAMP_TO_EDGE = "clamp_to_edge",
|
||||
MIRRORED_REPEAT = "mirrored_repeat",
|
||||
REPEAT = "repeat",
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
---@enum WindowMode
|
||||
WindowMode = {
|
||||
WNDOWED = "windowed",
|
||||
BORDERLESS_FULLSCREEN = "borderless_fullscreen",
|
||||
SIZED_FULLSCREEN = "sized_fullscreen",
|
||||
FULLSCREEN = "fullscreen",
|
||||
}
|
||||
|
||||
---@enum CursorGrabMode
|
||||
CursorGrabMode = {
|
||||
NONE = "none",
|
||||
CONFINED = "confined",
|
||||
LOCKED = "locked",
|
||||
}
|
||||
|
||||
---@enum WindowTheme
|
||||
WindowTheme = {
|
||||
LIGHT = "light",
|
||||
DARK = "dark",
|
||||
}
|
||||
|
||||
---@enum WindowLevel
|
||||
WindowLevel = {
|
||||
ALWAYS_ON_BOTTOM = "always_on_bottom",
|
||||
NORMAL = "normal",
|
||||
ALWAYS_ON_TOP = "always_on_top",
|
||||
}
|
|
@ -40,12 +40,8 @@ impl ScriptApiProvider for LyraEcsApiProvider {
|
|||
fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
|
||||
let ctx = ctx.lock().unwrap();
|
||||
|
||||
// load window enums
|
||||
let bytes = include_str!("../../../scripts/lua/window.lua");
|
||||
ctx.load(bytes).exec().unwrap();
|
||||
|
||||
// load asset handle enums
|
||||
let bytes = include_str!("../../../scripts/lua/asset_handle.lua");
|
||||
// load enums
|
||||
let bytes = include_str!("../../../scripts/lua/enums.lua");
|
||||
ctx.load(bytes).exec().unwrap();
|
||||
|
||||
let globals = ctx.globals();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{any::TypeId, ops::Deref};
|
||||
//use mlua::{AnyUserData, IntoLua, FromLua, Lua, Value};
|
||||
use lyra_resource::{gltf::{Gltf, Material, Mesh}, Texture, ResHandle, UntypedResHandle};
|
||||
use lyra_resource::{gltf::{Gltf, Material, Mesh}, FilterMode, ResHandle, Texture, UntypedResHandle, WrappingMode};
|
||||
use lyra_game::scene::SceneGraph;
|
||||
use lyra_reflect::{Reflect, TypeData};
|
||||
use lyra_scripting_derive::{lua_wrap_handle, wrap_lua_struct};
|
||||
|
@ -111,15 +111,87 @@ impl mlua::FromLua for LuaResHandle {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: fields
|
||||
wrap_lua_struct!(lyra_resource::gltf::PbrGlossiness, skip(lua_reflect)); // doesn't need internal lua reflection methods
|
||||
// TODO: fields
|
||||
wrap_lua_struct!(lyra_resource::gltf::Specular, skip(lua_reflect)); // doesn't need internal lua reflection methods
|
||||
fn filter_mode_to_str(fm: FilterMode) -> &'static str {
|
||||
match fm {
|
||||
FilterMode::Nearest => "nearest",
|
||||
FilterMode::Linear => "linear",
|
||||
}
|
||||
}
|
||||
|
||||
fn wrapping_mode_to_str(wm: WrappingMode) -> &'static str {
|
||||
match wm {
|
||||
WrappingMode::ClampToEdge => "clamp_to_edge",
|
||||
WrappingMode::MirroredRepeat => "mirrored_repeat",
|
||||
WrappingMode::Repeat => "repeat",
|
||||
}
|
||||
}
|
||||
|
||||
wrap_lua_struct!(lyra_resource::TextureSampler,
|
||||
// this can be safely skipped since it wont be a component or resource.
|
||||
skip(lua_reflect),
|
||||
field_getters={
|
||||
(mag_filter, {
|
||||
this.mag_filter.map(|f| filter_mode_to_str(f))
|
||||
.into_lua(lua)
|
||||
}),
|
||||
(min_filter, {
|
||||
this.min_filter.map(|f| filter_mode_to_str(f))
|
||||
.into_lua(lua)
|
||||
}),
|
||||
(mipmap_filter, {
|
||||
this.mipmap_filter.map(|f| filter_mode_to_str(f))
|
||||
.into_lua(lua)
|
||||
}),
|
||||
(wrap_u, {
|
||||
wrapping_mode_to_str(this.wrap_u)
|
||||
.into_lua(lua)
|
||||
}),
|
||||
(wrap_v, {
|
||||
wrapping_mode_to_str(this.wrap_v)
|
||||
.into_lua(lua)
|
||||
}),
|
||||
(wrap_w, {
|
||||
wrapping_mode_to_str(this.wrap_w)
|
||||
.into_lua(lua)
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
wrap_lua_struct!(lyra_resource::gltf::PbrGlossiness,
|
||||
// this can be safely skipped since it wont be a component or resource.
|
||||
skip(lua_reflect),
|
||||
field_getters={
|
||||
(diffuse_color, wrapper=crate::lua::wrappers::LuaVec4),
|
||||
(specular, wrapper=crate::lua::wrappers::LuaVec3),
|
||||
glossiness,
|
||||
}
|
||||
);
|
||||
|
||||
wrap_lua_struct!(lyra_resource::gltf::Specular,
|
||||
// this can be safely skipped since it wont be a component or resource.
|
||||
skip(lua_reflect),
|
||||
field_getters={
|
||||
factor,
|
||||
(color_factor, wrapper=crate::lua::wrappers::LuaVec3),
|
||||
},
|
||||
extra_fields={
|
||||
fields.add_field_method_get("texture", |lua, this| {
|
||||
this.texture.clone()
|
||||
.map(|t| LuaTextureHandle(t))
|
||||
.into_lua(lua)
|
||||
});
|
||||
fields.add_field_method_get("color_texture", |lua, this| {
|
||||
this.color_texture.clone()
|
||||
.map(|t| LuaTextureHandle(t))
|
||||
.into_lua(lua)
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// TODO: fields
|
||||
lua_wrap_handle!(SceneGraph, name=Scene, {});
|
||||
|
||||
lua_wrap_handle!(Mesh,
|
||||
lua_wrap_handle!(Mesh,
|
||||
field_getters={
|
||||
(material, {
|
||||
data.material.clone()
|
||||
|
@ -154,10 +226,32 @@ lua_wrap_handle!(Mesh,
|
|||
}
|
||||
});
|
||||
|
||||
// TODO: attributes
|
||||
// TODO: mesh attributes
|
||||
}
|
||||
);
|
||||
lua_wrap_handle!(Texture, {});
|
||||
|
||||
lua_wrap_handle!(lyra_resource::Image,
|
||||
field_getters={
|
||||
(width, {
|
||||
data.width().into_lua(lua)
|
||||
}),
|
||||
(height, {
|
||||
data.height().into_lua(lua)
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
lua_wrap_handle!(Texture,
|
||||
field_getters={
|
||||
(image, wrapper=LuaImageHandle),
|
||||
(sampler, {
|
||||
data.sampler.clone()
|
||||
.map(|s| LuaTextureSampler(s))
|
||||
.into_lua(lua)
|
||||
})
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
lua_wrap_handle!(Material,
|
||||
field_getters={
|
||||
|
@ -185,7 +279,6 @@ lua_wrap_handle!(Material,
|
|||
alpha_cutoff,
|
||||
(alpha_mode, {
|
||||
match data.alpha_mode {
|
||||
// TODO: Lua enums
|
||||
lyra_resource::gltf::AlphaMode::Opaque => "opaque",
|
||||
lyra_resource::gltf::AlphaMode::Mask => "mask",
|
||||
lyra_resource::gltf::AlphaMode::Blend => "blend",
|
||||
|
|
Loading…
Reference in New Issue