diff --git a/src/load_roblox.rs b/src/load_roblox.rs index afa30c6..bb10df4 100644 --- a/src/load_roblox.rs +++ b/src/load_roblox.rs @@ -217,9 +217,30 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index * glam::Affine3A::from_scale( glam::Vec3::new(size.x,size.y,size.z)/2.0 ); - if object.name=="MapStart"{ - spawn_point=model_transform.transform_point3(-glam::Vec3::Y)+glam::vec3(0.0,2.5+0.1,0.0); - println!("Found MapStart{:?}",spawn_point); + + //push TempIndexedAttributes + let mut temp_indexing_attributes=Vec::new(); + if let Some(attr)=match &object.name[..]{ + "MapStart"=>{ + spawn_point=model_transform.transform_point3(glam::Vec3::ZERO)+glam::vec3(0.0,2.5,0.0); + Some(crate::model::TempIndexedAttributes::Start{mode_id:0}) + }, + "UnorderedCheckpoint"=>Some(crate::model::TempIndexedAttributes::UnorderedCheckpoint{mode_id:0}), + other=>{ + let regman=lazy_regex::regex!(r"^(BonusStart|Spawn|OrderedCheckpoint)(\d+)$"); + if let Some(captures) = regman.captures(other) { + match &captures[1]{ + "BonusStart"=>Some(crate::model::TempIndexedAttributes::Start{mode_id:captures[2].parse::().unwrap()}), + "Spawn"=>Some(crate::model::TempIndexedAttributes::Spawn{mode_id:0,stage_id:captures[2].parse::().unwrap()}), + "OrderedCheckpoint"=>Some(crate::model::TempIndexedAttributes::OrderedCheckpoint{mode_id:0,checkpoint_id:captures[2].parse::().unwrap()}), + _=>None, + } + }else{ + None + } + } + }{ + temp_indexing_attributes.push(attr); } //TODO: also detect "CylinderMesh" etc here @@ -420,6 +441,7 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index transform:model_transform, color:glam::vec4(color3.r as f32/255f32, color3.g as f32/255f32, color3.b as f32/255f32, 1.0-*transparency), attributes:get_attributes(&object.name,*can_collide,glam::vec3(velocity.x,velocity.y,velocity.z)), + temp_indexing:temp_indexing_attributes, }); } } diff --git a/src/main.rs b/src/main.rs index 4a219e6..8e14f2a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,14 +95,68 @@ impl GlobalState{ } fn generate_model_physics(&mut self,indexed_models:&model::IndexedModelInstances){ + let mut starts=Vec::new(); + let mut spawns=Vec::new(); + let mut ordered_checkpoints=Vec::new(); + let mut unordered_checkpoints=Vec::new(); for model in &indexed_models.models{ //make aabb and run vertices to get realistic bounds for model_instance in &model.instances{ if let Some(model_physics)=body::ModelPhysics::from_model(model,model_instance){ + let model_id=self.physics.models.len() as u32; + //snoop it before it gets stolen + for attr in model_instance.temp_indexing.iter(){ + match attr{ + model::TempIndexedAttributes::Start{mode_id}=>starts.push((*mode_id,model_id)), + model::TempIndexedAttributes::Spawn{mode_id,stage_id}=>spawns.push((*mode_id,model_id,*stage_id)), + model::TempIndexedAttributes::OrderedCheckpoint{mode_id,checkpoint_id}=>ordered_checkpoints.push((*mode_id,model_id,*checkpoint_id)), + model::TempIndexedAttributes::UnorderedCheckpoint{mode_id}=>unordered_checkpoints.push((*mode_id,model_id)), + } + } + //steal it self.physics.models.push(model_physics); } } } + //I don't wanna write structs for temporary structures + //this code builds ModeDescriptions from the unsorted lists at the top of the function + starts.sort_by_key(|tup|tup.0); + let mut eshmep=std::collections::HashMap::new(); + let mut modedatas:Vec<(u32,Vec<(u32,u32)>,Vec<(u32,u32)>,Vec)>=starts.into_iter().enumerate().map(|(i,tup)|{ + eshmep.insert(tup.0,i); + (tup.1,Vec::new(),Vec::new(),Vec::new()) + }).collect(); + for tup in spawns{ + if let Some(mode_id)=eshmep.get(&tup.0){ + if let Some(modedata)=modedatas.get_mut(*mode_id){ + modedata.1.push((tup.2,tup.1)); + } + } + } + for tup in ordered_checkpoints{ + if let Some(mode_id)=eshmep.get(&tup.0){ + if let Some(modedata)=modedatas.get_mut(*mode_id){ + modedata.2.push((tup.2,tup.1)); + } + } + } + for tup in unordered_checkpoints{ + if let Some(mode_id)=eshmep.get(&tup.0){ + if let Some(modedata)=modedatas.get_mut(*mode_id){ + modedata.3.push(tup.1); + } + } + } + self.physics.modes.append(&mut modedatas.into_iter().map(|mut tup|{ + tup.1.sort_by_key(|tup|tup.0); + tup.2.sort_by_key(|tup|tup.0); + model::ModeDescription{ + start:tup.0, + spawns:tup.1.into_iter().map(|tup|tup.1).collect(), + ordered_checkpoints:tup.2.into_iter().map(|tup|tup.1).collect(), + unordered_checkpoints:tup.3, + } + }).collect()); println!("Physics Objects: {}",self.physics.models.len()); } fn generate_model_graphics(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,indexed_models:model::IndexedModelInstances){ diff --git a/src/model.rs b/src/model.rs index 96df6ac..0386abf 100644 --- a/src/model.rs +++ b/src/model.rs @@ -60,6 +60,17 @@ pub struct ModelInstance{ pub transform:glam::Affine3A, pub color:glam::Vec4,//transparency is in here pub attributes:CollisionAttributes, + pub temp_indexing:Vec, +} +impl std::default::Default for ModelInstance{ + fn default() -> Self { + Self{ + color:glam::Vec4::ONE, + transform:Default::default(), + attributes:Default::default(), + temp_indexing:Default::default(), + } + } } pub struct IndexedModelInstances{ pub textures:Vec,//RenderPattern @@ -75,6 +86,22 @@ pub struct ModeDescription{ pub ordered_checkpoints:Vec,//ordered_checkpoints[checkpoint_id]=model_id pub unordered_checkpoints:Vec,//unordered_checkpoints[checkpoint_id]=model_id } +pub enum TempIndexedAttributes{ + Start{ + mode_id:u32, + }, + Spawn{ + mode_id:u32, + stage_id:u32, + }, + OrderedCheckpoint{ + mode_id:u32, + checkpoint_id:u32, + }, + UnorderedCheckpoint{ + mode_id:u32, + }, +} //you have this effect while in contact #[derive(Clone)]