bones_scripting/lua/bindings/
components.rs1use super::*;
2
3pub fn metatable(ctx: Context) -> Table {
4 let metatable = Table::new(&ctx);
5 metatable
6 .set(
7 ctx,
8 "__tostring",
9 Callback::from_fn(&ctx, |ctx, _fuel, mut stack| {
10 stack.push_front(
11 piccolo::String::from_static(&ctx, "Components { insert, remove, get }").into(),
12 );
13 Ok(CallbackReturn::Return)
14 }),
15 )
16 .unwrap();
17 metatable
18 .set(ctx, "__newindex", ctx.singletons().get(ctx, no_newindex))
19 .unwrap();
20
21 let get_callback = ctx.registry().stash(
22 &ctx,
23 Callback::from_fn(&ctx, |ctx, _fuel, mut stack| {
24 let (world, entity_ecsref, schema): (&WorldRef, &EcsRef, UserData) =
25 stack.consume(ctx)?;
26
27 let b = entity_ecsref.borrow();
28 let entity = *b.schema_ref()?.try_cast::<Entity>()?;
29
30 let schema = *schema.downcast_static::<&Schema>()?;
31
32 let store = world.with(|world| {
33 let store = world.components.get_cell_by_schema(schema);
34 Ok::<_, anyhow::Error>(store)
35 })?;
36
37 let ecsref = EcsRef {
38 data: EcsRefData::Component(ComponentRef { store, entity }),
39 path: default(),
40 };
41
42 if ecsref.borrow().schema_ref().is_err() {
44 stack.replace(ctx, Value::Nil);
45 return Ok(CallbackReturn::Return);
46 }
47
48 let ecsref = ecsref.into_value(ctx);
49 stack.replace(ctx, ecsref);
50
51 Ok(CallbackReturn::Return)
52 }),
53 );
54 let insert_callback = ctx.registry().stash(
55 &ctx,
56 Callback::from_fn(&ctx, |ctx, _fuel, mut stack| {
57 let (world, entity_ecsref, value_ecsref): (&WorldRef, &EcsRef, &EcsRef) =
58 stack.consume(ctx)?;
59
60 let b = entity_ecsref.borrow();
61 let entity = *b.schema_ref()?.try_cast::<Entity>()?;
62
63 let value = {
64 let b = value_ecsref.borrow();
65 let value = b.schema_ref()?;
66 value.clone_into_box()
67 };
68
69 world.with(|world| {
70 let store = world.components.get_by_schema(value.schema());
71 let mut store = store.borrow_mut();
72 store.insert_box(entity, value);
73 Ok::<_, anyhow::Error>(())
74 })?;
75
76 Ok(CallbackReturn::Return)
77 }),
78 );
79 let remove_callback = ctx.registry().stash(
80 &ctx,
81 Callback::from_fn(&ctx, |ctx, _fuel, mut stack| {
82 let (world, entity_ecsref, schema): (&WorldRef, &EcsRef, UserData) =
83 stack.consume(ctx)?;
84
85 let b = entity_ecsref.borrow();
86 let entity = *b.schema_ref()?.try_cast::<Entity>()?;
87
88 let schema = *schema.downcast_static::<&Schema>()?;
89
90 world.with(|world| {
91 let store = world.components.get_by_schema(schema);
92 let mut store = store.borrow_mut();
93 store.remove_box(entity);
94 Ok::<_, anyhow::Error>(())
95 })?;
96
97 Ok(CallbackReturn::Return)
98 }),
99 );
100
101 metatable
102 .set(
103 ctx,
104 "__index",
105 Callback::from_fn(&ctx, move |ctx, _fuel, mut stack| {
106 let (_world, key): (&WorldRef, lua::Value) = stack.consume(ctx)?;
107
108 if let Value::String(key) = key {
109 #[allow(clippy::single_match)]
110 match key.as_bytes() {
111 b"get" => {
112 stack.push_front(ctx.registry().fetch(&get_callback).into());
113 }
114 b"insert" => {
115 stack.push_front(ctx.registry().fetch(&insert_callback).into());
116 }
117 b"remove" => {
118 stack.push_front(ctx.registry().fetch(&remove_callback).into());
119 }
120 _ => (),
121 }
122 }
123
124 Ok(CallbackReturn::Return)
125 }),
126 )
127 .unwrap();
128
129 metatable
130}