2024-10-04 00:19:47 +00:00
|
|
|
use rbx_dom_weak::{types::Ref,InstanceBuilder,WeakDom};
|
2024-09-17 01:54:04 +00:00
|
|
|
|
|
|
|
pub fn class_is_a(class:&str,superclass:&str)->bool{
|
|
|
|
class==superclass
|
|
|
|
||rbx_reflection_database::get().classes.get(class)
|
|
|
|
.is_some_and(|descriptor|
|
|
|
|
descriptor.superclass.as_ref().is_some_and(|class_super|
|
|
|
|
class_is_a(class_super,superclass)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-09-20 20:51:17 +00:00
|
|
|
#[repr(transparent)]
|
2024-09-19 01:47:38 +00:00
|
|
|
pub struct Context{
|
|
|
|
pub(crate)dom:WeakDom,
|
2024-09-17 01:54:04 +00:00
|
|
|
}
|
|
|
|
|
2024-09-19 01:47:38 +00:00
|
|
|
impl Context{
|
2024-10-03 23:26:54 +00:00
|
|
|
pub const fn new(dom:WeakDom)->Self{
|
|
|
|
Self{dom}
|
2024-09-17 01:54:04 +00:00
|
|
|
}
|
2024-10-04 23:14:03 +00:00
|
|
|
pub fn script_singleton(source:String)->(Context,crate::runner::instance::Script,Services){
|
2024-10-04 00:19:47 +00:00
|
|
|
let script=InstanceBuilder::new("Script")
|
|
|
|
.with_property("Source",rbx_types::Variant::String(source));
|
|
|
|
let script_ref=script.referent();
|
2024-10-04 23:14:03 +00:00
|
|
|
let mut context=Self::new(WeakDom::new(
|
|
|
|
InstanceBuilder::new("DataModel")
|
|
|
|
.with_child(script)
|
|
|
|
));
|
|
|
|
let services=context.convert_into_place();
|
|
|
|
(context,crate::runner::instance::Script::new(script_ref),services)
|
2024-09-28 19:32:19 +00:00
|
|
|
}
|
2024-10-04 23:32:49 +00:00
|
|
|
pub fn from_ref(dom:&WeakDom)->&Context{
|
|
|
|
unsafe{&*(dom as *const WeakDom as *const Context)}
|
|
|
|
}
|
2024-09-20 20:51:17 +00:00
|
|
|
pub fn from_mut(dom:&mut WeakDom)->&mut Context{
|
|
|
|
unsafe{&mut *(dom as *mut WeakDom as *mut Context)}
|
2024-09-19 01:47:38 +00:00
|
|
|
}
|
2024-09-17 01:54:04 +00:00
|
|
|
/// Creates an iterator over all items of a particular class.
|
|
|
|
pub fn superclass_iter<'a>(&'a self,superclass:&'a str)->impl Iterator<Item=Ref>+'a{
|
|
|
|
self.dom.descendants().filter(|&instance|
|
|
|
|
class_is_a(instance.class.as_ref(),superclass)
|
|
|
|
).map(|instance|instance.referent())
|
|
|
|
}
|
2024-09-21 20:26:20 +00:00
|
|
|
pub fn scripts(&self)->Vec<crate::runner::instance::Script>{
|
|
|
|
self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Script::new).collect()
|
2024-09-17 01:54:04 +00:00
|
|
|
}
|
2024-10-04 23:14:03 +00:00
|
|
|
|
|
|
|
pub fn find_services(&self)->Option<Services>{
|
|
|
|
Some(Services{
|
|
|
|
workspace:*self.dom.root().children().iter().find(|&&r|
|
|
|
|
self.dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
|
|
|
|
)?,
|
|
|
|
game:self.dom.root_ref(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
pub fn convert_into_place(&mut self)->Services{
|
|
|
|
//snapshot root instances
|
|
|
|
let children=self.dom.root().children().to_owned();
|
|
|
|
|
|
|
|
//insert services
|
|
|
|
let game=self.dom.root_ref();
|
|
|
|
let workspace=self.dom.insert(game,
|
|
|
|
InstanceBuilder::new("Workspace")
|
|
|
|
.with_child(InstanceBuilder::new("Terrain"))
|
|
|
|
);
|
|
|
|
self.dom.insert(game,InstanceBuilder::new("Lighting"));
|
|
|
|
|
|
|
|
//transfer original root instances into workspace
|
|
|
|
for instance in children{
|
|
|
|
self.dom.transfer_within(instance,workspace);
|
|
|
|
}
|
|
|
|
|
|
|
|
Services{
|
|
|
|
game,
|
|
|
|
workspace,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Services{
|
|
|
|
pub game:Ref,
|
|
|
|
pub workspace:Ref,
|
2024-09-17 01:54:04 +00:00
|
|
|
}
|