diff --git a/pof/src/parse.rs b/pof/src/parse.rs index b87ed03..a9cb92d 100644 --- a/pof/src/parse.rs +++ b/pof/src/parse.rs @@ -253,7 +253,14 @@ impl Parser { b"EYE " => { eye_points = Some(self.read_list(|this| { Ok(EyePoint { - attached_subobj: ObjectId(this.read_u32()?), + attached_subobj: { + let id = this.read_u32()?; + if id == u32::MAX { + None + } else { + Some(ObjectId(id)) + } + }, position: this.read_vec3d()?, normal: this.read_vec3d()?.try_into().unwrap_or_default(), }) @@ -814,8 +821,13 @@ trait IsNode<'a>: Clone { fn parse_properties(&self, properties: &mut String) { for node in self.children() { - if let Some(name) = node.name() { + if let Some(mut name) = node.name() { if let Some(idx) = name.find(":") { + if let Some(idx2) = name.find(".") { + if name.find("fvec").is_none() && name.find("uvec").is_none() { + name = &name[0..idx2]; + } + } if properties.is_empty() { *properties = format!("{}", &name[(idx + 1)..]); } else { @@ -1016,6 +1028,7 @@ trait ParseCtx<'a> { let up = self.up(); let offset = Vec3d::from(center).from_coord(up); + println!("{:?}", node.name()); let name = match node.name() { Some(name) => name, None => continue, @@ -1283,7 +1296,7 @@ trait ParseCtx<'a> { for (_, name) in node_children_with_keyword(node, "parent") { if let Some(idx) = name.find(":") { if let Ok(val) = &name[(idx + 1)..].parse() { - new_point.attached_subobj = ObjectId(*val); + new_point.attached_subobj = Some(ObjectId(*val)); break; } } @@ -1603,7 +1616,13 @@ pub fn parse_gltf(path: std::path::PathBuf) -> Model { model.path_to_file = path.canonicalize().unwrap_or(path); model.textures = gltf .materials() - .map(|mat| mat.name().unwrap().strip_suffix("-material").unwrap_or(mat.name().unwrap()).to_string()) + .map(|mat| { + let mut name = mat.name().unwrap().strip_suffix("-material").unwrap_or(mat.name().unwrap()); + if let Some(idx) = name.find(".") { + name = &name[0..idx]; + } + name.to_string() + }) .collect(); GltfContext { buffers }.parse_top_level_nodes(&mut model, gltf.default_scene().expect("Default scene in gltf file not set!").nodes()); diff --git a/pof/src/types.rs b/pof/src/types.rs index 78232e5..30bd990 100644 --- a/pof/src/types.rs +++ b/pof/src/types.rs @@ -602,7 +602,7 @@ mk_struct! { #[derive(Default, Debug, Clone)] pub struct EyePoint { - pub attached_subobj: ObjectId, + pub attached_subobj: Option, pub position: Vec3d, pub normal: NormalVec3, } diff --git a/pof/src/write.rs b/pof/src/write.rs index 143b1a1..969ea72 100644 --- a/pof/src/write.rs +++ b/pof/src/write.rs @@ -744,9 +744,11 @@ fn make_eyes_node(ctx: &mut N::Ctx, eye_points: &[EyePoint], up: UpAxis point_node.translate(pos.into()); point_node.rotate(vec_to_rotation(&point.normal.0, up)); - point_node - .children() - .push(N::from_name(format!("#e{}-parent", i), format!("#e{}-parent:{}", i, point.attached_subobj.0)).build(ctx)); + if let Some(id) = point.attached_subobj { + point_node + .children() + .push(N::from_name(format!("#e{}-parent", i), format!("#e{}-parent:{}", i, id.0)).build(ctx)); + } node.children().push(point_node.build(ctx)); } diff --git a/src/ui.rs b/src/ui.rs index 6c6d88e..9587d54 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1625,7 +1625,15 @@ impl PofToolsGui { ui_state.tree_selectable_item( &self.model, ui, - &format!("{} {}", self.model.sub_objects[eye.attached_subobj].name, i + 1), + &format!( + "{} {}", + if let Some(id) = eye.attached_subobj { + &self.model.sub_objects[id].name + } else { + "(None)" + }, + i + 1 + ), TreeValue::EyePoints(EyeTreeValue::EyePoint(i)), ); } diff --git a/src/ui_properties_panel.rs b/src/ui_properties_panel.rs index daf7565..ce3d96d 100644 --- a/src/ui_properties_panel.rs +++ b/src/ui_properties_panel.rs @@ -622,7 +622,7 @@ impl UiState { self.properties_panel = PropertiesPanel::EyePoint { position_string: format!("{}", model.eye_points[idx].position), normal_string: format!("{}", model.eye_points[idx].normal.0), - attached_subobj_idx: model.eye_points[idx].attached_subobj.0 as usize, + attached_subobj_idx: model.eye_points[idx].attached_subobj.map_or(model.sub_objects.len(), |id| id.0 as usize), } } _ => self.properties_panel = PropertiesPanel::default_eye(), @@ -2573,10 +2573,17 @@ impl PofToolsGui { ui.add_enabled_ui(eye_num.is_some(), |ui| { if let Some(num) = eye_num { - let name_list = self.model.get_subobj_names(); + let mut name_list = self.model.get_subobj_names(); + if self.model.eye_points[num].attached_subobj.is_none() { + name_list.push("None".to_string()); + } + egui::ComboBox::from_label("Attached submodel") - .show_index(ui, attached_subobj_idx, self.model.sub_objects.len(), |i| name_list[i].to_owned()); - self.model.eye_points[num].attached_subobj = ObjectId(*attached_subobj_idx as u32); + .show_index(ui, attached_subobj_idx, name_list.len(), |i| name_list[i].to_owned()); + + if *attached_subobj_idx < self.model.sub_objects.len() { + self.model.eye_points[num].attached_subobj = Some(ObjectId(*attached_subobj_idx as u32)); + } } else { egui::ComboBox::from_label("Attached submodel").show_index(ui, attached_subobj_idx, 1, |_| format!("")); }