Create an early scripting engine #2
|
@ -120,7 +120,6 @@ impl Iterator for DynamicViewIter {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//let world = unsafe { self.world_ptr.as_ref() };
|
|
||||||
let world = self.world_ptr.as_ref();
|
let world = self.world_ptr.as_ref();
|
||||||
|
|
||||||
self.fetchers = self.queries.iter()
|
self.fetchers = self.queries.iter()
|
||||||
|
@ -153,8 +152,6 @@ pub struct ReflectedIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReflectedIterator {
|
impl ReflectedIterator {
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "lua")]
|
#[cfg(feature = "lua")]
|
||||||
pub fn next_lua<'a>(&mut self, lua: &'a mlua::Lua) -> Option<ReflectedRow<'a>> {
|
pub fn next_lua<'a>(&mut self, lua: &'a mlua::Lua) -> Option<ReflectedRow<'a>> {
|
||||||
|
|
||||||
|
@ -167,11 +164,6 @@ impl ReflectedIterator {
|
||||||
.map(|r| NonNull::from(r.deref()));
|
.map(|r| NonNull::from(r.deref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* let mut row = ReflectedRow {
|
|
||||||
entity: row.entity,
|
|
||||||
row: row.item,
|
|
||||||
}; */
|
|
||||||
|
|
||||||
let mut dynamic_row = vec![];
|
let mut dynamic_row = vec![];
|
||||||
for d in row.item.iter() {
|
for d in row.item.iter() {
|
||||||
let id = d.info.type_id.as_rust();
|
let id = d.info.type_id.as_rust();
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
pub mod dynamic_iter;
|
pub mod dynamic_iter;
|
||||||
use anyhow::anyhow;
|
|
||||||
pub use dynamic_iter::*;
|
pub use dynamic_iter::*;
|
||||||
|
|
||||||
pub mod world;
|
pub mod world;
|
||||||
use lyra_game::{game::GameStages, plugin::Plugin};
|
|
||||||
use lyra_resource::ResourceManager;
|
|
||||||
use tracing::{debug, debug_span, error, trace};
|
|
||||||
pub use world::*;
|
pub use world::*;
|
||||||
|
|
||||||
pub mod script;
|
pub mod script;
|
||||||
|
@ -20,13 +16,15 @@ pub mod wrappers;
|
||||||
pub mod proxy;
|
pub mod proxy;
|
||||||
pub use proxy::*;
|
pub use proxy::*;
|
||||||
|
|
||||||
|
pub mod system;
|
||||||
|
pub use system::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use std::{any::TypeId, ptr::NonNull, sync::Mutex};
|
use std::{any::TypeId, sync::Mutex};
|
||||||
|
|
||||||
use lyra_ecs::{
|
use lyra_ecs::{
|
||||||
query::{Entities, ResMut, View},
|
|
||||||
DynamicBundle, World,
|
DynamicBundle, World,
|
||||||
};
|
};
|
||||||
use lyra_reflect::{FromType, Reflect, TypeRegistry};
|
use lyra_reflect::{FromType, Reflect, TypeRegistry};
|
||||||
|
@ -38,13 +36,9 @@ 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";
|
||||||
|
|
||||||
use crate::{
|
use crate::{ScriptBorrow, ScriptDynamicBundle};
|
||||||
GameScriptExt, ScriptApiProviders, ScriptBorrow, ScriptContexts, ScriptData,
|
|
||||||
ScriptDynamicBundle, ScriptError, ScriptHost, ScriptList, ScriptWorldPtr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::providers::{LyraEcsApiProvider, LyraMathApiProvider, UtilityApiProvider};
|
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
@ -113,232 +107,4 @@ impl mlua::UserData for ScriptDynamicBundle {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A system that creates the script contexts in the world as new scripts are found
|
|
||||||
pub fn lua_scripts_create_contexts(
|
|
||||||
mut host: ResMut<LuaHost>,
|
|
||||||
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
|
||||||
mut providers: ResMut<ScriptApiProviders<LuaHost>>,
|
|
||||||
view: View<(Entities, &ScriptList<LuaScript>)>,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
for (en, scripts) in view.into_iter() {
|
|
||||||
for script in scripts.iter() {
|
|
||||||
if !contexts.has_context(script.id()) {
|
|
||||||
let script_data = ScriptData {
|
|
||||||
name: script.name().to_string(),
|
|
||||||
script_id: script.id(),
|
|
||||||
entity: en,
|
|
||||||
};
|
|
||||||
|
|
||||||
let script_name = script.name();
|
|
||||||
let _span = debug_span!("lua", script = script_name).entered();
|
|
||||||
|
|
||||||
if let Some(script_res) = &script.res_handle().try_data_ref() {
|
|
||||||
debug!("Loading script...");
|
|
||||||
let mut script_ctx =
|
|
||||||
host.load_script(&script_res.bytes, &script_data, &mut providers)?;
|
|
||||||
trace!("Finished loading script");
|
|
||||||
|
|
||||||
debug!("Setting up script...");
|
|
||||||
host.setup_script(&script_data, &mut script_ctx, &mut providers)?;
|
|
||||||
trace!("Finished setting up script");
|
|
||||||
|
|
||||||
contexts.add_context(script.id(), script_ctx);
|
|
||||||
} else {
|
|
||||||
trace!("Script is not loaded yet, skipping for now");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A system that triggers a reload of watched script resources.
|
|
||||||
///
|
|
||||||
/// Note: This only works if the script is watched. See [`lyra_resource::ResourceManager::watch`].
|
|
||||||
pub fn lua_scripts_reload_system(
|
|
||||||
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
|
||||||
mut resman: ResMut<ResourceManager>,
|
|
||||||
view: View<&ScriptList<LuaScript>>,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
for scripts in view.into_iter() {
|
|
||||||
for script in scripts.iter() {
|
|
||||||
let handle = script.res_handle();
|
|
||||||
if handle.is_watched() {
|
|
||||||
let handle_path = handle.path();
|
|
||||||
let watch_recv = resman.watcher_event_recv(&handle_path).unwrap();
|
|
||||||
|
|
||||||
match watch_recv.try_recv() {
|
|
||||||
Ok(ev) => {
|
|
||||||
let evs =
|
|
||||||
ev.map_err(|e| anyhow!("Script watcher ran into errors: {:?}", e))?;
|
|
||||||
|
|
||||||
if evs.iter().any(|ev| ev.event.kind.is_modify()) {
|
|
||||||
debug!(
|
|
||||||
"Detected change of '{}' script, triggering reload",
|
|
||||||
handle_path
|
|
||||||
);
|
|
||||||
|
|
||||||
contexts.remove_context(script.id()).unwrap();
|
|
||||||
resman.reload(handle)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => match e {
|
|
||||||
lyra_resource::channel::TryRecvError::Empty => {}
|
|
||||||
lyra_resource::channel::TryRecvError::Disconnected => {
|
|
||||||
resman.stop_watching(&handle_path).unwrap();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lua_call_script_function(world: &mut World, stage_name: &str) -> anyhow::Result<()> {
|
|
||||||
let world_ptr = ScriptWorldPtr::from_ref(&world);
|
|
||||||
let mut host = world.get_resource_mut::<LuaHost>();
|
|
||||||
let mut contexts = world.get_resource_mut::<ScriptContexts<LuaContext>>();
|
|
||||||
let mut providers = world.get_resource_mut::<ScriptApiProviders<LuaHost>>();
|
|
||||||
|
|
||||||
for (en, scripts) in world.view_iter::<(Entities, &ScriptList<LuaScript>)>() {
|
|
||||||
for script in scripts.iter() {
|
|
||||||
let script_data = ScriptData {
|
|
||||||
name: script.name().to_string(),
|
|
||||||
script_id: script.id(),
|
|
||||||
entity: en,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(ctx) = contexts.get_context_mut(script.id()) {
|
|
||||||
trace!(
|
|
||||||
"Running '{}' function in script '{}'",
|
|
||||||
stage_name,
|
|
||||||
script.name()
|
|
||||||
);
|
|
||||||
|
|
||||||
match host.call_script(
|
|
||||||
world_ptr.clone(),
|
|
||||||
&script_data,
|
|
||||||
ctx,
|
|
||||||
&mut providers,
|
|
||||||
stage_name,
|
|
||||||
) {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => match e {
|
|
||||||
ScriptError::MluaError(m) => {
|
|
||||||
error!("Script '{}' ran into an error: {}", script.name(), m);
|
|
||||||
}
|
|
||||||
ScriptError::Other(_) => return Err(e.into()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This system executes the 'on_update' function of lua scripts in the world. It is meant to run
|
|
||||||
/// during the 'GameStages::Update' stage.
|
|
||||||
pub fn lua_script_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
|
||||||
lua_call_script_function(world, "on_update")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This system executes the 'on_pre_update' function of lua scripts in the world. It is meant to run
|
|
||||||
/// during the 'GameStages::PreUpdate' stage.
|
|
||||||
pub fn lua_script_pre_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
|
||||||
lua_call_script_function(world, "on_pre_update")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This system executes the 'on_post_update' function of lua scripts in the world. It is meant to run
|
|
||||||
/// during the 'GameStages::PostUpdate' stage.
|
|
||||||
pub fn lua_script_post_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
|
||||||
lua_call_script_function(world, "on_post_update")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This system executes the 'on_first' function of lua scripts in the world. It is meant to run
|
|
||||||
/// during the 'GameStages::First' stage.
|
|
||||||
pub fn lua_script_first_stage_system(world: &mut World) -> anyhow::Result<()> {
|
|
||||||
lua_call_script_function(world, "on_first")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This system executes the 'on_last' function of lua scripts in the world. It is meant to run
|
|
||||||
/// during the 'GameStages::Last' stage.
|
|
||||||
pub fn lua_script_last_stage_system(world: &mut World) -> anyhow::Result<()> {
|
|
||||||
lua_call_script_function(world, "on_last")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LuaScriptingPlugin;
|
|
||||||
|
|
||||||
impl Plugin for LuaScriptingPlugin {
|
|
||||||
fn setup(&self, game: &mut lyra_game::game::Game) {
|
|
||||||
let world = game.world();
|
|
||||||
|
|
||||||
world.add_resource_default::<TypeRegistry>();
|
|
||||||
|
|
||||||
world.add_resource_default::<LuaHost>();
|
|
||||||
world.add_resource_default::<ScriptApiProviders<LuaHost>>();
|
|
||||||
world.add_resource_default::<ScriptContexts<LuaContext>>();
|
|
||||||
|
|
||||||
let mut loader = world
|
|
||||||
.try_get_resource_mut::<ResourceManager>()
|
|
||||||
.expect("Add 'ResourceManager' to the world before trying to add this plugin");
|
|
||||||
loader.register_loader::<LuaLoader>();
|
|
||||||
drop(loader);
|
|
||||||
|
|
||||||
game.add_script_api_provider::<LuaHost, _>(UtilityApiProvider);
|
|
||||||
game.add_script_api_provider::<LuaHost, _>(LyraEcsApiProvider);
|
|
||||||
game.add_script_api_provider::<LuaHost, _>(LyraMathApiProvider);
|
|
||||||
|
|
||||||
game.add_system_to_stage(
|
|
||||||
GameStages::First,
|
|
||||||
"lua_create_contexts",
|
|
||||||
lua_scripts_create_contexts,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::First,
|
|
||||||
"lua_reload_scripts",
|
|
||||||
lua_scripts_reload_system,
|
|
||||||
&["lua_create_contexts"],
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::First,
|
|
||||||
"lua_first_stage",
|
|
||||||
lua_script_first_stage_system,
|
|
||||||
&["lua_reload_scripts"],
|
|
||||||
)
|
|
||||||
// cannot depend on 'lua_create_contexts' since it will cause a panic.
|
|
||||||
// the staged executor separates the executor of a single stage so this system
|
|
||||||
// cannot depend on the other one.
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::PreUpdate,
|
|
||||||
"lua_pre_update",
|
|
||||||
lua_script_pre_update_stage_system,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::Update,
|
|
||||||
"lua_update",
|
|
||||||
lua_script_update_stage_system,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::PostUpdate,
|
|
||||||
"lua_post_update",
|
|
||||||
lua_script_post_update_stage_system,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
GameStages::Last,
|
|
||||||
"lua_last_stage",
|
|
||||||
lua_script_last_stage_system,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use lyra_ecs::{query::{Entities, ResMut, View}, World};
|
||||||
|
use lyra_game::{game::GameStages, plugin::Plugin};
|
||||||
|
use lyra_reflect::TypeRegistry;
|
||||||
|
use lyra_resource::ResourceManager;
|
||||||
|
use tracing::{debug, debug_span, error, trace};
|
||||||
|
|
||||||
|
use crate::{GameScriptExt, ScriptApiProviders, ScriptContexts, ScriptData, ScriptError, ScriptHost, ScriptList, ScriptWorldPtr};
|
||||||
|
|
||||||
|
use super::{providers::{LyraEcsApiProvider, LyraMathApiProvider, UtilityApiProvider}, LuaContext, LuaHost, LuaLoader, LuaScript};
|
||||||
|
|
||||||
|
/// A system that creates the script contexts in the world as new scripts are found
|
||||||
|
pub fn lua_scripts_create_contexts(
|
||||||
|
mut host: ResMut<LuaHost>,
|
||||||
|
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
||||||
|
mut providers: ResMut<ScriptApiProviders<LuaHost>>,
|
||||||
|
view: View<(Entities, &ScriptList<LuaScript>)>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
for (en, scripts) in view.into_iter() {
|
||||||
|
for script in scripts.iter() {
|
||||||
|
if !contexts.has_context(script.id()) {
|
||||||
|
let script_data = ScriptData {
|
||||||
|
name: script.name().to_string(),
|
||||||
|
script_id: script.id(),
|
||||||
|
entity: en,
|
||||||
|
};
|
||||||
|
|
||||||
|
let script_name = script.name();
|
||||||
|
let _span = debug_span!("lua", script = script_name).entered();
|
||||||
|
|
||||||
|
if let Some(script_res) = &script.res_handle().try_data_ref() {
|
||||||
|
debug!("Loading script...");
|
||||||
|
let mut script_ctx =
|
||||||
|
host.load_script(&script_res.bytes, &script_data, &mut providers)?;
|
||||||
|
trace!("Finished loading script");
|
||||||
|
|
||||||
|
debug!("Setting up script...");
|
||||||
|
host.setup_script(&script_data, &mut script_ctx, &mut providers)?;
|
||||||
|
trace!("Finished setting up script");
|
||||||
|
|
||||||
|
contexts.add_context(script.id(), script_ctx);
|
||||||
|
} else {
|
||||||
|
trace!("Script is not loaded yet, skipping for now");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A system that triggers a reload of watched script resources.
|
||||||
|
///
|
||||||
|
/// Note: This only works if the script is watched. See [`lyra_resource::ResourceManager::watch`].
|
||||||
|
pub fn lua_scripts_reload_system(
|
||||||
|
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
||||||
|
mut resman: ResMut<ResourceManager>,
|
||||||
|
view: View<&ScriptList<LuaScript>>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
for scripts in view.into_iter() {
|
||||||
|
for script in scripts.iter() {
|
||||||
|
let handle = script.res_handle();
|
||||||
|
if handle.is_watched() {
|
||||||
|
let handle_path = handle.path();
|
||||||
|
let watch_recv = resman.watcher_event_recv(&handle_path).unwrap();
|
||||||
|
|
||||||
|
match watch_recv.try_recv() {
|
||||||
|
Ok(ev) => {
|
||||||
|
let evs =
|
||||||
|
ev.map_err(|e| anyhow!("Script watcher ran into errors: {:?}", e))?;
|
||||||
|
|
||||||
|
if evs.iter().any(|ev| ev.event.kind.is_modify()) {
|
||||||
|
debug!(
|
||||||
|
"Detected change of '{}' script, triggering reload",
|
||||||
|
handle_path
|
||||||
|
);
|
||||||
|
|
||||||
|
contexts.remove_context(script.id()).unwrap();
|
||||||
|
resman.reload(handle)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
lyra_resource::channel::TryRecvError::Empty => {}
|
||||||
|
lyra_resource::channel::TryRecvError::Disconnected => {
|
||||||
|
resman.stop_watching(&handle_path).unwrap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lua_call_script_function(world: &mut World, stage_name: &str) -> anyhow::Result<()> {
|
||||||
|
let world_ptr = ScriptWorldPtr::from_ref(&world);
|
||||||
|
let mut host = world.get_resource_mut::<LuaHost>();
|
||||||
|
let mut contexts = world.get_resource_mut::<ScriptContexts<LuaContext>>();
|
||||||
|
let mut providers = world.get_resource_mut::<ScriptApiProviders<LuaHost>>();
|
||||||
|
|
||||||
|
for (en, scripts) in world.view_iter::<(Entities, &ScriptList<LuaScript>)>() {
|
||||||
|
for script in scripts.iter() {
|
||||||
|
let script_data = ScriptData {
|
||||||
|
name: script.name().to_string(),
|
||||||
|
script_id: script.id(),
|
||||||
|
entity: en,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ctx) = contexts.get_context_mut(script.id()) {
|
||||||
|
trace!(
|
||||||
|
"Running '{}' function in script '{}'",
|
||||||
|
stage_name,
|
||||||
|
script.name()
|
||||||
|
);
|
||||||
|
|
||||||
|
match host.call_script(
|
||||||
|
world_ptr.clone(),
|
||||||
|
&script_data,
|
||||||
|
ctx,
|
||||||
|
&mut providers,
|
||||||
|
stage_name,
|
||||||
|
) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => match e {
|
||||||
|
ScriptError::MluaError(m) => {
|
||||||
|
error!("Script '{}' ran into an error: {}", script.name(), m);
|
||||||
|
}
|
||||||
|
ScriptError::Other(_) => return Err(e.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This system executes the 'on_update' function of lua scripts in the world. It is meant to run
|
||||||
|
/// during the 'GameStages::Update' stage.
|
||||||
|
pub fn lua_script_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
|
lua_call_script_function(world, "on_update")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This system executes the 'on_pre_update' function of lua scripts in the world. It is meant to run
|
||||||
|
/// during the 'GameStages::PreUpdate' stage.
|
||||||
|
pub fn lua_script_pre_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
|
lua_call_script_function(world, "on_pre_update")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This system executes the 'on_post_update' function of lua scripts in the world. It is meant to run
|
||||||
|
/// during the 'GameStages::PostUpdate' stage.
|
||||||
|
pub fn lua_script_post_update_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
|
lua_call_script_function(world, "on_post_update")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This system executes the 'on_first' function of lua scripts in the world. It is meant to run
|
||||||
|
/// during the 'GameStages::First' stage.
|
||||||
|
pub fn lua_script_first_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
|
lua_call_script_function(world, "on_first")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This system executes the 'on_last' function of lua scripts in the world. It is meant to run
|
||||||
|
/// during the 'GameStages::Last' stage.
|
||||||
|
pub fn lua_script_last_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
|
lua_call_script_function(world, "on_last")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LuaScriptingPlugin;
|
||||||
|
|
||||||
|
impl Plugin for LuaScriptingPlugin {
|
||||||
|
fn setup(&self, game: &mut lyra_game::game::Game) {
|
||||||
|
let world = game.world();
|
||||||
|
|
||||||
|
world.add_resource_default::<TypeRegistry>();
|
||||||
|
|
||||||
|
world.add_resource_default::<LuaHost>();
|
||||||
|
world.add_resource_default::<ScriptApiProviders<LuaHost>>();
|
||||||
|
world.add_resource_default::<ScriptContexts<LuaContext>>();
|
||||||
|
|
||||||
|
let mut loader = world
|
||||||
|
.try_get_resource_mut::<ResourceManager>()
|
||||||
|
.expect("Add 'ResourceManager' to the world before trying to add this plugin");
|
||||||
|
loader.register_loader::<LuaLoader>();
|
||||||
|
drop(loader);
|
||||||
|
|
||||||
|
game.add_script_api_provider::<LuaHost, _>(UtilityApiProvider);
|
||||||
|
game.add_script_api_provider::<LuaHost, _>(LyraEcsApiProvider);
|
||||||
|
game.add_script_api_provider::<LuaHost, _>(LyraMathApiProvider);
|
||||||
|
|
||||||
|
game.add_system_to_stage(
|
||||||
|
GameStages::First,
|
||||||
|
"lua_create_contexts",
|
||||||
|
lua_scripts_create_contexts,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::First,
|
||||||
|
"lua_reload_scripts",
|
||||||
|
lua_scripts_reload_system,
|
||||||
|
&["lua_create_contexts"],
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::First,
|
||||||
|
"lua_first_stage",
|
||||||
|
lua_script_first_stage_system,
|
||||||
|
&["lua_reload_scripts"],
|
||||||
|
)
|
||||||
|
// cannot depend on 'lua_create_contexts' since it will cause a panic.
|
||||||
|
// the staged executor separates the executor of a single stage so this system
|
||||||
|
// cannot depend on the other one.
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::PreUpdate,
|
||||||
|
"lua_pre_update",
|
||||||
|
lua_script_pre_update_stage_system,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::Update,
|
||||||
|
"lua_update",
|
||||||
|
lua_script_update_stage_system,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::PostUpdate,
|
||||||
|
"lua_post_update",
|
||||||
|
lua_script_post_update_stage_system,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
GameStages::Last,
|
||||||
|
"lua_last_stage",
|
||||||
|
lua_script_last_stage_system,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -164,24 +164,6 @@ impl mlua::UserData for ScriptWorldPtr {
|
||||||
let reflect = ty
|
let reflect = ty
|
||||||
.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
|
||||||
.expect("Type does not implement 'reflect_type' properly");
|
.expect("Type does not implement 'reflect_type' properly");
|
||||||
|
|
||||||
//if let Some(data) = reflect.data {
|
|
||||||
/* let res = reflect.reflect_branch.as_resource_unchecked();
|
|
||||||
if let Some(res_ptr) = res.reflect_arc(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");
|
|
||||||
|
|
||||||
//let res = Arc::new(RwLock::new(data.as_any_box()))
|
|
||||||
(proxy.fn_as_uservalue_ref)(lua, res_ptr)
|
|
||||||
.and_then(|ud| ud.into_lua(lua))
|
|
||||||
|
|
||||||
//Ok(mlua::Value::Nil)
|
|
||||||
} else {
|
|
||||||
Ok(mlua::Value::Nil)
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
let res = reflect.reflect_branch.as_resource_unchecked();
|
let res = reflect.reflect_branch.as_resource_unchecked();
|
||||||
if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) {
|
if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) {
|
||||||
|
|
Loading…
Reference in New Issue