use crate::model::Unit;
use crate::utils::hardware::HardwareCapabilities;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ModelStats {
pub unit: Unit,
pub generator: Option<String>,
pub metadata: HashMap<String, String>,
pub geometry: GeometryStats,
pub materials: MaterialsStats,
pub production: ProductionStats,
pub displacement: DisplacementStats,
pub vendor: VendorData,
pub system_info: HardwareCapabilities,
pub thumbnails: ThumbnailStats,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ThumbnailStats {
pub package_thumbnail_present: bool,
pub object_thumbnail_count: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct MaterialsStats {
pub base_materials_count: usize,
pub color_groups_count: usize,
pub texture_2d_groups_count: usize,
pub composite_materials_count: usize,
pub multi_properties_count: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GeometryStats {
pub object_count: usize,
pub instance_count: usize,
pub triangle_count: u64,
pub vertex_count: u64,
pub bounding_box: Option<BoundingBox>,
pub surface_area: f64,
pub volume: f64,
pub is_manifold: bool,
#[serde(default)]
pub type_counts: HashMap<String, usize>,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub struct BoundingBox {
pub min: [f32; 3],
pub max: [f32; 3],
}
impl BoundingBox {
pub fn transform(&self, matrix: glam::Mat4) -> Self {
let corners = [
glam::Vec3::new(self.min[0], self.min[1], self.min[2]),
glam::Vec3::new(self.min[0], self.min[1], self.max[2]),
glam::Vec3::new(self.min[0], self.max[1], self.min[2]),
glam::Vec3::new(self.min[0], self.max[1], self.max[2]),
glam::Vec3::new(self.max[0], self.min[1], self.min[2]),
glam::Vec3::new(self.max[0], self.min[1], self.max[2]),
glam::Vec3::new(self.max[0], self.max[1], self.min[2]),
glam::Vec3::new(self.max[0], self.max[1], self.max[2]),
];
let mut transformed_min = glam::Vec3::splat(f32::INFINITY);
let mut transformed_max = glam::Vec3::splat(f32::NEG_INFINITY);
for corner in corners {
let transformed = matrix.transform_point3(corner);
transformed_min = transformed_min.min(transformed);
transformed_max = transformed_max.max(transformed);
}
Self {
min: [transformed_min.x, transformed_min.y, transformed_min.z],
max: [transformed_max.x, transformed_max.y, transformed_max.z],
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProductionStats {
pub uuid_count: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DisplacementStats {
pub mesh_count: usize,
pub texture_count: usize,
pub normal_count: u64,
pub gradient_count: u64,
pub displaced_triangle_count: u64,
pub total_triangle_count: u64,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct VendorData {
pub printer_model: Option<String>,
pub filaments: Vec<FilamentInfo>,
pub plates: Vec<PlateInfo>,
pub print_time_estimate: Option<String>,
pub slicer_version: Option<String>,
pub nozzle_diameter: Option<f32>,
pub slicer_warnings: Vec<SlicerWarning>,
pub object_metadata: Vec<BambuObjectMetadata>,
pub project_settings: Option<BambuProjectSettings>,
pub profile_configs: Vec<BambuProfileConfig>,
pub assembly_info: Vec<AssemblyItem>,
pub bambu_cover_thumbnail: Option<String>,
pub bambu_gcode: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct FilamentInfo {
pub id: u32,
pub tray_info_idx: Option<String>,
pub type_: String,
pub color: Option<String>,
pub used_m: Option<f32>,
pub used_g: Option<f32>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PlateInfo {
pub id: u32,
pub name: Option<String>,
pub locked: bool,
pub gcode_file: Option<String>,
pub thumbnail_file: Option<String>,
pub items: Vec<PlateModelInstance>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PlateModelInstance {
pub object_id: u32,
pub instance_id: u32,
pub identify_id: Option<u32>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SlicerWarning {
pub msg: String,
pub level: Option<String>,
pub error_code: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuObjectMetadata {
pub id: u32,
pub name: Option<String>,
pub extruder: Option<u32>,
pub face_count: Option<u64>,
pub parts: Vec<BambuPartMetadata>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuPartMetadata {
pub id: u32,
pub subtype: PartSubtype,
pub name: Option<String>,
pub matrix: Option<String>,
pub source: Option<BambuPartSource>,
pub mesh_stat: Option<BambuMeshStat>,
pub print_overrides: HashMap<String, String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub enum PartSubtype {
#[default]
NormalPart,
ModifierPart,
SupportBlocker,
SupportEnforcer,
Other(String),
}
impl PartSubtype {
pub fn parse(s: &str) -> Self {
match s {
"normal_part" => Self::NormalPart,
"modifier_part" => Self::ModifierPart,
"support_blocker" => Self::SupportBlocker,
"support_enforcer" => Self::SupportEnforcer,
other => Self::Other(other.to_string()),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuPartSource {
pub volume_id: Option<u32>,
pub offset_x: Option<f64>,
pub offset_y: Option<f64>,
pub offset_z: Option<f64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuMeshStat {
pub edges_fixed: Option<u32>,
pub degenerate_facets: Option<u32>,
pub facets_removed: Option<u32>,
pub facets_reversed: Option<u32>,
pub backwards_edges: Option<u32>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuProjectSettings {
pub printer_model: Option<String>,
pub printer_inherits: Option<String>,
pub bed_type: Option<String>,
pub layer_height: Option<f32>,
pub first_layer_height: Option<f32>,
pub filament_type: Vec<String>,
pub filament_colour: Vec<String>,
pub nozzle_diameter: Vec<f32>,
pub print_sequence: Option<String>,
pub wall_loops: Option<u32>,
pub infill_density: Option<String>,
pub support_type: Option<String>,
pub extras: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BambuProfileConfig {
pub config_type: String, pub index: u32, pub inherits: Option<String>,
pub name: Option<String>,
pub extras: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AssemblyItem {
pub object_id: u32,
pub instance_count: u32,
pub transform: Option<String>,
pub offset: Option<String>,
}