I broke everything, but we're less cooked.

This commit is contained in:
2026-02-18 10:40:03 +00:00
parent 6aa2003145
commit a7f013ecf8
4 changed files with 56 additions and 37 deletions

View File

@@ -30,21 +30,17 @@ impl<S: Asset> DefaultAsset<S> {
commands.insert_resource(DefaultAsset(handle)); commands.insert_resource(DefaultAsset(handle));
} }
} }
fn world<'w>(lua: &Lua) -> std::result::Result<&'w mut World, mlua::Error> { pub(crate) fn world<'w>(lua: &Lua) -> std::result::Result<&'w mut World, mlua::Error> {
lua.app_data_mut::<&World>() lua.app_data_mut::<&World>()
.ok_or_else(Error("Direct world access not available here!".into())) .ok_or_else(Error("Direct world access not available here!".into()))
.map_err(LuaError::external).deref_mut() .map_err(LuaError::external).deref_mut()
} }
impl LuaUserData for Transform { pub struct Instance(pub Entity);
}
pub struct Instance(Entity);
impl FromLua for Instance { impl FromLua for Instance {
fn from_lua(value: mlua::Value, _: &Lua) -> mlua::Result<Self> { fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
match value { match value {
mlua::Value::UserData(ud) => Ok(*ud.borrow::<Self>()?), Value::UserData(instance) => Ok(Self(instance.borrow::<Self>()?.0)),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -64,29 +60,44 @@ impl LuaUserData for Instance {
} }
Ok(()) Ok(())
}); });
fields.add_field_method_get("transform",|lua: Lua, this| {
Ok(world(&lua)?.get::<Transform>(this.0).unwrap())
});
fields.add_field_method_set("transform",|lua: Lua, this| {
Ok()
})
crate::script::add_fields(fields); crate::script::add_fields(fields);
crate::part::add_fields(fields); crate::part::add_fields(fields);
} }
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) { fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method("despawn",|lua: Lua, this| { methods.add_method("despawn",|lua: Lua, this| {
let world = world(lua).map_err(LuaError::external)?; let world = world(&lua).map_err(LuaError::external)?;
world.get_entity(this).map_err(LuaError::external)?; world.get_entity(this).map_err(LuaError::external)?;
Ok(()) Ok(())
}); });
crate::script::add_methods(methods); crate::script::add_methods(methods);
crate::part::add_fields(methods); crate::part::add_fields(fields);
} }
} }
impl Instance { impl Instance {
fn world_access(&self, lua: &Lua) -> std::result::Result<EntityWorldMut, mlua::Error> { fn world_access(&self, lua: &Lua) -> std::result::Result<EntityWorldMut, mlua::Error> {
world(lua)?.get_entity_mut(self.0).map_err(LuaError::external) world(lua)?.get_entity_mut(self.0).map_err(LuaError::external)
} }
fn new<T: Duck>(&self) {
T::add(self.spawn());
}
pub fn of(entity: Entity) -> Self {
Instance(entity)
}
}
pub trait Duck {
fn add(entity: &mut EntityCommands);
}
trait InstanceCommands {
fn new<T>() -> {
}
}
impl InstanceCommands for Commands {
} }
pub fn setup(app: &mut App) { pub fn setup(app: &mut App) {

View File

@@ -1,12 +1,12 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use bevy::prelude::*; use bevy::prelude::*;
use mlua::{UserDataFields, UserDataMethods}; use mlua::{FromLua, Lua, UserDataFields, UserDataMethods, Value};
use mlua::prelude::{LuaUserDataFields, LuaUserDataMethods}; use mlua::prelude::{LuaUserData, LuaUserDataFields, LuaUserDataMethods};
use crate::duck::instance::*; use crate::duck::instance::*;
pub struct Part; pub struct Part;
impl Class for Part { impl Duck for Part {
fn add_to(entity: &mut EntityCommands) -> Instance { fn add(entity: &mut EntityCommands) {
let id = entity.id(); let id = entity.id();
entity.commands().run_system_cached_with(move | entity.commands().run_system_cached_with(move |
In(id): In<Entity>, In(id): In<Entity>,
@@ -18,7 +18,6 @@ impl Class for Part {
entity.insert((Mesh3d(mesh.clone()),MeshMaterial3d(mat.clone()))); entity.insert((Mesh3d(mesh.clone()),MeshMaterial3d(mat.clone())));
} }
},id); },id);
Instance::Part(Object::<Part>::of(entity.id()))
} }
} }
@@ -36,6 +35,25 @@ pub fn setup(app: &mut App) {
} }
pub(crate) fn add_fields<F: LuaUserDataFields<Instance>>(fields: &mut F) { pub(crate) fn add_fields<F: LuaUserDataFields<Instance>>(fields: &mut F) {
fields.add_field_method_get("transform",|lua: Lua, this| {
Ok(world(&lua)?.get::<Transform>(this.0).unwrap())
});
fields.add_field_method_set("transform",|lua: Lua, this,transform: Transform| {
Ok(())
});
}
impl FromLua for Transform {
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> {
match value {
Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
_ => unreachable!(),
}
}
}
struct Transform(bevy::prelude::Transform);
impl LuaUserData for Transform {
} }

