use rbx_dom_weak::{types::Ref,InstanceBuilder,WeakDom}; 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) ) ) } #[repr(transparent)] pub struct Context{ pub(crate)dom:WeakDom, } impl Context{ pub const fn new(dom:WeakDom)->Self{ Self{dom} } pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance,Services){ let script=InstanceBuilder::new("Script") .with_property("Source",rbx_types::Variant::String(source)); let script_ref=script.referent(); let mut context=Self::new(WeakDom::new( InstanceBuilder::new("DataModel") .with_child(script) )); let services=context.convert_into_place(); (context,crate::runner::instance::Instance::new(script_ref),services) } pub fn from_ref(dom:&WeakDom)->&Context{ unsafe{&*(dom as *const WeakDom as *const Context)} } pub fn from_mut(dom:&mut WeakDom)->&mut Context{ unsafe{&mut *(dom as *mut WeakDom as *mut Context)} } /// Creates an iterator over all items of a particular class. pub fn superclass_iter<'a>(&'a self,superclass:&'a str)->impl Iterator+'a{ self.dom.descendants().filter(|&instance| class_is_a(instance.class.as_ref(),superclass) ).map(|instance|instance.referent()) } pub fn scripts(&self)->Vec{ self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Instance::new).collect() } pub fn find_services(&self)->Option{ 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 terrain_bldr=InstanceBuilder::new("Terrain"); let workspace=self.dom.insert(game, InstanceBuilder::new("Workspace") //Set Workspace.Terrain property equal to Terrain .with_property("Terrain",terrain_bldr.referent()) .with_child(terrain_bldr) ); { //Lowercase and upper case workspace property! let game=self.dom.root_mut(); game.properties.insert("workspace".to_owned(),rbx_types::Variant::Ref(workspace)); game.properties.insert("Workspace".to_owned(),rbx_types::Variant::Ref(workspace)); } 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, }