rbx_loader: use extended instance

This commit is contained in:
Quaternions 2025-04-17 16:46:51 -07:00
parent 0a3825ca2d
commit 04d7694da4
Signed by: Quaternions
GPG Key ID: D0DF5964F79AC131
2 changed files with 33 additions and 36 deletions
lib/rbx_loader/src

@ -1,5 +1,5 @@
use std::io::Read;
use rbx_dom_weak::WeakDom;
use roblox_emulator::types::WeakDom;
use strafesnet_deferred_loader::deferred_loader::{LoadFailureMode,MeshDeferredLoader,RenderConfigDeferredLoader};
mod rbx;
@ -95,8 +95,8 @@ pub fn read<R:Read>(input:R)->Result<Model,ReadError>{
let mut buf=std::io::BufReader::new(input);
let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?;
match &peek[0..8]{
b"<roblox!"=>rbx_binary::from_reader(buf).map(Model::new).map_err(ReadError::RbxBinary),
b"<roblox "=>rbx_xml::from_reader_default(buf).map(Model::new).map_err(ReadError::RbxXml),
b"<roblox!"=>rbx_binary::from_reader_generic(buf).map(Model::new).map_err(ReadError::RbxBinary),
b"<roblox "=>rbx_xml::from_reader_generic(buf,Default::default()).map(Model::new).map_err(ReadError::RbxXml),
_=>Err(ReadError::UnknownFileFormat),
}
}

@ -2,6 +2,7 @@ use std::collections::HashMap;
use crate::loader::MeshIndex;
use crate::primitives::{self,CubeFace,CubeFaceDescription,WedgeFaceDescription,CornerWedgeFaceDescription,FaceDescription,Primitives};
use rbx_dom_weak::ustr;
use roblox_emulator::types::{WeakDom,Instance};
use strafesnet_common::aabb::Aabb;
use strafesnet_common::map;
use strafesnet_common::model;
@ -14,30 +15,23 @@ use strafesnet_deferred_loader::deferred_loader::{RenderConfigDeferredLoader,Mes
use strafesnet_deferred_loader::mesh::Meshes;
use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
fn class_is_a(class: &str, superclass: &str) -> bool {
if class==superclass {
return true
}
let class_descriptor=rbx_reflection_database::get().classes.get(class);
if let Some(descriptor) = &class_descriptor {
if let Some(class_super) = &descriptor.superclass {
return class_is_a(&class_super, superclass)
}
}
false
}
fn recursive_collect_superclass(objects: &mut std::vec::Vec<rbx_dom_weak::types::Ref>,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, superclass: &str){
let mut stack=vec![instance];
while let Some(item)=stack.pop(){
for &referent in item.children(){
if let Some(c)=dom.get_by_ref(referent){
if class_is_a(c.class.as_str(),superclass){
objects.push(c.referent());//copy ref
}
stack.push(c);
}
}
}
fn recursive_collect_superclass(
objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,
dom:&WeakDom,
instance:&Instance,
superclass:&str
){
let instance=instance.as_ref();
let db=rbx_reflection_database::get();
let Some(superclass)=db.classes.get(superclass)else{
return;
};
objects.extend(
dom.descendants_of(instance.as_ref().referent()).filter_map(|instance|{
let class=db.classes.get(instance.as_ref().class.as_str())?;
db.has_superclass(class,superclass).then(||instance.as_ref().referent())
})
);
}
fn planar64_affine3_from_roblox(cf:&rbx_dom_weak::types::CFrame,size:&rbx_dom_weak::types::Vector3)->Planar64Affine3{
Planar64Affine3::new(
@ -405,19 +399,20 @@ fn get_content_url(content:&rbx_dom_weak::types::Content)->Option<&str>{
fn get_texture_description<'a>(
temp_objects:&mut Vec<rbx_dom_weak::types::Ref>,
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
dom:&'a rbx_dom_weak::WeakDom,
object:&rbx_dom_weak::Instance,
dom:&'a WeakDom,
object:&Instance,
size:&rbx_dom_weak::types::Vector3,
)->RobloxPartDescription{
//use the biggest one and cut it down later...
let mut part_texture_description=RobloxPartDescription::default();
temp_objects.clear();
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
recursive_collect_superclass(temp_objects,dom,object,"Decal");
for &mut decal_ref in temp_objects{
let Some(decal)=dom.get_by_ref(decal_ref) else{
println!("Decal get_by_ref failed");
continue;
};
let decal=decal.as_ref();
let (
Some(rbx_dom_weak::types::Variant::ContentId(content)),
Some(rbx_dom_weak::types::Variant::Enum(normalid)),
@ -521,7 +516,7 @@ struct GetAttributesArgs<'a>{
velocity:Planar64Vec3,
}
pub fn convert<'a>(
dom:&'a rbx_dom_weak::WeakDom,
dom:&'a WeakDom,
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
mesh_deferred_loader:&mut MeshDeferredLoader<MeshIndex<'a>>,
)->PartialMap1<'a>{
@ -536,9 +531,10 @@ pub fn convert<'a>(
let mut object_refs=Vec::new();
let mut temp_objects=Vec::new();
recursive_collect_superclass(&mut object_refs, &dom, dom.root(),"BasePart");
for object_ref in object_refs {
if let Some(object)=dom.get_by_ref(object_ref){
recursive_collect_superclass(&mut object_refs,dom,dom.root(),"BasePart");
for object_ref in object_refs{
if let Some(object_extended)=dom.get_by_ref(object_ref){
let object=object_extended.as_ref();
if let (
Some(rbx_dom_weak::types::Variant::CFrame(cf)),
Some(rbx_dom_weak::types::Variant::Vector3(size)),
@ -561,6 +557,7 @@ pub fn convert<'a>(
let mut parent_ref=object.parent();
let mut full_path=object.name.clone();
while let Some(parent)=dom.get_by_ref(parent_ref){
let parent=parent.as_ref();
full_path=format!("{}.{}",parent.name,full_path);
parent_ref=parent.parent();
}
@ -590,7 +587,7 @@ pub fn convert<'a>(
let (availability,mesh_id)=match shape{
Shape::Primitive(primitive_shape)=>{
//TODO: TAB TAB
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object_extended,size);
//obscure rust syntax "slice pattern"
let RobloxPartDescription([
f0,//Cube::Right
@ -671,7 +668,7 @@ pub fn convert<'a>(
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(&ustr("PhysicsData")){
physics_data=data.as_ref();
}
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object_extended,size);
let mesh_index=MeshIndex::union(content,mesh_data,physics_data,size,part_texture_description.clone());
let mesh_id=mesh_deferred_loader.acquire_mesh_id(mesh_index);
(MeshAvailability::DeferredUnion(part_texture_description),mesh_id)