View File

@@ -40,10 +40,9 @@ impl AssetLoader for ScriptAssetLoader {
} }
#[derive(Component)] #[derive(Component)]
struct ScriptHandle(Handle<ScriptAsset>); struct Script(Handle<ScriptAsset>);
pub struct Script; impl Duck for Script {
impl Class for Script {
fn add_to(entity: &mut EntityCommands) -> Instance { fn add_to(entity: &mut EntityCommands) -> Instance {
let id = entity.id(); let id = entity.id();
entity.commands().run_system_cached_with(| // Get commands -> defer a system entity.commands().run_system_cached_with(| // Get commands -> defer a system
@@ -52,17 +51,9 @@ impl Class for Script {
script: Res<DefaultAsset<ScriptAsset>> // The default script asset to load it with script: Res<DefaultAsset<ScriptAsset>> // The default script asset to load it with
| { | {
if let Ok(mut entity) = commands.get_entity(id) { if let Ok(mut entity) = commands.get_entity(id) {
entity.insert(ScriptHandle(script.clone())); entity.insert(Script(script.clone()));
} }
},id); },id);
Self::run(entity);
Instance::Script(Object::<Script>::of(entity.id()))
}
fn fields<S: Class, F: LuaUserDataFields<Object<S>>>(fields: &mut F) {
}
fn methods<S: Class, F: LuaUserDataMethods<Object<S>>>(methods: &mut F) {
} }
} }
@@ -70,7 +61,7 @@ fn run(entity: &mut EntityCommands) {
let id= entity.id(); let id= entity.id();
entity.commands().run_system_cached_with(| // Get commands -> defer a system: entity.commands().run_system_cached_with(| // Get commands -> defer a system:
In(id): In<Entity>, In(id): In<Entity>,
query: Query<&ScriptHandle>, // A query to find it again query: Query<&Script>, // A query to find it again
context: Res<DefaultScriptContext>, // A resource for our script context context: Res<DefaultScriptContext>, // A resource for our script context
scripts: Res<Assets<ScriptAsset>> // The assets resource for all our scripts scripts: Res<Assets<ScriptAsset>> // The assets resource for all our scripts
| { | {
@@ -78,7 +69,7 @@ fn run(entity: &mut EntityCommands) {
let asset = scripts.get(script.0.id()).unwrap(); // Get the asset (!) let asset = scripts.get(script.0.id()).unwrap(); // Get the asset (!)
let lua = &context.0; let lua = &context.0;
let chunk = lua.load(asset.source.clone()).set_environment(lua.globals()); let chunk = lua.load(asset.source.clone()).set_environment(lua.globals());
chunk.environment().unwrap().set("script",Instance(id)).unwrap(); chunk.environment().unwrap().set("script",Instance::of(id)).unwrap();
match chunk.exec() { match chunk.exec() {
Ok(()) => {}, Ok(()) => {},
Err(e) => { println!("Error: {:?}", e); } Err(e) => { println!("Error: {:?}", e); }

View File

@@ -16,6 +16,7 @@ fn setup(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) { ) {
commands.new::<>();
// circular base // circular base
commands.spawn(( commands.spawn((
Mesh3d(meshes.add(Circle::new(4.0))), Mesh3d(meshes.add(Circle::new(4.0))),
@@ -41,6 +42,4 @@ fn setup(
Camera3d::default(), Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
)); ));
commands.new::<Script>();
commands.new::<Script>();
} }