Compare commits
2 Commits
90b821f95c
...
6731fcd7f2
Author | SHA1 | Date |
---|---|---|
SeanOMik | 6731fcd7f2 | |
SeanOMik | 4a7cdfab80 |
|
@ -1,10 +1,12 @@
|
||||||
--local cube: resource = world:request_res("loader", "assets/cube-texture-embedded.gltf")
|
|
||||||
|
|
||||||
--cube = nil
|
|
||||||
|
|
||||||
function on_init()
|
function on_init()
|
||||||
local cube = world:request_res("assets/cube-texture-embedded.gltf")
|
local cube = world:request_res("assets/cube-texture-embedded.gltf")
|
||||||
print("Loaded textured cube")
|
print("Loaded textured cube")
|
||||||
|
|
||||||
|
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
||||||
|
local cube_comp = ModelComponent.new(cube)
|
||||||
|
|
||||||
|
local e = world:spawn(pos, cube_comp)
|
||||||
|
print("spawned entity " .. tostring(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ function on_first()
|
--[[ function on_first()
|
||||||
|
|
|
@ -80,12 +80,13 @@ macro_rules! impl_fn_system_tuple {
|
||||||
|
|
||||||
fn execute_deferred(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
fn execute_deferred(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
||||||
let state = self.arg_state.as_mut().expect("Somehow there was no state");
|
let state = self.arg_state.as_mut().expect("Somehow there was no state");
|
||||||
|
state.reverse();
|
||||||
|
|
||||||
$(
|
$(
|
||||||
let arg_state_box = state.pop()
|
let arg_state_box = state.pop()
|
||||||
.expect("Missing expected arg state");
|
.expect("Missing expected arg state");
|
||||||
let arg_state = *arg_state_box.downcast::<$name::State>()
|
let arg_state = *arg_state_box.downcast::<$name::State>()
|
||||||
.unwrap();
|
.expect("Somehow the state cannot be downcasted from boxed Any");
|
||||||
$name::apply_deferred(arg_state, world);
|
$name::apply_deferred(arg_state, world);
|
||||||
)+
|
)+
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{collections::{HashMap, VecDeque, HashSet}, ptr::NonNull};
|
||||||
|
|
||||||
use super::System;
|
use super::System;
|
||||||
|
|
||||||
use crate::world::World;
|
use crate::{world::World, CommandQueue, Commands};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum GraphExecutorError {
|
pub enum GraphExecutorError {
|
||||||
|
@ -58,7 +58,7 @@ impl GraphExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes the systems in the graph
|
/// Executes the systems in the graph
|
||||||
pub fn execute(&mut self, world_ptr: NonNull<World>, stop_on_error: bool) -> Result<Vec<GraphExecutorError>, GraphExecutorError> {
|
pub fn execute(&mut self, mut world_ptr: NonNull<World>, stop_on_error: bool) -> Result<Vec<GraphExecutorError>, GraphExecutorError> {
|
||||||
let mut stack = VecDeque::new();
|
let mut stack = VecDeque::new();
|
||||||
let mut visited = HashSet::new();
|
let mut visited = HashSet::new();
|
||||||
|
|
||||||
|
@ -91,6 +91,25 @@ impl GraphExecutor {
|
||||||
possible_errors.push(e);
|
possible_errors.push(e);
|
||||||
unimplemented!("Cannot resume topological execution from error"); // TODO: resume topological execution from error
|
unimplemented!("Cannot resume topological execution from error"); // TODO: resume topological execution from error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let world = unsafe { world_ptr.as_mut() };
|
||||||
|
if let Some(mut queue) = world.try_get_resource_mut::<CommandQueue>() {
|
||||||
|
// Safety: Commands only borrows world.entities when adding commands
|
||||||
|
let world = unsafe { world_ptr.as_mut() };
|
||||||
|
let mut commands = Commands::new(&mut queue, world);
|
||||||
|
|
||||||
|
let world = unsafe { world_ptr.as_mut() };
|
||||||
|
if let Err(e) = commands.execute(world)
|
||||||
|
.map_err(|e| GraphExecutorError::Command(e)) {
|
||||||
|
|
||||||
|
if stop_on_error {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
possible_errors.push(e);
|
||||||
|
unimplemented!("Cannot resume topological execution from error"); // TODO: resume topological execution from error
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(possible_errors)
|
Ok(possible_errors)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lyra_ecs::Commands;
|
use lyra_ecs::CommandQueue;
|
||||||
use lyra_resource::ResourceManager;
|
use lyra_resource::ResourceManager;
|
||||||
|
|
||||||
use crate::EventsPlugin;
|
use crate::EventsPlugin;
|
||||||
|
@ -109,10 +109,22 @@ pub struct DefaultPlugins;
|
||||||
|
|
||||||
impl Plugin for DefaultPlugins {
|
impl Plugin for DefaultPlugins {
|
||||||
fn setup(&self, game: &mut Game) {
|
fn setup(&self, game: &mut Game) {
|
||||||
|
CommandQueuePlugin.setup(game);
|
||||||
EventsPlugin.setup(game);
|
EventsPlugin.setup(game);
|
||||||
InputPlugin.setup(game);
|
InputPlugin.setup(game);
|
||||||
ResourceManagerPlugin.setup(game);
|
ResourceManagerPlugin.setup(game);
|
||||||
WindowPlugin::default().setup(game);
|
WindowPlugin::default().setup(game);
|
||||||
DeltaTimePlugin.setup(game);
|
DeltaTimePlugin.setup(game);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A plugin that creates a CommandQueue, and inserts it into the world as a Resource.
|
||||||
|
/// The queue is processed at the end of every system execution in the GraphExecutor.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CommandQueuePlugin;
|
||||||
|
|
||||||
|
impl Plugin for CommandQueuePlugin {
|
||||||
|
fn setup(&self, game: &mut Game) {
|
||||||
|
game.world_mut().add_resource(CommandQueue::default());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -47,9 +47,6 @@ impl ScriptHost for LuaHost {
|
||||||
provider.setup_script(script_data, ctx)?;
|
provider.setup_script(script_data, ctx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctx = ctx.lock().expect("Failure to get Lua ScriptContext");
|
|
||||||
try_call_lua_function(&ctx, "on_init")?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use lyra_ecs::{query::{Entities, ResMut, View}, CommandQueue, Commands, World};
|
use lyra_ecs::{query::{Entities, ResMut, View}, World};
|
||||||
use lyra_game::{game::GameStages, plugin::Plugin};
|
use lyra_game::{game::GameStages, plugin::Plugin};
|
||||||
use lyra_reflect::TypeRegistry;
|
use lyra_reflect::TypeRegistry;
|
||||||
use lyra_resource::ResourceManager;
|
use lyra_resource::ResourceManager;
|
||||||
|
@ -12,15 +10,13 @@ use crate::{GameScriptExt, ScriptApiProviders, ScriptContexts, ScriptData, Scrip
|
||||||
use super::{providers::{LyraEcsApiProvider, LyraMathApiProvider, UtilityApiProvider}, LuaContext, LuaHost, LuaLoader, LuaScript};
|
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
|
/// A system that creates the script contexts in the world as new scripts are found
|
||||||
pub fn lua_scripts_create_contexts<'a>(
|
pub fn lua_scripts_create_contexts(
|
||||||
world: &mut World,
|
world: &mut World,
|
||||||
mut host: ResMut<LuaHost>,
|
mut host: ResMut<LuaHost>,
|
||||||
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
mut contexts: ResMut<ScriptContexts<LuaContext>>,
|
||||||
mut providers: ResMut<ScriptApiProviders<LuaHost>>,
|
mut providers: ResMut<ScriptApiProviders<LuaHost>>,
|
||||||
view: View<(Entities, &ScriptList<LuaScript>)>,
|
view: View<(Entities, &ScriptList<LuaScript>)>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
world.add_resource_default::<CommandQueue>();
|
|
||||||
|
|
||||||
for (en, scripts) in view.into_iter() {
|
for (en, scripts) in view.into_iter() {
|
||||||
for script in scripts.iter() {
|
for script in scripts.iter() {
|
||||||
if !contexts.has_context(script.id()) {
|
if !contexts.has_context(script.id()) {
|
||||||
|
@ -43,6 +39,24 @@ pub fn lua_scripts_create_contexts<'a>(
|
||||||
host.setup_script(&script_data, &mut script_ctx, &mut providers)?;
|
host.setup_script(&script_data, &mut script_ctx, &mut providers)?;
|
||||||
trace!("Finished setting up script");
|
trace!("Finished setting up script");
|
||||||
|
|
||||||
|
// call on_init, handle the error
|
||||||
|
let world_ptr = ScriptWorldPtr::from_ref(&world);
|
||||||
|
match host.call_script(
|
||||||
|
world_ptr,
|
||||||
|
&script_data,
|
||||||
|
&mut script_ctx,
|
||||||
|
&mut providers,
|
||||||
|
"on_init",
|
||||||
|
) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => match e {
|
||||||
|
ScriptError::MluaError(m) => {
|
||||||
|
error!("Script '{}' ran into an error: {}", script.name(), m);
|
||||||
|
}
|
||||||
|
ScriptError::Other(_) => return Err(e.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
contexts.add_context(script.id(), script_ctx);
|
contexts.add_context(script.id(), script_ctx);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -52,14 +66,6 @@ pub fn lua_scripts_create_contexts<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ptr = NonNull::from(world);
|
|
||||||
let world = unsafe { ptr.as_ref() };
|
|
||||||
let mut queue = world.get_resource_mut::<CommandQueue>();
|
|
||||||
|
|
||||||
let mut commands = Commands::new(&mut queue, unsafe { ptr.as_mut() });
|
|
||||||
commands.execute(unsafe { ptr.as_mut() }).unwrap();
|
|
||||||
//commands.execute(unsafe { world_ptr.as_mut() } )?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{ptr::NonNull, sync::Arc};
|
use std::{ptr::NonNull, sync::Arc};
|
||||||
|
|
||||||
use crate::{ScriptBorrow, ScriptDynamicBundle, ScriptEntity, ScriptWorldPtr};
|
use crate::{ScriptBorrow, ScriptEntity, ScriptWorldPtr};
|
||||||
use elua::AsLua;
|
use elua::AsLua;
|
||||||
use lyra_ecs::{query::dynamic::QueryDynamicType, Commands, DynamicBundle};
|
use lyra_ecs::{query::dynamic::QueryDynamicType, CommandQueue, Commands, DynamicBundle, World};
|
||||||
use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry};
|
use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry};
|
||||||
use lyra_resource::ResourceManager;
|
use lyra_resource::ResourceManager;
|
||||||
|
|
||||||
|
@ -64,10 +64,38 @@ impl elua::Userdata for ScriptWorldPtr {
|
||||||
builder: &mut elua::UserdataBuilder<'a, Self>,
|
builder: &mut elua::UserdataBuilder<'a, Self>,
|
||||||
) -> elua::Result<()> {
|
) -> elua::Result<()> {
|
||||||
builder
|
builder
|
||||||
.method_mut("spawn", |_, this, bundle: ScriptDynamicBundle| {
|
.method_mut("spawn", |_, this, vals: elua::ValueVec| {
|
||||||
let world = this.as_mut();
|
let world = this.as_mut();
|
||||||
|
|
||||||
Ok(ScriptEntity(world.spawn(bundle.0)))
|
let mut bundle = DynamicBundle::new();
|
||||||
|
|
||||||
|
//while let Some(val) = vals.pop_front() {
|
||||||
|
for (i, val) in vals.into_iter().enumerate() {
|
||||||
|
let ud = val.as_userdata().ok_or(
|
||||||
|
elua::Error::bad_arg(
|
||||||
|
Some("World:spawn"),
|
||||||
|
2 + i as i32, // i starts at 0
|
||||||
|
Some("components..."),
|
||||||
|
Arc::new(elua::Error::runtime("provided component is not userdata")),
|
||||||
|
))?;
|
||||||
|
|
||||||
|
let script_brw = ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
||||||
|
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
||||||
|
|
||||||
|
let refl_data = script_brw.data.unwrap();
|
||||||
|
//let refl_data = refl_data.as_ref();
|
||||||
|
reflect.bundle_insert(&mut bundle, refl_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// defer the entity spawn
|
||||||
|
// safety: Commands borrows Entities from World, the resource borrows from the world resouces,
|
||||||
|
// they are borrowing different parts of World.
|
||||||
|
let world_ptr: *mut World = world;
|
||||||
|
let mut commands_queue = world.get_resource_mut::<CommandQueue>();
|
||||||
|
let mut commands = Commands::new(&mut commands_queue, unsafe { &mut *world_ptr });
|
||||||
|
let entity = commands.spawn(bundle);
|
||||||
|
|
||||||
|
Ok(ScriptEntity(entity))
|
||||||
})
|
})
|
||||||
.method_mut(
|
.method_mut(
|
||||||
"view",
|
"view",
|
||||||
|
|
Loading…
Reference in New Issue