197 lines
5.0 KiB
Rust
197 lines
5.0 KiB
Rust
use bevy::ecs::resource;
|
|
use mlua::UserData;
|
|
use mlua::Lua;
|
|
use bevy::prelude::*;
|
|
use mlua::UserDataFields;
|
|
use mlua::UserDataMethods;
|
|
use nameof::name_of_type;
|
|
use std::ops::Deref;
|
|
use std::ops::DerefMut;
|
|
|
|
use include_dir::{include_dir, Dir};
|
|
|
|
static DATA_DIR: Dir<'_> = include_dir!("data");
|
|
|
|
struct Context<'a> {
|
|
commands: Commands<'a, 'a>,
|
|
resource: Option<&'a Resource>
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct Resource {
|
|
default_script_context: Entity
|
|
}
|
|
impl Resource {
|
|
fn new_from_world(world: &mut World) -> Self {
|
|
let mut context = Context { commands: world.commands(), resource: Option::None };
|
|
let (entity_commands,_) = ScriptContext::new_entity( &mut context );
|
|
Resource {
|
|
default_script_context: entity_commands.id()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Id for this object to the server
|
|
struct Netlink {
|
|
|
|
}
|
|
trait Class {
|
|
// Class name for filtering
|
|
fn class_name() -> String { name_of_type!(Self).into() }
|
|
// Create a default object
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>, Self) where Self: Sized;
|
|
// fn clone(&self) -> Self;
|
|
fn add_fields<T, F: UserDataFields<T>>(_fields: &mut F) {}
|
|
fn add_methods<T, F: UserDataMethods<T>>(_methods: &mut F) {}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
struct Instance<S: Class> {
|
|
name: String,
|
|
class: S,
|
|
entity: Entity,
|
|
netlink: Netlink
|
|
}
|
|
impl<S: Class> UserData for Instance<S> {
|
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
|
S::add_fields::<Self,F>(fields);
|
|
}
|
|
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
|
S::add_methods::<Self,M>(methods);
|
|
}
|
|
}
|
|
impl<S: Class> Instance<S> {
|
|
fn new_entity(context: &'_ mut Context) -> Self {
|
|
let (entity,sub) = S::new_entity(context);
|
|
Instance {
|
|
name: S::class_name(),
|
|
class: sub,
|
|
entity: entity.id(),
|
|
netlink: Netlink {},
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Constructor;
|
|
|
|
impl UserData for Constructor {
|
|
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
|
methods.add_method("part",|lua, this: &Constructor, ()| {
|
|
Ok(IPart::new_entity(lua.app_data_mut::<Context>().unwrap().deref_mut()))
|
|
});
|
|
methods.add_method("script",|lua, this: &Constructor, ()| {
|
|
Ok(IScript::new_entity(lua.app_data_mut::<Context>().unwrap().deref_mut()))
|
|
});
|
|
}
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct ScriptContext {
|
|
lua: Lua
|
|
}
|
|
impl Class for ScriptContext {
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>,Self) {
|
|
( context.commands.spawn_empty(), ScriptContext::new() )
|
|
}
|
|
}
|
|
impl ScriptContext {
|
|
fn new() -> Self {
|
|
let lua = Lua::new();
|
|
lua.sandbox(true);
|
|
let globals = lua.globals();
|
|
globals.set("new",Constructor);
|
|
ScriptContext { lua: lua }
|
|
}
|
|
}
|
|
|
|
struct Script {
|
|
context: Entity
|
|
}
|
|
impl Class for Script {
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>, Self) {
|
|
(
|
|
context.commands.spawn_empty(),
|
|
Script {
|
|
context: context.resource.as_ref().unwrap().default_script_context
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
// Attachment
|
|
struct Node;
|
|
impl Class for Node {
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>, Self) {
|
|
( context.commands.spawn_empty(), Node {} )
|
|
}
|
|
}
|
|
|
|
struct Part {
|
|
|
|
}
|
|
impl Class for Part {
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>, Self) {
|
|
( context.commands.spawn_empty(), Part {} )
|
|
}
|
|
}
|
|
impl UserData for Part {}
|
|
|
|
struct Located<S: Class> {
|
|
class: S
|
|
}
|
|
impl<S: Class> UserData for Located<S> {
|
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
|
S::add_fields(fields);
|
|
}
|
|
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
|
S::add_methods(methods);
|
|
}
|
|
}
|
|
impl<S: Class> Class for Located<S> {
|
|
fn new_entity<'a>(context: &'a mut Context) -> (EntityCommands<'a>,Self) {
|
|
let (entity,sub) = S::new_entity(context);
|
|
( entity, Located { class: sub } )
|
|
}
|
|
}
|
|
|
|
type IAttachment = Instance<Located<Node>>;
|
|
type IModel = Instance<Located<Node>>;
|
|
type IPart = Instance<Located<Part>>;
|
|
type IContext = Instance<ScriptContext>;
|
|
type IScript = Instance<Script>;
|
|
type IFolder = Instance<Node>;
|
|
|
|
#[derive(Component)]
|
|
enum AnyInstance {
|
|
Attachment(IAttachment),
|
|
Context(IContext),
|
|
Folder(IFolder),
|
|
Script(IScript),
|
|
Model(IModel),
|
|
Part(IPart)
|
|
}
|
|
|
|
fn script_executor(mut commands: Commands, resource: Res<Resource>) {
|
|
|
|
}
|
|
|
|
fn script_test(commands: Commands, resource: Res<Resource>) {
|
|
let mut context = Context {commands: commands, resource: Some(resource.as_ref())};
|
|
IScript::new_entity(&mut context);
|
|
}
|
|
|
|
fn setup(world: &mut World) {
|
|
let res = Resource::new_from_world(world);
|
|
world.insert_resource(res);
|
|
}
|
|
|
|
pub struct DuckPlugin;
|
|
|
|
impl Plugin for DuckPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(Startup,setup);
|
|
app.add_systems(Update,script_executor);
|
|
app.add_systems(Startup,script_test);
|
|
app.insert_resource(ScriptContext::new());
|
|
}
|
|
} |