Compare commits
2 Commits
5726e70582
...
8d0807a12b
Author | SHA1 | Date | |
---|---|---|---|
8d0807a12b | |||
6dfa46bc67 |
@ -47,12 +47,8 @@ impl Context{
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_services(&self)->Option<Services>{
|
pub fn find_services(&self)->Option<Services>{
|
||||||
Some(Services{
|
//nil instances isn't real, it doesn't exist in real roblox places
|
||||||
workspace:*self.dom.root().children().iter().find(|&&r|
|
None
|
||||||
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{
|
pub fn convert_into_place(&mut self)->Services{
|
||||||
//snapshot root instances
|
//snapshot root instances
|
||||||
@ -74,6 +70,15 @@ impl Context{
|
|||||||
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"));
|
self.dom.insert(game,InstanceBuilder::new("Lighting"));
|
||||||
|
// Special nonexistent class that holds instances parented to nil,
|
||||||
|
// which can still be referenced by scripts.
|
||||||
|
// Using a sentinel value as a ref because global variables are hard.
|
||||||
|
let nil=self.dom.insert(
|
||||||
|
game,InstanceBuilder::new("Nil")
|
||||||
|
.with_referent(
|
||||||
|
<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
//transfer original root instances into workspace
|
//transfer original root instances into workspace
|
||||||
for instance in children{
|
for instance in children{
|
||||||
@ -83,6 +88,7 @@ impl Context{
|
|||||||
Services{
|
Services{
|
||||||
game,
|
game,
|
||||||
workspace,
|
workspace,
|
||||||
|
nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,4 +96,5 @@ impl Context{
|
|||||||
pub struct Services{
|
pub struct Services{
|
||||||
pub game:Ref,
|
pub game:Ref,
|
||||||
pub workspace:Ref,
|
pub workspace:Ref,
|
||||||
|
pub nil:Ref,
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
|||||||
instance_table.raw_set("new",
|
instance_table.raw_set("new",
|
||||||
lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{
|
lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{
|
||||||
let class_name_str=&*class_name.to_str()?;
|
let class_name_str=&*class_name.to_str()?;
|
||||||
let parent=parent.ok_or(mlua::Error::runtime("Nil Parent not yet supported"))?;
|
let parent=parent.unwrap_or(Instance::nil());
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
//TODO: Nil instances
|
|
||||||
Ok(Instance::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
|
Ok(Instance::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -91,6 +90,12 @@ impl Instance{
|
|||||||
pub const fn new(referent:Ref)->Self{
|
pub const fn new(referent:Ref)->Self{
|
||||||
Self{referent}
|
Self{referent}
|
||||||
}
|
}
|
||||||
|
// Using a sentinel value as a ref for nil instances because global variables are hard.
|
||||||
|
pub fn nil()->Self{
|
||||||
|
Self{
|
||||||
|
referent:<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn get<'a>(&self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{
|
pub fn get<'a>(&self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{
|
||||||
dom.get_by_ref(self.referent).ok_or(mlua::Error::runtime("Instance missing"))
|
dom.get_by_ref(self.referent).ok_or(mlua::Error::runtime("Instance missing"))
|
||||||
}
|
}
|
||||||
@ -124,11 +129,12 @@ impl mlua::UserData for Instance{
|
|||||||
fields.add_field_method_get("Parent",|lua,this|{
|
fields.add_field_method_get("Parent",|lua,this|{
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
let instance=this.get(dom)?;
|
let instance=this.get(dom)?;
|
||||||
|
//TODO: return nil when parent is Nil instances
|
||||||
Ok(Instance::new(instance.parent()))
|
Ok(Instance::new(instance.parent()))
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
fields.add_field_method_set("Parent",|lua,this,val:Option<Instance>|{
|
fields.add_field_method_set("Parent",|lua,this,val:Option<Instance>|{
|
||||||
let parent=val.ok_or(mlua::Error::runtime("Nil Parent not yet supported"))?;
|
let parent=val.unwrap_or(Instance::nil());
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
dom.transfer_within(this.referent,parent.referent);
|
dom.transfer_within(this.referent,parent.referent);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -218,7 +224,7 @@ impl mlua::UserData for Instance{
|
|||||||
);
|
);
|
||||||
methods.add_method("Destroy",|lua,this,()|
|
methods.add_method("Destroy",|lua,this,()|
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
dom.destroy(this.referent);
|
dom.transfer_within(this.referent,Instance::nil().referent);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -237,16 +243,27 @@ impl mlua::UserData for Instance{
|
|||||||
let class=db.classes.get(instance.class.as_str()).ok_or(mlua::Error::runtime("Class missing"))?;
|
let class=db.classes.get(instance.class.as_str()).ok_or(mlua::Error::runtime("Class missing"))?;
|
||||||
//Find existing property
|
//Find existing property
|
||||||
match instance.properties.get(index_str)
|
match instance.properties.get(index_str)
|
||||||
|
.cloned()
|
||||||
//Find default value
|
//Find default value
|
||||||
.or_else(||db.find_default_property(class,index_str))
|
.or_else(||db.find_default_property(class,index_str).cloned())
|
||||||
|
//Find virtual property
|
||||||
|
.or_else(||{
|
||||||
|
SuperClassIter{
|
||||||
|
database:db,
|
||||||
|
descriptor:Some(class),
|
||||||
|
}
|
||||||
|
.find_map(|class|
|
||||||
|
find_virtual_property(&instance.properties,class,index_str)
|
||||||
|
)
|
||||||
|
})
|
||||||
{
|
{
|
||||||
Some(&rbx_types::Variant::Int32(val))=>return val.into_lua(lua),
|
Some(rbx_types::Variant::Int32(val))=>return val.into_lua(lua),
|
||||||
Some(&rbx_types::Variant::Int64(val))=>return val.into_lua(lua),
|
Some(rbx_types::Variant::Int64(val))=>return val.into_lua(lua),
|
||||||
Some(&rbx_types::Variant::Float32(val))=>return val.into_lua(lua),
|
Some(rbx_types::Variant::Float32(val))=>return val.into_lua(lua),
|
||||||
Some(&rbx_types::Variant::Float64(val))=>return val.into_lua(lua),
|
Some(rbx_types::Variant::Float64(val))=>return val.into_lua(lua),
|
||||||
Some(&rbx_types::Variant::Ref(val))=>return Instance::new(val).into_lua(lua),
|
Some(rbx_types::Variant::Ref(val))=>return Instance::new(val).into_lua(lua),
|
||||||
Some(&rbx_types::Variant::CFrame(cf))=>return Into::<super::cframe::CFrame>::into(cf).into_lua(lua),
|
Some(rbx_types::Variant::CFrame(cf))=>return Into::<super::cframe::CFrame>::into(cf).into_lua(lua),
|
||||||
Some(&rbx_types::Variant::Vector3(v))=>return Into::<super::vector3::Vector3>::into(v).into_lua(lua),
|
Some(rbx_types::Variant::Vector3(v))=>return Into::<super::vector3::Vector3>::into(v).into_lua(lua),
|
||||||
None=>(),
|
None=>(),
|
||||||
other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance.name))),
|
other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance.name))),
|
||||||
}
|
}
|
||||||
@ -415,3 +432,51 @@ impl ClassMethods<'_>{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A virtual property pointer definition shorthand.
|
||||||
|
type VirtualPropertyFunctionPointer=fn(&rbx_types::Variant)->Option<rbx_types::Variant>;
|
||||||
|
const fn vpp(
|
||||||
|
property:&'static str,
|
||||||
|
pointer:VirtualPropertyFunctionPointer,
|
||||||
|
)->VirtualProperty{
|
||||||
|
VirtualProperty{
|
||||||
|
property,
|
||||||
|
pointer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct VirtualProperty{
|
||||||
|
property:&'static str,// Source property name
|
||||||
|
pointer:VirtualPropertyFunctionPointer,
|
||||||
|
}
|
||||||
|
type VPD=phf::Map<&'static str,// Class name
|
||||||
|
phf::Map<&'static str,// Virtual property name
|
||||||
|
VirtualProperty
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
static VIRTUAL_PROPERTY_DATABASE:VPD=phf::phf_map!{
|
||||||
|
"BasePart"=>phf::phf_map!{
|
||||||
|
"Position"=>vpp("CFrame",|c:&rbx_types::Variant|{
|
||||||
|
let c=match c{
|
||||||
|
rbx_types::Variant::CFrame(c)=>c,
|
||||||
|
_=>return None,//fail silently and ungracefully
|
||||||
|
};
|
||||||
|
Some(rbx_types::Variant::Vector3(c.position))
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn find_virtual_property(
|
||||||
|
properties:&HashMap<String,rbx_types::Variant>,
|
||||||
|
class:&rbx_reflection::ClassDescriptor,
|
||||||
|
index:&str
|
||||||
|
)->Option<rbx_types::Variant>{
|
||||||
|
//Find virtual property
|
||||||
|
let class_virtual_properties=VIRTUAL_PROPERTY_DATABASE.get(&class.name)?;
|
||||||
|
let virtual_property=class_virtual_properties.get(index)?;
|
||||||
|
|
||||||
|
//Get source property
|
||||||
|
let variant=properties.get(virtual_property.property)?;
|
||||||
|
|
||||||
|
//Transform Source property with provided function
|
||||||
|
(virtual_property.pointer)(variant)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user