diff --git a/pof/src/parse.rs b/pof/src/parse.rs index f740371..7ea9430 100644 --- a/pof/src/parse.rs +++ b/pof/src/parse.rs @@ -477,6 +477,15 @@ impl Parser { } }); + if let Some(points) = eye_points.as_deref_mut() { + for (i, eye) in points.iter_mut().enumerate() { + if eye.attached_subobj.map_or(false, |id| id.0 >= sub_objects.len() as u32) { + eye.attached_subobj = None; + warn!("Invalid eye point {} reset", i); + } + } + } + let mut textures = textures.unwrap_or_default(); let untextured_idx = post_parse_fill_untextured_slot(&mut sub_objects, &mut textures); diff --git a/pof/src/types.rs b/pof/src/types.rs index 30bd990..c0447a1 100644 --- a/pof/src/types.rs +++ b/pof/src/types.rs @@ -1960,6 +1960,11 @@ impl Model { Warning::InvalidDockParentSubmodel(idx) => self.docking_bays.get(*idx).map_or(false, |dock| { properties_get_field(&dock.properties, "$parent_submodel").map_or(false, |name| self.get_obj_id_by_name(name).is_none()) }), + Warning::Detail0NonZeroOffset => self + .header + .detail_levels + .get(0) + .map_or(false, |id| !self.sub_objects[*id].offset.is_null()), }; let existing_warning = self.warnings.contains(&warning); @@ -2092,6 +2097,12 @@ impl Model { self.warnings.insert(Warning::DuplicatePathName(duped_name.clone())); } + if let Some(id) = self.header.detail_levels.get(0) { + if !self.sub_objects[*id].offset.is_null() { + self.warnings.insert(Warning::Detail0NonZeroOffset); + } + } + for duped_id in self.header.detail_levels.iter().duplicates() { self.warnings.insert(Warning::DuplicateDetailLevel(*duped_id)); } @@ -2676,6 +2687,7 @@ pub enum Warning { TooManyEyePoints, TooManyTextures, InvalidDockParentSubmodel(usize), + Detail0NonZeroOffset, PathNameTooLong(usize), SpecialPointNameTooLong(usize), diff --git a/src/main.rs b/src/main.rs index 61f33ff..a998210 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,6 @@ use std::{ collections::HashMap, f32::consts::PI, fs::File, - hash::Hash, io::{Cursor, Read}, ops::{Deref, DerefMut}, path::PathBuf, diff --git a/src/ui.rs b/src/ui.rs index 9587d54..8d30b59 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -132,6 +132,7 @@ impl TreeValue { Warning::GlowBankPropertiesTooLong(idx) => Some(TreeValue::Glows(GlowTreeValue::Bank(*idx))), Warning::SpecialPointPropertiesTooLong(idx) => Some(TreeValue::SpecialPoints(SpecialPointTreeValue::Point(*idx))), Warning::InvalidDockParentSubmodel(idx) => Some(TreeValue::DockingBays(DockingTreeValue::Bay(*idx))), + Warning::Detail0NonZeroOffset => Some(TreeValue::SubObjects(SubObjectTreeValue::SubObject(model.header.detail_levels[0]))), } } @@ -1224,6 +1225,10 @@ impl PofToolsGui { dock_name ) } + Warning::Detail0NonZeroOffset => { + let id = self.model.header.detail_levels[0]; + format!("⚠ Detail0 object '{}' should have a (0, 0, 0) offset.", self.model.sub_objects[id].name) + } Warning::PathNameTooLong(_) | Warning::SubObjectNameTooLong(_) | Warning::SpecialPointNameTooLong(_) diff --git a/src/ui_properties_panel.rs b/src/ui_properties_panel.rs index ce3d96d..83ab4a9 100644 --- a/src/ui_properties_panel.rs +++ b/src/ui_properties_panel.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use egui::{style::Widgets, text::LayoutJob, CollapsingHeader, Color32, DragValue, Label, Response, RichText, TextEdit, TextFormat, TextStyle, Ui}; use glium::Display; -use itertools::Itertools; use nalgebra_glm::TMat4; use pof::{ Dock, Error, EyePoint, GlowPoint, GlowPointBank, Insignia, ObjectId, PathId, PathPoint, Set::*, SpecialPoint, SubsysRotationAxis, @@ -1302,7 +1301,14 @@ impl PofToolsGui { // Offset edit ================================================================ ui.horizontal_wrapped(|ui| { + if self.model.header.detail_levels.get(0).map_or(false, |id| selected_id == Some(*id)) + && self.model.warnings.contains(&Warning::Detail0NonZeroOffset) + { + ui.visuals_mut().override_text_color = Some(WARNING_YELLOW); + } ui.label("Offset:"); + ui.visuals_mut().override_text_color = None; + let response = ui.add_enabled(selected_id.is_some(), egui::Button::new("Recalculate")); if response.clicked() { @@ -1330,6 +1336,7 @@ impl PofToolsGui { self.model.sub_objects[id].offset = parsed_string; } self.ui_state.viewport_3d_dirty = true; + self.model.recheck_warnings(One(Warning::Detail0NonZeroOffset)); } } self.ui_state.display_origin |= response.hovered() || response.has_focus();