2721 lines
110 KiB
Rust
2721 lines
110 KiB
Rust
|
|
//! OCS-facing integration for non-graphical DWG object graphs.
|
|||
|
|
//!
|
|||
|
|
//! Dynamic-block evaluation records, solid construction history and
|
|||
|
|
//! associative networks do not draw standalone geometry. Their native place in
|
|||
|
|
//! OCS is the selected entity's semantic/property view, while the evaluated
|
|||
|
|
//! entity geometry continues through the normal render pipeline.
|
|||
|
|
|
|||
|
|
use acadrust::objects::{
|
|||
|
|
AssociativeData, BlockEvalValue, DynamicBlockData, ObjectType,
|
|||
|
|
SolidHistoryNodeBase, SolidHistoryOperation,
|
|||
|
|
};
|
|||
|
|
use acadrust::{CadDocument, EntityType, Handle};
|
|||
|
|
|
|||
|
|
use crate::scene::model::object::{PropSection, PropValue, Property};
|
|||
|
|
|
|||
|
|
#[derive(Debug, Clone, Default)]
|
|||
|
|
pub struct ObjectDataCache {
|
|||
|
|
document_sections: std::sync::Arc<Vec<PropSection>>,
|
|||
|
|
dynamic_objects: std::sync::Arc<Vec<Handle>>,
|
|||
|
|
associative_objects: std::sync::Arc<Vec<Handle>>,
|
|||
|
|
light_entities: std::sync::Arc<Vec<Handle>>,
|
|||
|
|
sun_objects: std::sync::Arc<Vec<Handle>>,
|
|||
|
|
geo_objects: std::sync::Arc<Vec<Handle>>,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn build_cache(document: &CadDocument) -> ObjectDataCache {
|
|||
|
|
let mut dynamic_objects = Vec::new();
|
|||
|
|
let mut associative_objects = Vec::new();
|
|||
|
|
let mut ordered_lights = Vec::new();
|
|||
|
|
let mut sun_objects = Vec::new();
|
|||
|
|
let mut geo_objects = Vec::new();
|
|||
|
|
for (handle, object) in &document.objects {
|
|||
|
|
match object {
|
|||
|
|
ObjectType::DynamicBlock(_) => dynamic_objects.push(*handle),
|
|||
|
|
ObjectType::Associative(_) => associative_objects.push(*handle),
|
|||
|
|
ObjectType::GeoData(_) => geo_objects.push(*handle),
|
|||
|
|
ObjectType::ClassObject(value) => match &value.data {
|
|||
|
|
acadrust::objects::ClassObjectData::LightList(list) => {
|
|||
|
|
ordered_lights.extend(list.lights.iter().map(|entry| entry.handle));
|
|||
|
|
}
|
|||
|
|
acadrust::objects::ClassObjectData::Sun(_) => sun_objects.push(*handle),
|
|||
|
|
_ => {}
|
|||
|
|
},
|
|||
|
|
_ => {}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let mut seen_lights = rustc_hash::FxHashSet::default();
|
|||
|
|
ordered_lights.retain(|handle| seen_lights.insert(*handle));
|
|||
|
|
for entity in document.entities() {
|
|||
|
|
if let EntityType::Light(light) = entity {
|
|||
|
|
if seen_lights.insert(light.common.handle) {
|
|||
|
|
ordered_lights.push(light.common.handle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
dynamic_objects.sort_by_key(|handle| handle.value());
|
|||
|
|
associative_objects.sort_by_key(|handle| handle.value());
|
|||
|
|
sun_objects.sort_by_key(|handle| handle.value());
|
|||
|
|
geo_objects.sort_by_key(|handle| handle.value());
|
|||
|
|
ObjectDataCache {
|
|||
|
|
document_sections: std::sync::Arc::new(build_document_sections(document)),
|
|||
|
|
dynamic_objects: std::sync::Arc::new(dynamic_objects),
|
|||
|
|
associative_objects: std::sync::Arc::new(associative_objects),
|
|||
|
|
light_entities: std::sync::Arc::new(ordered_lights),
|
|||
|
|
sun_objects: std::sync::Arc::new(sun_objects),
|
|||
|
|
geo_objects: std::sync::Arc::new(geo_objects),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn cache_is_prepared(cache: &ObjectDataCache) -> bool {
|
|||
|
|
!cache.document_sections.is_empty()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn light_entities(cache: &ObjectDataCache) -> &[Handle] {
|
|||
|
|
&cache.light_entities
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn sun_objects(cache: &ObjectDataCache) -> &[Handle] {
|
|||
|
|
&cache.sun_objects
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn geo_objects(cache: &ObjectDataCache) -> &[Handle] {
|
|||
|
|
&cache.geo_objects
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pub fn update_light_entity(
|
|||
|
|
cache: &mut ObjectDataCache,
|
|||
|
|
handle: Handle,
|
|||
|
|
exists: bool,
|
|||
|
|
) {
|
|||
|
|
let lights = std::sync::Arc::make_mut(&mut cache.light_entities);
|
|||
|
|
if exists {
|
|||
|
|
if !lights.contains(&handle) {
|
|||
|
|
lights.push(handle);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
lights.retain(|candidate| *candidate != handle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn ro(label: impl Into<String>, value: impl Into<String>) -> Property {
|
|||
|
|
Property {
|
|||
|
|
label: label.into(),
|
|||
|
|
field: "dwg_object_data",
|
|||
|
|
value: PropValue::ReadOnly(value.into()),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn handle_text(handle: Handle) -> String {
|
|||
|
|
if handle.is_valid() {
|
|||
|
|
format!("{:X}", handle.value())
|
|||
|
|
} else {
|
|||
|
|
"None".to_string()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn entity_history_handle(entity: &EntityType) -> Option<Handle> {
|
|||
|
|
match entity {
|
|||
|
|
EntityType::Solid3D(value) => value.history_handle,
|
|||
|
|
EntityType::Region(value) => value.history_handle,
|
|||
|
|
EntityType::Body(value) => value.history_handle,
|
|||
|
|
EntityType::Surface(value) => value.history_handle,
|
|||
|
|
_ => None,
|
|||
|
|
}
|
|||
|
|
.filter(|handle| handle.is_valid())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn history_operation_name(operation: &SolidHistoryOperation) -> &'static str {
|
|||
|
|
match operation {
|
|||
|
|
SolidHistoryOperation::Unknown => "Unknown",
|
|||
|
|
SolidHistoryOperation::Box(_) => "Box",
|
|||
|
|
SolidHistoryOperation::Wedge(_) => "Wedge",
|
|||
|
|
SolidHistoryOperation::Sphere(_) => "Sphere",
|
|||
|
|
SolidHistoryOperation::Cylinder(_) => "Cylinder",
|
|||
|
|
SolidHistoryOperation::Cone(_) => "Cone",
|
|||
|
|
SolidHistoryOperation::Pyramid(_) => "Pyramid",
|
|||
|
|
SolidHistoryOperation::Torus(_) => "Torus",
|
|||
|
|
SolidHistoryOperation::Boolean(_) => "Boolean",
|
|||
|
|
SolidHistoryOperation::Brep(_) => "Brep",
|
|||
|
|
SolidHistoryOperation::Fillet(_) => "Fillet",
|
|||
|
|
SolidHistoryOperation::Chamfer(_) => "Chamfer",
|
|||
|
|
SolidHistoryOperation::Sweep(_) => "Sweep",
|
|||
|
|
SolidHistoryOperation::Extrusion(_) => "Extrusion",
|
|||
|
|
SolidHistoryOperation::Loft(_) => "Loft",
|
|||
|
|
SolidHistoryOperation::Revolve(_) => "Revolve",
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn history_step_id(operation: &SolidHistoryOperation) -> Option<i32> {
|
|||
|
|
let base = match operation {
|
|||
|
|
SolidHistoryOperation::Unknown => return None,
|
|||
|
|
SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Sphere(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Cylinder(value) | SolidHistoryOperation::Cone(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Pyramid(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Torus(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Boolean(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Brep(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Fillet(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Chamfer(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Sweep(value) | SolidHistoryOperation::Extrusion(value) => {
|
|||
|
|
&value.base
|
|||
|
|
}
|
|||
|
|
SolidHistoryOperation::Loft(value) => &value.base,
|
|||
|
|
SolidHistoryOperation::Revolve(value) => &value.base,
|
|||
|
|
};
|
|||
|
|
Some(base.step_id)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn history_base_text(base: &SolidHistoryNodeBase) -> String {
|
|||
|
|
format!(
|
|||
|
|
"node {}; version {}.{}; material {}; color {:?}; transform [{:.4}, {:.4}, {:.4}, {:.4}; {:.4}, {:.4}, {:.4}, {:.4}; {:.4}, {:.4}, {:.4}, {:.4}; {:.4}, {:.4}, {:.4}, {:.4}]",
|
|||
|
|
base.eval.node_id,
|
|||
|
|
base.major,
|
|||
|
|
base.minor,
|
|||
|
|
handle_text(base.material),
|
|||
|
|
base.color,
|
|||
|
|
base.transform[0],
|
|||
|
|
base.transform[1],
|
|||
|
|
base.transform[2],
|
|||
|
|
base.transform[3],
|
|||
|
|
base.transform[4],
|
|||
|
|
base.transform[5],
|
|||
|
|
base.transform[6],
|
|||
|
|
base.transform[7],
|
|||
|
|
base.transform[8],
|
|||
|
|
base.transform[9],
|
|||
|
|
base.transform[10],
|
|||
|
|
base.transform[11],
|
|||
|
|
base.transform[12],
|
|||
|
|
base.transform[13],
|
|||
|
|
base.transform[14],
|
|||
|
|
base.transform[15],
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn embedded_name(value: Option<&acadrust::entities::EmbeddedEntity>) -> &'static str {
|
|||
|
|
match value {
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Point(_)) => "Point",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Line(_)) => "Line",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Arc(_)) => "Arc",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Circle(_)) => "Circle",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Ellipse(_)) => "Ellipse",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Spline(_)) => "Spline",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::LwPolyline(_)) => "Polyline",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Ray(_)) => "Ray",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::XLine(_)) => "XLine",
|
|||
|
|
Some(acadrust::entities::EmbeddedEntity::Unknown { .. }) => "Unknown",
|
|||
|
|
None => "None",
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn history_operation_text(operation: &SolidHistoryOperation) -> String {
|
|||
|
|
match operation {
|
|||
|
|
SolidHistoryOperation::Unknown => "Unknown operation".to_string(),
|
|||
|
|
SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) => format!(
|
|||
|
|
"{}; length {:.6}; width {:.6}; height {:.6}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.length,
|
|||
|
|
value.width,
|
|||
|
|
value.height
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Sphere(value) => format!(
|
|||
|
|
"{}; radius {:.6}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.radius
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Cylinder(value) | SolidHistoryOperation::Cone(value) => format!(
|
|||
|
|
"{}; height {:.6}; radii {:.6}/{:.6}; x-radius {:.6}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.height,
|
|||
|
|
value.major_radius,
|
|||
|
|
value.minor_radius,
|
|||
|
|
value.x_radius
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Pyramid(value) => format!(
|
|||
|
|
"{}; height {:.6}; sides {}; radii {:.6}/{:.6}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.height,
|
|||
|
|
value.sides,
|
|||
|
|
value.radius,
|
|||
|
|
value.top_radius
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Torus(value) => format!(
|
|||
|
|
"{}; radii {:.6}/{:.6}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.major_radius,
|
|||
|
|
value.minor_radius
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Boolean(value) => format!(
|
|||
|
|
"{}; operation {}; operands {}/{}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.operation,
|
|||
|
|
value.first_operand,
|
|||
|
|
value.second_operand
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Brep(value) => format!(
|
|||
|
|
"{}; ACIS {} bytes; materials {}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.acis_data.sat_data.len() + value.acis_data.sab_data.len(),
|
|||
|
|
value.acis_data.materials.len()
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Fillet(value) => format!(
|
|||
|
|
"{}; method {}; edges {}; radii {}; setbacks {}/{}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.method,
|
|||
|
|
value.edges.len(),
|
|||
|
|
value.radii.len(),
|
|||
|
|
value.start_setbacks.len(),
|
|||
|
|
value.end_setbacks.len()
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Chamfer(value) => format!(
|
|||
|
|
"{}; method {}; distances {:.6}/{:.6}; edges {}; base face {}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.method,
|
|||
|
|
value.base_distance,
|
|||
|
|
value.other_distance,
|
|||
|
|
value.edges.len(),
|
|||
|
|
value.base_face
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Sweep(value) | SolidHistoryOperation::Extrusion(value) => format!(
|
|||
|
|
"{}; sweep {}; path {}; direction {:.6},{:.6},{:.6}; draft {:.6}; scale {:.6}; twist {:.6}; align {:.6}; bank {}; intersections {}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
embedded_name(value.sweep_entity.as_ref()),
|
|||
|
|
embedded_name(value.path_entity.as_ref()),
|
|||
|
|
value.direction.x,
|
|||
|
|
value.direction.y,
|
|||
|
|
value.direction.z,
|
|||
|
|
value.draft_angle,
|
|||
|
|
value.scale_factor,
|
|||
|
|
value.twist_angle,
|
|||
|
|
value.align_angle,
|
|||
|
|
value.bank,
|
|||
|
|
value.check_intersections
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Loft(value) => format!(
|
|||
|
|
"{}; cross sections {}; guides {}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
value.cross_sections.len(),
|
|||
|
|
value.guides.len()
|
|||
|
|
),
|
|||
|
|
SolidHistoryOperation::Revolve(value) => format!(
|
|||
|
|
"{}; profile {}; axis point {:.6},{:.6},{:.6}; direction {:.6},{:.6}; angle {:.6}; start {:.6}; draft {:.6}; twist {:.6}; close-to-axis {}",
|
|||
|
|
history_base_text(&value.base),
|
|||
|
|
embedded_name(value.sweep_entity.as_ref()),
|
|||
|
|
value.axis_point.x,
|
|||
|
|
value.axis_point.y,
|
|||
|
|
value.axis_point.z,
|
|||
|
|
value.direction.x,
|
|||
|
|
value.direction.y,
|
|||
|
|
value.revolve_angle,
|
|||
|
|
value.start_angle,
|
|||
|
|
value.draft_angle,
|
|||
|
|
value.twist_angle,
|
|||
|
|
value.close_to_axis
|
|||
|
|
),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn solid_history_sections(
|
|||
|
|
document: &CadDocument,
|
|||
|
|
cache: &ObjectDataCache,
|
|||
|
|
entity: &EntityType,
|
|||
|
|
) -> Vec<PropSection> {
|
|||
|
|
let Some(history_handle) = entity_history_handle(entity) else {
|
|||
|
|
return Vec::new();
|
|||
|
|
};
|
|||
|
|
let Some(ObjectType::DynamicBlock(history_object)) =
|
|||
|
|
document.objects.get(&history_handle)
|
|||
|
|
else {
|
|||
|
|
return vec![PropSection {
|
|||
|
|
title: "Solid History".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Handle", handle_text(history_handle)),
|
|||
|
|
ro("Status", "Referenced history object is unresolved"),
|
|||
|
|
],
|
|||
|
|
}];
|
|||
|
|
};
|
|||
|
|
let DynamicBlockData::SolidHistory(history) = &history_object.data else {
|
|||
|
|
return vec![PropSection {
|
|||
|
|
title: "Solid History".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Handle", handle_text(history_handle)),
|
|||
|
|
ro("Status", "Referenced object is not a solid history"),
|
|||
|
|
],
|
|||
|
|
}];
|
|||
|
|
};
|
|||
|
|
let mut nodes = cache
|
|||
|
|
.dynamic_objects
|
|||
|
|
.iter()
|
|||
|
|
.filter_map(|handle| match document.objects.get(handle) {
|
|||
|
|
Some(ObjectType::DynamicBlock(value))
|
|||
|
|
if document.owner_chain_reaches(value.owner, history_handle) =>
|
|||
|
|
{
|
|||
|
|
match &value.data {
|
|||
|
|
DynamicBlockData::SolidHistoryNode(node) => Some(node),
|
|||
|
|
_ => None,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
_ => None,
|
|||
|
|
})
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
nodes.sort_by_key(|node| history_step_id(node).unwrap_or(i32::MAX));
|
|||
|
|
|
|||
|
|
let mut sections = vec![PropSection {
|
|||
|
|
title: "Solid History".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Handle", handle_text(history_handle)),
|
|||
|
|
ro("Version", format!("{}.{}", history.major, history.minor)),
|
|||
|
|
ro("Root node", history.history_node_id.to_string()),
|
|||
|
|
ro("Show history", history.show_history.to_string()),
|
|||
|
|
ro("Record history", history.record_history.to_string()),
|
|||
|
|
ro("Steps", nodes.len().to_string()),
|
|||
|
|
],
|
|||
|
|
}];
|
|||
|
|
if !nodes.is_empty() {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Construction Steps".to_string(),
|
|||
|
|
props: nodes
|
|||
|
|
.into_iter()
|
|||
|
|
.map(|node| {
|
|||
|
|
let step = history_step_id(node)
|
|||
|
|
.map(|value| value.to_string())
|
|||
|
|
.unwrap_or_else(|| "?".to_string());
|
|||
|
|
ro(
|
|||
|
|
format!("Step {step} · {}", history_operation_name(node)),
|
|||
|
|
history_operation_text(node),
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
.collect(),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
sections
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn block_value_text(value: &BlockEvalValue) -> String {
|
|||
|
|
match value {
|
|||
|
|
BlockEvalValue::None => "None".to_string(),
|
|||
|
|
BlockEvalValue::Real(value) => format!("{value:.6}"),
|
|||
|
|
BlockEvalValue::Point(value) => format!("{:.6}, {:.6}", value[0], value[1]),
|
|||
|
|
BlockEvalValue::Text(value) => value.clone(),
|
|||
|
|
BlockEvalValue::Long(value) => value.to_string(),
|
|||
|
|
BlockEvalValue::Handle(value) => handle_text(*value),
|
|||
|
|
BlockEvalValue::Short(value) => value.to_string(),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn dynamic_data_text(data: &DynamicBlockData) -> String {
|
|||
|
|
match data {
|
|||
|
|
DynamicBlockData::Unknown => "Unknown".to_string(),
|
|||
|
|
DynamicBlockData::Representation(value) => {
|
|||
|
|
format!("block {}; flags {}", handle_text(value.block), value.flags)
|
|||
|
|
}
|
|||
|
|
DynamicBlockData::ProxyNode(value) => format!(
|
|||
|
|
"node {}; parent {}; version {}.{}; value {}",
|
|||
|
|
value.node_id,
|
|||
|
|
value.parent_id,
|
|||
|
|
value.major,
|
|||
|
|
value.minor,
|
|||
|
|
block_value_text(&value.value)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::GripLocationComponent(value) => format!(
|
|||
|
|
"grip type {}; expression {}; value {}",
|
|||
|
|
value.grip_type,
|
|||
|
|
value.expression,
|
|||
|
|
block_value_text(&value.eval.value)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::AlignmentGrip(value) | DynamicBlockData::LinearGrip(value) => format!(
|
|||
|
|
"{} at {:.6},{:.6},{:.6}; orientation {:.6},{:.6},{:.6}; cycling {}",
|
|||
|
|
value.grip.element.name,
|
|||
|
|
value.grip.location.x,
|
|||
|
|
value.grip.location.y,
|
|||
|
|
value.grip.location.z,
|
|||
|
|
value.orientation.x,
|
|||
|
|
value.orientation.y,
|
|||
|
|
value.orientation.z,
|
|||
|
|
value.grip.insert_cycling
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::FlipGrip(value) => format!(
|
|||
|
|
"{} at {:.6},{:.6},{:.6}; state {}; orientation {:.6},{:.6},{:.6}",
|
|||
|
|
value.grip.element.name,
|
|||
|
|
value.grip.location.x,
|
|||
|
|
value.grip.location.y,
|
|||
|
|
value.grip.location.z,
|
|||
|
|
value.combined_state,
|
|||
|
|
value.orientation.x,
|
|||
|
|
value.orientation.y,
|
|||
|
|
value.orientation.z
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::LookupGrip(value)
|
|||
|
|
| DynamicBlockData::PolarGrip(value)
|
|||
|
|
| DynamicBlockData::RotationGrip(value)
|
|||
|
|
| DynamicBlockData::VisibilityGrip(value)
|
|||
|
|
| DynamicBlockData::XYGrip(value)
|
|||
|
|
| DynamicBlockData::PropertiesTableGrip(value) => format!(
|
|||
|
|
"{} at {:.6},{:.6},{:.6}; flags {}/{}; cycling {} weight {}",
|
|||
|
|
value.element.name,
|
|||
|
|
value.location.x,
|
|||
|
|
value.location.y,
|
|||
|
|
value.location.z,
|
|||
|
|
value.flags_91,
|
|||
|
|
value.flags_92,
|
|||
|
|
value.insert_cycling,
|
|||
|
|
value.insert_cycling_weight
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::AlignmentParameter(value) => format!(
|
|||
|
|
"{}; perpendicular {}; base {:.6},{:.6},{:.6}; end {:.6},{:.6},{:.6}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.align_perpendicular,
|
|||
|
|
value.parameter.definition_base_point.x,
|
|||
|
|
value.parameter.definition_base_point.y,
|
|||
|
|
value.parameter.definition_base_point.z,
|
|||
|
|
value.parameter.definition_end_point.x,
|
|||
|
|
value.parameter.definition_end_point.y,
|
|||
|
|
value.parameter.definition_end_point.z
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::BasePointParameter(value) => format!(
|
|||
|
|
"{}; point {:.6},{:.6},{:.6}; base {:.6},{:.6},{:.6}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.point.x,
|
|||
|
|
value.point.y,
|
|||
|
|
value.point.z,
|
|||
|
|
value.base_point.x,
|
|||
|
|
value.base_point.y,
|
|||
|
|
value.base_point.z
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::FlipParameter(value) => format!(
|
|||
|
|
"{}; labels {}/{}; tooltip {}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.base_state_label,
|
|||
|
|
value.flipped_state_label,
|
|||
|
|
value.tooltip
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::LinearParameter(value) => format!(
|
|||
|
|
"{}; {} = {:.6}; range {:.6}..{:.6}; increment {:.6}; values {}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.distance_name,
|
|||
|
|
value.distance,
|
|||
|
|
value.value_set.minimum,
|
|||
|
|
value.value_set.maximum,
|
|||
|
|
value.value_set.increment,
|
|||
|
|
value.value_set.values.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::LookupParameter(value) => format!(
|
|||
|
|
"{}; {} index {}; description {}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.lookup_name,
|
|||
|
|
value.index,
|
|||
|
|
value.lookup_description
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::PointParameter(value) => format!(
|
|||
|
|
"{}; {}; label at {:.6},{:.6},{:.6}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.position_name,
|
|||
|
|
value.definition_label_point.x,
|
|||
|
|
value.definition_label_point.y,
|
|||
|
|
value.definition_label_point.z
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::PolarParameter(value) => format!(
|
|||
|
|
"{}; angle {}; distance {}; offset {:.6}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.angle_name,
|
|||
|
|
value.distance_name,
|
|||
|
|
value.offset
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::RotationParameter(value) => format!(
|
|||
|
|
"{}; {} = {:.6}; range {:.6}..{:.6}; values {}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.angle_name,
|
|||
|
|
value.angle,
|
|||
|
|
value.value_set.minimum,
|
|||
|
|
value.value_set.maximum,
|
|||
|
|
value.value_set.values.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::UserParameter(value) => format!(
|
|||
|
|
"{}; expression {}; value {}; variable {}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.expression,
|
|||
|
|
block_value_text(&value.value),
|
|||
|
|
handle_text(value.associated_variable)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::VisibilityParameter(value) => format!(
|
|||
|
|
"{}; states {}; members {}; point {:.6},{:.6},{:.6}",
|
|||
|
|
value.name,
|
|||
|
|
value.states.len(),
|
|||
|
|
value.all_blocks.len(),
|
|||
|
|
value.def_point.x,
|
|||
|
|
value.def_point.y,
|
|||
|
|
value.def_point.z
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::XYParameter(value) => format!(
|
|||
|
|
"{}; {} = {:.6}; {} = {:.6}",
|
|||
|
|
value.parameter.parameter.element.name,
|
|||
|
|
value.x_label,
|
|||
|
|
value.x_value,
|
|||
|
|
value.y_label,
|
|||
|
|
value.y_value
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::AngularConstraintParameter(value) => format!(
|
|||
|
|
"{} = {:.6}; dependency {}",
|
|||
|
|
value.expression_name,
|
|||
|
|
value.angle,
|
|||
|
|
handle_text(value.constraint.dependency)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::DiametricConstraintParameter(value)
|
|||
|
|
| DynamicBlockData::RadialConstraintParameter(value) => format!(
|
|||
|
|
"{} = {:.6}; dependency {}",
|
|||
|
|
value.expression_name,
|
|||
|
|
value.distance,
|
|||
|
|
handle_text(value.constraint.dependency)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::AlignedConstraintParameter(value)
|
|||
|
|
| DynamicBlockData::LinearConstraintParameter(value)
|
|||
|
|
| DynamicBlockData::HorizontalConstraintParameter(value)
|
|||
|
|
| DynamicBlockData::VerticalConstraintParameter(value) => format!(
|
|||
|
|
"{} = {:.6}; dependency {}",
|
|||
|
|
value.expression_name,
|
|||
|
|
value.value,
|
|||
|
|
handle_text(value.constraint.dependency)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::ParameterDependencyBody(value) => format!(
|
|||
|
|
"{}; dependency version {}; dimension version {}; class version {}",
|
|||
|
|
value.name,
|
|||
|
|
value.dependency_body_version,
|
|||
|
|
value.dimension_base_version,
|
|||
|
|
value.class_version
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::MoveAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; actions {}; offsets {:.6},{:.6}; angle {:.6}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.action.action_ids.len(),
|
|||
|
|
value.offsets.offset_x,
|
|||
|
|
value.offsets.offset_y,
|
|||
|
|
value.offsets.angle_offset
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::FlipAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; actions {}; connections {}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.action.action_ids.len(),
|
|||
|
|
value.connections.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::RotateAction(value) | DynamicBlockData::ScaleAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; actions {}; base {:.6},{:.6},{:.6}; dependent {}",
|
|||
|
|
value.action.action.element.name,
|
|||
|
|
value.action.action.dependencies.len(),
|
|||
|
|
value.action.action.action_ids.len(),
|
|||
|
|
value.action.base_point.x,
|
|||
|
|
value.action.base_point.y,
|
|||
|
|
value.action.base_point.z,
|
|||
|
|
value.action.dependent
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::ArrayAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; columns offset {:.6}; rows offset {:.6}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.column_offset,
|
|||
|
|
value.row_offset
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::LookupAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; table {}×{}; expressions {}; rows {}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.row_count,
|
|||
|
|
value.column_count,
|
|||
|
|
value.expressions.len(),
|
|||
|
|
value.rows.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::StretchAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; points {}; handles {}; codes {}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.points.len(),
|
|||
|
|
value.handles.len(),
|
|||
|
|
value.codes.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::PolarStretchAction(value) => format!(
|
|||
|
|
"{}; dependencies {}; points {}; handles {}; codes {}",
|
|||
|
|
value.action.element.name,
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.points.len(),
|
|||
|
|
value.handles.len(),
|
|||
|
|
value.codes.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::EvaluationGraph(value) => format!(
|
|||
|
|
"first node {}; nodes {}; edges {}",
|
|||
|
|
value.first_node_id,
|
|||
|
|
value.nodes.len(),
|
|||
|
|
value.edges.len()
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::AngularConstraintParameterEntity(value) => format!(
|
|||
|
|
"{} = {:.6}; dependency {}",
|
|||
|
|
value.expression_name,
|
|||
|
|
value.angle,
|
|||
|
|
handle_text(value.constraint.dependency)
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::SolidHistory(value) => format!(
|
|||
|
|
"version {}.{}; root {}; show {}; record {}",
|
|||
|
|
value.major,
|
|||
|
|
value.minor,
|
|||
|
|
value.history_node_id,
|
|||
|
|
value.show_history,
|
|||
|
|
value.record_history
|
|||
|
|
),
|
|||
|
|
DynamicBlockData::SolidHistoryNode(value) => history_operation_text(value),
|
|||
|
|
DynamicBlockData::PropertiesTable
|
|||
|
|
| DynamicBlockData::AlignmentParameterEntity
|
|||
|
|
| DynamicBlockData::BasePointParameterEntity
|
|||
|
|
| DynamicBlockData::FlipParameterEntity
|
|||
|
|
| DynamicBlockData::LinearParameterEntity
|
|||
|
|
| DynamicBlockData::PointParameterEntity
|
|||
|
|
| DynamicBlockData::RotationParameterEntity
|
|||
|
|
| DynamicBlockData::VisibilityParameterEntity
|
|||
|
|
| DynamicBlockData::XYParameterEntity
|
|||
|
|
| DynamicBlockData::FlipGripEntity
|
|||
|
|
| DynamicBlockData::LinearGripEntity
|
|||
|
|
| DynamicBlockData::PolarGripEntity
|
|||
|
|
| DynamicBlockData::RotationGripEntity
|
|||
|
|
| DynamicBlockData::VisibilityGripEntity
|
|||
|
|
| DynamicBlockData::XYGripEntity => "Semantic entity marker".to_string(),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn dynamic_block_sections(
|
|||
|
|
document: &CadDocument,
|
|||
|
|
cache: &ObjectDataCache,
|
|||
|
|
handle: Handle,
|
|||
|
|
) -> Vec<PropSection> {
|
|||
|
|
let Some(definition) = document.dynamic_definition_for_insert(handle) else {
|
|||
|
|
return Vec::new();
|
|||
|
|
};
|
|||
|
|
let mut objects = cache
|
|||
|
|
.dynamic_objects
|
|||
|
|
.iter()
|
|||
|
|
.filter_map(|object_handle| match document.objects.get(object_handle) {
|
|||
|
|
Some(ObjectType::DynamicBlock(value))
|
|||
|
|
if document.owner_chain_reaches(value.owner, definition) =>
|
|||
|
|
{
|
|||
|
|
Some(value)
|
|||
|
|
}
|
|||
|
|
_ => None,
|
|||
|
|
})
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
let visibility = document.block_visibility_param_for_def(definition);
|
|||
|
|
if objects.is_empty() && visibility.is_none() {
|
|||
|
|
return Vec::new();
|
|||
|
|
}
|
|||
|
|
objects.sort_by_key(|object| object.handle.value());
|
|||
|
|
|
|||
|
|
let mut overview = vec![
|
|||
|
|
ro("Definition", handle_text(definition)),
|
|||
|
|
ro("Native records", objects.len().to_string()),
|
|||
|
|
];
|
|||
|
|
if let Some(parameter) = visibility {
|
|||
|
|
overview.push(ro("Visibility", parameter.name.clone()));
|
|||
|
|
overview.push(ro(
|
|||
|
|
"Visibility states",
|
|||
|
|
parameter
|
|||
|
|
.states
|
|||
|
|
.iter()
|
|||
|
|
.map(|state| state.name.as_str())
|
|||
|
|
.collect::<Vec<_>>()
|
|||
|
|
.join(", "),
|
|||
|
|
));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let mut sections = vec![PropSection {
|
|||
|
|
title: "Dynamic Block".to_string(),
|
|||
|
|
props: overview,
|
|||
|
|
}];
|
|||
|
|
if !objects.is_empty() {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Dynamic Parameters / Actions".to_string(),
|
|||
|
|
props: objects
|
|||
|
|
.into_iter()
|
|||
|
|
.filter(|object| {
|
|||
|
|
!matches!(
|
|||
|
|
object.data,
|
|||
|
|
DynamicBlockData::SolidHistory(_)
|
|||
|
|
| DynamicBlockData::SolidHistoryNode(_)
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
.map(|object| {
|
|||
|
|
let class = if object.dxf_name.is_empty() {
|
|||
|
|
object.cpp_class_name.as_str()
|
|||
|
|
} else {
|
|||
|
|
object.dxf_name.as_str()
|
|||
|
|
};
|
|||
|
|
ro(
|
|||
|
|
format!("{} · {}", handle_text(object.handle), class),
|
|||
|
|
dynamic_data_text(&object.data),
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
.collect(),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
sections
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn associative_data_text(data: &AssociativeData) -> String {
|
|||
|
|
match data {
|
|||
|
|
AssociativeData::Unknown => "Unknown".to_string(),
|
|||
|
|
AssociativeData::Dependency(value) => format!(
|
|||
|
|
"status {}; read {}; write {}; attached {}; target {}; body {}",
|
|||
|
|
value.status,
|
|||
|
|
value.is_read_dependency,
|
|||
|
|
value.is_write_dependency,
|
|||
|
|
value.is_attached_to_object,
|
|||
|
|
handle_text(value.dependent_on),
|
|||
|
|
handle_text(value.dependency_body)
|
|||
|
|
),
|
|||
|
|
AssociativeData::ValueDependency(value) => format!(
|
|||
|
|
"{}; target {}; value {:?}",
|
|||
|
|
value.name,
|
|||
|
|
handle_text(value.dependency.dependent_on),
|
|||
|
|
value.value.value
|
|||
|
|
),
|
|||
|
|
AssociativeData::GeomDependency(value) => format!(
|
|||
|
|
"target {}; enabled {}; subentity {}",
|
|||
|
|
handle_text(value.dependency.dependent_on),
|
|||
|
|
value.enabled,
|
|||
|
|
value.persistent_subent.class_name
|
|||
|
|
),
|
|||
|
|
AssociativeData::Action(value) => format!(
|
|||
|
|
"status {}; network {}; body {}; dependencies {}; parameters {}; values {}",
|
|||
|
|
value.geometry_status,
|
|||
|
|
handle_text(value.owning_network),
|
|||
|
|
handle_text(value.action_body),
|
|||
|
|
value.dependencies.len(),
|
|||
|
|
value.owned_parameters.len(),
|
|||
|
|
value.values.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::Network(value) => format!(
|
|||
|
|
"actions {}; owned {}; dependencies {}; values {}",
|
|||
|
|
value.actions.len(),
|
|||
|
|
value.owned_actions.len(),
|
|||
|
|
value.action.dependencies.len(),
|
|||
|
|
value.action.values.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::ConstraintGroup(value) => format!(
|
|||
|
|
"status {}; dependency {}; actions {}; nodes {}",
|
|||
|
|
value.action.geometry_status,
|
|||
|
|
handle_text(value.dependency),
|
|||
|
|
value.actions.len(),
|
|||
|
|
value.nodes.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::Variable(value) => format!(
|
|||
|
|
"{} = {:?}; expression {}; evaluator {}; values {}",
|
|||
|
|
value.name,
|
|||
|
|
value.value.value,
|
|||
|
|
value.expression,
|
|||
|
|
value.evaluator,
|
|||
|
|
value.action.values.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::ArrayParameters(value) => format!(
|
|||
|
|
"{}; items {}; rows {}; levels {}",
|
|||
|
|
value.class_name,
|
|||
|
|
value.items.len(),
|
|||
|
|
value.row_count,
|
|||
|
|
value.level_count
|
|||
|
|
),
|
|||
|
|
AssociativeData::ArrayActionBody(value) => format!(
|
|||
|
|
"parameter block {}; dependencies {}; value parameters {}",
|
|||
|
|
value.parameter_block,
|
|||
|
|
value.parameter_body.dependencies.len(),
|
|||
|
|
value.parameter_body.values.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::ArrayModifyActionBody(value) => format!(
|
|||
|
|
"items {}; dependencies {}; value parameters {}",
|
|||
|
|
value.item_locations.len(),
|
|||
|
|
value.body.parameter_body.dependencies.len(),
|
|||
|
|
value.body.parameter_body.values.len()
|
|||
|
|
),
|
|||
|
|
AssociativeData::DimensionAssociation(value) => format!(
|
|||
|
|
"dimension {}; associativity {}; references {}",
|
|||
|
|
handle_text(value.dimension),
|
|||
|
|
value.associativity,
|
|||
|
|
value.references.iter().flatten().count()
|
|||
|
|
),
|
|||
|
|
other => format!("{} semantic payload", associative_data_name(other)),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn associative_data_name(data: &AssociativeData) -> &'static str {
|
|||
|
|
match data {
|
|||
|
|
AssociativeData::Unknown => "Unknown",
|
|||
|
|
AssociativeData::Dependency(_) => "Dependency",
|
|||
|
|
AssociativeData::ValueDependency(_) => "Value Dependency",
|
|||
|
|
AssociativeData::GeomDependency(_) => "Geometry Dependency",
|
|||
|
|
AssociativeData::SurfaceActionBody(_) => "Surface Action",
|
|||
|
|
AssociativeData::Action(_) => "Action",
|
|||
|
|
AssociativeData::Network(_) => "Network",
|
|||
|
|
AssociativeData::AnnotationActionBody(_) => "Annotation Action",
|
|||
|
|
AssociativeData::PersSubentManager(_) => "Persistent Subentity Manager",
|
|||
|
|
AssociativeData::EdgeActionParam(_) => "Edge Parameter",
|
|||
|
|
AssociativeData::ConstraintGroup(_) => "Constraint Group",
|
|||
|
|
AssociativeData::Variable(_) => "Variable",
|
|||
|
|
AssociativeData::ActionParam(_) => "Action Parameter",
|
|||
|
|
AssociativeData::CompoundActionParam(_) => "Compound Parameter",
|
|||
|
|
AssociativeData::OsnapPointRefActionParam(_) => "Object Snap Parameter",
|
|||
|
|
AssociativeData::PointRefActionParam(_) => "Point Reference",
|
|||
|
|
AssociativeData::ObjectActionParam(_) => "Object Parameter",
|
|||
|
|
AssociativeData::PathActionParam(_) => "Path Parameter",
|
|||
|
|
AssociativeData::DimDependencyBody(_) => "Dimension Dependency",
|
|||
|
|
AssociativeData::FaceActionParam(_) => "Face Parameter",
|
|||
|
|
AssociativeData::VertexActionParam(_) => "Vertex Parameter",
|
|||
|
|
AssociativeData::AsmBodyActionParam(_) => "ASM Body Parameter",
|
|||
|
|
AssociativeData::ArrayParameters(_) => "Array Parameters",
|
|||
|
|
AssociativeData::ArrayActionBody(_) => "Array Action",
|
|||
|
|
AssociativeData::ArrayModifyActionBody(_) => "Array Modify Action",
|
|||
|
|
AssociativeData::DimensionAssociation(_) => "Dimension Association",
|
|||
|
|
AssociativeData::PersSubentManagerStatic(_) => "Static Subentity Manager",
|
|||
|
|
AssociativeData::ViewRepActionBody(_) => "View Representation Action",
|
|||
|
|
AssociativeData::ViewObjectActionParam(_) => "View Object Parameter",
|
|||
|
|
AssociativeData::ViewRepHatchManager(_) => "View Hatch Manager",
|
|||
|
|
AssociativeData::ViewRepHatchActionParam(_) => "View Hatch Parameter",
|
|||
|
|
AssociativeData::ViewLabelActionParam(_) => "View Label Parameter",
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn associative_sections(
|
|||
|
|
document: &CadDocument,
|
|||
|
|
cache: &ObjectDataCache,
|
|||
|
|
handle: Handle,
|
|||
|
|
) -> Vec<PropSection> {
|
|||
|
|
let mut objects = cache
|
|||
|
|
.associative_objects
|
|||
|
|
.iter()
|
|||
|
|
.filter_map(|object_handle| match document.objects.get(object_handle) {
|
|||
|
|
Some(ObjectType::Associative(value))
|
|||
|
|
if document.owner_chain_reaches(value.owner, handle)
|
|||
|
|
|| value.references_handle(handle) =>
|
|||
|
|
{
|
|||
|
|
Some(value)
|
|||
|
|
}
|
|||
|
|
_ => None,
|
|||
|
|
})
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
if objects.is_empty() {
|
|||
|
|
return Vec::new();
|
|||
|
|
}
|
|||
|
|
objects.sort_by_key(|object| object.handle.value());
|
|||
|
|
vec![PropSection {
|
|||
|
|
title: "Associative Data".to_string(),
|
|||
|
|
props: objects
|
|||
|
|
.into_iter()
|
|||
|
|
.map(|object| {
|
|||
|
|
let class = if object.dxf_name.is_empty() {
|
|||
|
|
object.cpp_class_name.as_str()
|
|||
|
|
} else {
|
|||
|
|
object.dxf_name.as_str()
|
|||
|
|
};
|
|||
|
|
ro(
|
|||
|
|
format!("{} · {}", handle_text(object.handle), class),
|
|||
|
|
associative_data_text(&object.data),
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
.collect(),
|
|||
|
|
}]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Semantic DWG object sections connected to one selected entity.
|
|||
|
|
pub fn sections(
|
|||
|
|
document: &CadDocument,
|
|||
|
|
cache: &ObjectDataCache,
|
|||
|
|
handle: Handle,
|
|||
|
|
entity: &EntityType,
|
|||
|
|
) -> Vec<PropSection> {
|
|||
|
|
let mut sections = solid_history_sections(document, cache, entity);
|
|||
|
|
if matches!(entity, EntityType::Insert(_)) {
|
|||
|
|
sections.extend(dynamic_block_sections(document, cache, handle));
|
|||
|
|
}
|
|||
|
|
if let EntityType::Table(table) = entity {
|
|||
|
|
let mut linked = rustc_hash::FxHashSet::default();
|
|||
|
|
for row in &table.rows {
|
|||
|
|
for cell in &row.cells {
|
|||
|
|
if let Some(link_handle) = cell.data_link_handle {
|
|||
|
|
if linked.insert(link_handle) {
|
|||
|
|
if let Some(ObjectType::ClassObject(object)) =
|
|||
|
|
document.objects.get(&link_handle)
|
|||
|
|
{
|
|||
|
|
if let Some(section) = class_object_section(&object.data) {
|
|||
|
|
sections.push(section);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sections.extend(associative_sections(document, cache, handle));
|
|||
|
|
|
|||
|
|
// A directly attached typed object can still be useful when its semantic
|
|||
|
|
// graph contains no backlink (for example a sparse extension dictionary).
|
|||
|
|
if sections.is_empty() {
|
|||
|
|
if let Some(ObjectType::DynamicBlock(object)) = document.objects.get(&handle) {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Dynamic Object".to_string(),
|
|||
|
|
props: vec![ro("Decoded data", dynamic_data_text(&object.data))],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sections
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn preview_text(value: &str, limit: usize) -> String {
|
|||
|
|
if value.chars().count() <= limit {
|
|||
|
|
return value.to_string();
|
|||
|
|
}
|
|||
|
|
let mut preview: String = value.chars().take(limit).collect();
|
|||
|
|
preview.push_str(&format!("… ({} chars)", value.chars().count()));
|
|||
|
|
preview
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn bounded_join<I>(values: I, limit: usize) -> String
|
|||
|
|
where
|
|||
|
|
I: IntoIterator<Item = String>,
|
|||
|
|
{
|
|||
|
|
let mut values = values.into_iter();
|
|||
|
|
let mut visible = Vec::new();
|
|||
|
|
for _ in 0..limit {
|
|||
|
|
let Some(value) = values.next() else {
|
|||
|
|
break;
|
|||
|
|
};
|
|||
|
|
visible.push(value);
|
|||
|
|
}
|
|||
|
|
let hidden = values.count();
|
|||
|
|
let mut result = visible.join("; ");
|
|||
|
|
if hidden != 0 {
|
|||
|
|
result.push_str(&format!("; … +{hidden}"));
|
|||
|
|
}
|
|||
|
|
result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn class_object_section(
|
|||
|
|
data: &acadrust::objects::ClassObjectData,
|
|||
|
|
) -> Option<PropSection> {
|
|||
|
|
use acadrust::objects::ClassObjectData;
|
|||
|
|
|
|||
|
|
let section = match data {
|
|||
|
|
ClassObjectData::Empty => return None,
|
|||
|
|
ClassObjectData::SpatialIndex(value) => PropSection {
|
|||
|
|
title: "Spatial Index".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Updated",
|
|||
|
|
format!(
|
|||
|
|
"Julian {}; {} ms",
|
|||
|
|
value.last_updated_julian_day,
|
|||
|
|
value.last_updated_milliseconds
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Extents",
|
|||
|
|
format!(
|
|||
|
|
"{:.6},{:.6},{:.6} → {:.6},{:.6},{:.6}",
|
|||
|
|
value.min_corner.x,
|
|||
|
|
value.min_corner.y,
|
|||
|
|
value.min_corner.z,
|
|||
|
|
value.max_corner.x,
|
|||
|
|
value.max_corner.y,
|
|||
|
|
value.max_corner.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro("Indexed Objects", value.indexed_objects.len().to_string()),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::LayerFilter(value) => PropSection {
|
|||
|
|
title: "Layer Filter".to_string(),
|
|||
|
|
props: vec![ro("Names", bounded_join(value.names.iter().cloned(), 64))],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PartialViewingIndex(value) => PropSection {
|
|||
|
|
title: "Partial Viewing Index".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Has Entries", value.has_entries.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Entries",
|
|||
|
|
bounded_join(
|
|||
|
|
value.entries.iter().map(|entry| {
|
|||
|
|
format!(
|
|||
|
|
"{}: {:.4},{:.4},{:.4} → {:.4},{:.4},{:.4}",
|
|||
|
|
handle_text(entry.object),
|
|||
|
|
entry.extents_min.x,
|
|||
|
|
entry.extents_min.y,
|
|||
|
|
entry.extents_min.z,
|
|||
|
|
entry.extents_max.x,
|
|||
|
|
entry.extents_max.y,
|
|||
|
|
entry.extents_max.z
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
32,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::VbaProject(value) => PropSection {
|
|||
|
|
title: "VBA Project".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Detached Records",
|
|||
|
|
format!(
|
|||
|
|
"{} leading / {} bytes; {} trailing / {} bytes",
|
|||
|
|
value.storage.leading_records.len(),
|
|||
|
|
value
|
|||
|
|
.storage
|
|||
|
|
.leading_records
|
|||
|
|
.iter()
|
|||
|
|
.map(|record| record.data.len())
|
|||
|
|
.sum::<usize>(),
|
|||
|
|
value.storage.trailing_records.len(),
|
|||
|
|
value
|
|||
|
|
.storage
|
|||
|
|
.trailing_records
|
|||
|
|
.iter()
|
|||
|
|
.map(|record| record.data.len())
|
|||
|
|
.sum::<usize>()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Streams",
|
|||
|
|
value
|
|||
|
|
.storage
|
|||
|
|
.compound_file
|
|||
|
|
.as_ref()
|
|||
|
|
.map(|storage| storage.root.entries.len())
|
|||
|
|
.unwrap_or_default()
|
|||
|
|
.to_string(),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SectionManager(value) => PropSection {
|
|||
|
|
title: "Section Manager".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Live", value.is_live.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Sections",
|
|||
|
|
bounded_join(
|
|||
|
|
value.sections.iter().map(|handle| handle_text(*handle)),
|
|||
|
|
64,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SectionSettings(value) => PropSection {
|
|||
|
|
title: "Section Settings".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Current Type", value.current_type.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Types",
|
|||
|
|
bounded_join(
|
|||
|
|
value.types.iter().map(|setting| {
|
|||
|
|
let geometry = bounded_join(
|
|||
|
|
setting.geometry.iter().map(|geometry| {
|
|||
|
|
format!(
|
|||
|
|
"#{} flags {} layer '{}' linetype '{}' scale {:.4} weight {} transparency {}/{} hatch {} '{}' angle {:.4} spacing {:.4} scale {:.4} color {:?}",
|
|||
|
|
geometry.index,
|
|||
|
|
geometry.flags,
|
|||
|
|
geometry.layer,
|
|||
|
|
geometry.linetype,
|
|||
|
|
geometry.linetype_scale,
|
|||
|
|
geometry.lineweight,
|
|||
|
|
geometry.face_transparency,
|
|||
|
|
geometry.edge_transparency,
|
|||
|
|
geometry.hatch_type,
|
|||
|
|
geometry.hatch_pattern,
|
|||
|
|
geometry.hatch_angle,
|
|||
|
|
geometry.hatch_spacing,
|
|||
|
|
geometry.hatch_scale,
|
|||
|
|
geometry.color
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
16,
|
|||
|
|
);
|
|||
|
|
format!(
|
|||
|
|
"type {} generation {} sources [{}] destination {} file '{}' geometry {} [{}]",
|
|||
|
|
setting.section_type,
|
|||
|
|
setting.generation,
|
|||
|
|
bounded_join(
|
|||
|
|
setting.sources.iter().map(|handle| handle_text(*handle)),
|
|||
|
|
32
|
|||
|
|
),
|
|||
|
|
handle_text(setting.destination_block),
|
|||
|
|
setting.destination_file,
|
|||
|
|
setting.geometry.len(),
|
|||
|
|
geometry
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
16,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::GradientBackground(value) => PropSection {
|
|||
|
|
title: "Gradient Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Colors",
|
|||
|
|
format!(
|
|||
|
|
"#{:06X} / #{:06X} / #{:06X}",
|
|||
|
|
value.color_top & 0x00FF_FFFF,
|
|||
|
|
value.color_middle & 0x00FF_FFFF,
|
|||
|
|
value.color_bottom & 0x00FF_FFFF
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Geometry",
|
|||
|
|
format!(
|
|||
|
|
"horizon {:.6}; height {:.6}; rotation {:.6}",
|
|||
|
|
value.horizon, value.height, value.rotation
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::GroundPlaneBackground(value) => PropSection {
|
|||
|
|
title: "Ground Plane Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Colors",
|
|||
|
|
format!(
|
|||
|
|
"sky #{:06X}/#{:06X}; underground #{:06X}/#{:06X}; near/far #{:06X}/#{:06X}",
|
|||
|
|
value.color_sky_zenith & 0x00FF_FFFF,
|
|||
|
|
value.color_sky_horizon & 0x00FF_FFFF,
|
|||
|
|
value.color_underground_horizon & 0x00FF_FFFF,
|
|||
|
|
value.color_underground_azimuth & 0x00FF_FFFF,
|
|||
|
|
value.color_near & 0x00FF_FFFF,
|
|||
|
|
value.color_far & 0x00FF_FFFF
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::IblBackground(value) => PropSection {
|
|||
|
|
title: "Image Based Lighting Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("Enabled", value.enabled.to_string()),
|
|||
|
|
ro("Name", value.name.clone()),
|
|||
|
|
ro("Rotation", format!("{:.6}", value.rotation)),
|
|||
|
|
ro("Display Image", value.display_image.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Secondary Background",
|
|||
|
|
handle_text(value.secondary_background),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ImageBackground(value) => PropSection {
|
|||
|
|
title: "Image Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("File", value.filename.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Display",
|
|||
|
|
format!(
|
|||
|
|
"fit {}; aspect {}; tile {}",
|
|||
|
|
value.fit_to_screen,
|
|||
|
|
value.maintain_aspect_ratio,
|
|||
|
|
value.use_tiling
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Offset / Scale",
|
|||
|
|
format!(
|
|||
|
|
"{:.6},{:.6} / {:.6},{:.6}",
|
|||
|
|
value.offset.x, value.offset.y, value.scale.x, value.scale.y
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SkyLightBackground(value) => PropSection {
|
|||
|
|
title: "Sky Light Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("Sun", handle_text(value.sun)),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SolidBackground(value) => PropSection {
|
|||
|
|
title: "Solid Background".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("Color", format!("#{:06X}", value.color & 0x00FF_FFFF)),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::RenderEntry(value) => PropSection {
|
|||
|
|
title: "Render History Entry".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Image", value.image_filename.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Preset / View",
|
|||
|
|
format!("{} / {}", value.preset_name, value.view_name),
|
|||
|
|
),
|
|||
|
|
ro("Size", format!("{}×{}", value.width, value.height)),
|
|||
|
|
ro(
|
|||
|
|
"Started",
|
|||
|
|
format!(
|
|||
|
|
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
|
|||
|
|
value.start_year,
|
|||
|
|
value.start_month,
|
|||
|
|
value.start_day,
|
|||
|
|
value.start_hour,
|
|||
|
|
value.start_minute,
|
|||
|
|
value.start_second,
|
|||
|
|
value.start_millisecond
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Finished",
|
|||
|
|
format!(
|
|||
|
|
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
|
|||
|
|
value.end_year,
|
|||
|
|
value.end_month,
|
|||
|
|
value.end_day,
|
|||
|
|
value.end_hour,
|
|||
|
|
value.end_minute,
|
|||
|
|
value.end_second,
|
|||
|
|
value.end_millisecond
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Statistics",
|
|||
|
|
format!(
|
|||
|
|
"{:.4}s; {} memory; {} materials; {} lights; {} triangles; index {}",
|
|||
|
|
value.render_time,
|
|||
|
|
value.memory_amount,
|
|||
|
|
value.material_count,
|
|||
|
|
value.light_count,
|
|||
|
|
value.triangle_count,
|
|||
|
|
value.display_index
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::MotionPath(value) => PropSection {
|
|||
|
|
title: "Motion Path".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Camera / Target / View",
|
|||
|
|
format!(
|
|||
|
|
"{} / {} / {}",
|
|||
|
|
handle_text(value.camera_path),
|
|||
|
|
handle_text(value.target_path),
|
|||
|
|
handle_text(value.view)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Playback",
|
|||
|
|
format!(
|
|||
|
|
"{} frames at {} fps; corner deceleration {}",
|
|||
|
|
value.frames, value.frame_rate, value.corner_deceleration
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::CurvePath(value) => PropSection {
|
|||
|
|
title: "Curve Path".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("Entity", handle_text(value.entity)),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PointPath(value) => PropSection {
|
|||
|
|
title: "Point Path".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Point",
|
|||
|
|
format!("{:.8}, {:.8}, {:.8}", value.point.x, value.point.y, value.point.z),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::TvDeviceProperties(value) => PropSection {
|
|||
|
|
title: "Graphics Device Properties".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Flags", value.flags.to_string()),
|
|||
|
|
ro("Max Regen Threads", value.max_regen_threads.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Palette / Highlight",
|
|||
|
|
format!(
|
|||
|
|
"{} / {} / {}",
|
|||
|
|
value.use_lut_palette,
|
|||
|
|
value.alternate_highlight,
|
|||
|
|
value.alternate_highlight_color
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"GPU",
|
|||
|
|
format!(
|
|||
|
|
"geometry shader {}; blending {}; AA {:.4}; reserved {:.4}",
|
|||
|
|
value.geometry_shader_usage,
|
|||
|
|
value.blending_mode,
|
|||
|
|
value.antialiasing_level,
|
|||
|
|
value.reserved_double
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PointCloudDefinition(value)
|
|||
|
|
| ClassObjectData::PointCloudDefinitionEx(value) => PropSection {
|
|||
|
|
title: "Point Cloud Definition".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("File", value.source_filename.clone()),
|
|||
|
|
ro("Loaded", value.is_loaded.to_string()),
|
|||
|
|
ro("Points", value.point_count.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Extents",
|
|||
|
|
format!(
|
|||
|
|
"{:.6},{:.6},{:.6} → {:.6},{:.6},{:.6}",
|
|||
|
|
value.extents_min.x,
|
|||
|
|
value.extents_min.y,
|
|||
|
|
value.extents_min.z,
|
|||
|
|
value.extents_max.x,
|
|||
|
|
value.extents_max.y,
|
|||
|
|
value.extents_max.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PointCloudDefinitionReactor(value)
|
|||
|
|
| ClassObjectData::PointCloudDefinitionReactorEx(value) => PropSection {
|
|||
|
|
title: "Point Cloud Reactor".to_string(),
|
|||
|
|
props: vec![ro("Version", value.class_version.to_string())],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PointCloudColorMap(value) => PropSection {
|
|||
|
|
title: "Point Cloud Color Map".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Defaults",
|
|||
|
|
format!(
|
|||
|
|
"intensity '{}'; elevation '{}'; classification '{}'",
|
|||
|
|
value.default_intensity_scheme,
|
|||
|
|
value.default_elevation_scheme,
|
|||
|
|
value.default_classification_scheme
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Ramps",
|
|||
|
|
bounded_join(
|
|||
|
|
value.color_ramps.iter().map(|ramp| {
|
|||
|
|
format!(
|
|||
|
|
"v{} [{}]",
|
|||
|
|
ramp.class_version,
|
|||
|
|
ramp.color_schemes.join(", ")
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
32,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Classification Ramps",
|
|||
|
|
bounded_join(
|
|||
|
|
value.classification_color_ramps.iter().map(|ramp| {
|
|||
|
|
format!(
|
|||
|
|
"v{} [{}]",
|
|||
|
|
ramp.class_version,
|
|||
|
|
ramp.color_schemes.join(", ")
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
32,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::NavisworksModelDefinition(value) => PropSection {
|
|||
|
|
title: "Coordination Model Definition".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Path", value.path.clone()),
|
|||
|
|
ro(
|
|||
|
|
"State",
|
|||
|
|
format!(
|
|||
|
|
"flags {}; status {}; host visible {}",
|
|||
|
|
value.flags, value.status, value.host_drawing_visibility
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Extents",
|
|||
|
|
format!(
|
|||
|
|
"{:.6},{:.6},{:.6} → {:.6},{:.6},{:.6}",
|
|||
|
|
value.extents_min.x,
|
|||
|
|
value.extents_min.y,
|
|||
|
|
value.extents_min.z,
|
|||
|
|
value.extents_max.x,
|
|||
|
|
value.extents_max.y,
|
|||
|
|
value.extents_max.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ContextDataManager(value) => PropSection {
|
|||
|
|
title: "Context Data Manager".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Object Context", handle_text(value.object_context)),
|
|||
|
|
ro(
|
|||
|
|
"Sub-Managers",
|
|||
|
|
bounded_join(
|
|||
|
|
value.sub_managers.iter().map(|manager| {
|
|||
|
|
format!(
|
|||
|
|
"{} [{}]",
|
|||
|
|
handle_text(manager.handle),
|
|||
|
|
bounded_join(
|
|||
|
|
manager.entries.iter().map(|entry| format!(
|
|||
|
|
"{}={}",
|
|||
|
|
entry.name,
|
|||
|
|
handle_text(entry.item)
|
|||
|
|
)),
|
|||
|
|
32
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
32,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SunStudy(value) => PropSection {
|
|||
|
|
title: "Sun Study".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Name", value.setup_name.clone()),
|
|||
|
|
ro("Description", value.description.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Output",
|
|||
|
|
format!(
|
|||
|
|
"type {}; subset {} '{} / {}'; calendar {}; range {}",
|
|||
|
|
value.output_type,
|
|||
|
|
value.use_subset,
|
|||
|
|
value.sheet_set_name,
|
|||
|
|
value.sheet_subset_name,
|
|||
|
|
value.select_dates_from_calendar,
|
|||
|
|
value.select_range_of_dates
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Dates",
|
|||
|
|
bounded_join(
|
|||
|
|
value.dates.iter().map(|date| {
|
|||
|
|
format!("Julian {} @ {} ms", date.julian_day, date.milliseconds)
|
|||
|
|
}),
|
|||
|
|
64,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Time",
|
|||
|
|
format!(
|
|||
|
|
"{}..{} every {}; active hours {}",
|
|||
|
|
value.start_time,
|
|||
|
|
value.end_time,
|
|||
|
|
value.interval,
|
|||
|
|
value.hours.iter().filter(|enabled| **enabled).count()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Layout",
|
|||
|
|
format!(
|
|||
|
|
"shade {}; viewports {}; {}×{} spacing {:.6}; lock {}; labels {}",
|
|||
|
|
value.shade_plot_type,
|
|||
|
|
value.viewport_count,
|
|||
|
|
value.rows,
|
|||
|
|
value.columns,
|
|||
|
|
value.spacing,
|
|||
|
|
value.lock_viewports,
|
|||
|
|
value.label_viewports
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"References",
|
|||
|
|
format!(
|
|||
|
|
"wizard {}; view {}; visual style {}; text style {}",
|
|||
|
|
handle_text(value.page_setup_wizard),
|
|||
|
|
handle_text(value.view),
|
|||
|
|
handle_text(value.visual_style),
|
|||
|
|
handle_text(value.text_style)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::DataTable(value) => PropSection {
|
|||
|
|
title: format!("Data Table · {}", value.name),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Shape",
|
|||
|
|
format!(
|
|||
|
|
"{} rows; {} columns; flags {}",
|
|||
|
|
value.row_count,
|
|||
|
|
value.columns.len(),
|
|||
|
|
value.flags
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Columns",
|
|||
|
|
bounded_join(
|
|||
|
|
value.columns.iter().map(|column| {
|
|||
|
|
format!(
|
|||
|
|
"{} type {} rows [{}]",
|
|||
|
|
column.name,
|
|||
|
|
column.value_type,
|
|||
|
|
bounded_join(
|
|||
|
|
column.rows.iter().map(|cell| format!(
|
|||
|
|
"{} | {:.8} | {}",
|
|||
|
|
cell.integer,
|
|||
|
|
cell.real,
|
|||
|
|
preview_text(&cell.text, 128)
|
|||
|
|
)),
|
|||
|
|
32
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
32,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::DataLink(value) => PropSection {
|
|||
|
|
title: "Data Link".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Adapter", value.data_adapter.clone()),
|
|||
|
|
ro("Description", value.description.clone()),
|
|||
|
|
ro("Tooltip", value.tooltip.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Connection",
|
|||
|
|
preview_text(&value.connection_string, 1024),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Options",
|
|||
|
|
format!(
|
|||
|
|
"{} / update {}; flags {}; path {}; status {} '{}'",
|
|||
|
|
value.option,
|
|||
|
|
value.update_option,
|
|||
|
|
value.flags,
|
|||
|
|
value.path_option,
|
|||
|
|
value.status_flags,
|
|||
|
|
value.update_status
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Updated",
|
|||
|
|
format!(
|
|||
|
|
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
|
|||
|
|
value.year,
|
|||
|
|
value.month,
|
|||
|
|
value.day,
|
|||
|
|
value.hour,
|
|||
|
|
value.minute,
|
|||
|
|
value.second,
|
|||
|
|
value.millisecond
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro("Owner", handle_text(value.hard_owner)),
|
|||
|
|
ro(
|
|||
|
|
"Custom Data",
|
|||
|
|
bounded_join(
|
|||
|
|
value.custom_data.iter().map(|entry| {
|
|||
|
|
format!(
|
|||
|
|
"{}='{}'",
|
|||
|
|
handle_text(entry.target),
|
|||
|
|
preview_text(&entry.value, 256)
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
64,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::PersistentSubentityManager(value) => PropSection {
|
|||
|
|
title: "Persistent Subentity Manager".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Reserved",
|
|||
|
|
format!("{}/{}", value.reserved_zero, value.reserved_two),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Steps",
|
|||
|
|
format!(
|
|||
|
|
"{} declared; [{}]",
|
|||
|
|
value.associated_step_count,
|
|||
|
|
bounded_join(value.steps.iter().map(ToString::to_string), 128)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Subentities",
|
|||
|
|
format!(
|
|||
|
|
"{} declared; [{}]",
|
|||
|
|
value.associated_subentity_count,
|
|||
|
|
bounded_join(value.subentities.iter().map(ToString::to_string), 128)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::GeoMapImage(value) => PropSection {
|
|||
|
|
title: "Geographic Map Image".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Origin / Size",
|
|||
|
|
format!(
|
|||
|
|
"{:.8},{:.8},{:.8} / {:.4}×{:.4}",
|
|||
|
|
value.origin.x,
|
|||
|
|
value.origin.y,
|
|||
|
|
value.origin.z,
|
|||
|
|
value.image_size.x,
|
|||
|
|
value.image_size.y
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Display",
|
|||
|
|
format!(
|
|||
|
|
"properties {}; clip {}; brightness {}; contrast {}; fade {}",
|
|||
|
|
value.display_properties,
|
|||
|
|
value.clipping_enabled,
|
|||
|
|
value.brightness,
|
|||
|
|
value.contrast,
|
|||
|
|
value.fade
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::DetailViewStyle(value) => PropSection {
|
|||
|
|
title: format!("Detail View Style · {}", value.base.display_name),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Description", value.base.description.clone()),
|
|||
|
|
ro(
|
|||
|
|
"State",
|
|||
|
|
format!(
|
|||
|
|
"base v{} flags {}; modified {}; v{} flags {}",
|
|||
|
|
value.base.class_version,
|
|||
|
|
value.base.flags,
|
|||
|
|
value.base.modified_for_recompute,
|
|||
|
|
value.class_version,
|
|||
|
|
value.flags
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Identifier",
|
|||
|
|
format!(
|
|||
|
|
"style {}; color {:?}; height {:.6}; excluded '{}'; offset {:.6}; placement {}",
|
|||
|
|
handle_text(value.identifier_style),
|
|||
|
|
value.identifier_color,
|
|||
|
|
value.identifier_height,
|
|||
|
|
value.identifier_excluded_characters,
|
|||
|
|
value.identifier_offset,
|
|||
|
|
value.identifier_placement
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Arrow / Boundary",
|
|||
|
|
format!(
|
|||
|
|
"symbol {} color {:?} size {:.6}; boundary {} weight {} color {:?}",
|
|||
|
|
handle_text(value.arrow_symbol),
|
|||
|
|
value.arrow_symbol_color,
|
|||
|
|
value.arrow_symbol_size,
|
|||
|
|
handle_text(value.boundary_linetype),
|
|||
|
|
value.boundary_lineweight,
|
|||
|
|
value.boundary_color
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"View Label",
|
|||
|
|
format!(
|
|||
|
|
"style {} color {:?} height {:.6}; attachment {}; offset {:.6}; alignment {}; pattern '{}'",
|
|||
|
|
handle_text(value.view_label_text_style),
|
|||
|
|
value.view_label_text_color,
|
|||
|
|
value.view_label_text_height,
|
|||
|
|
value.view_label_attachment,
|
|||
|
|
value.view_label_offset,
|
|||
|
|
value.view_label_alignment,
|
|||
|
|
value.view_label_pattern
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Connection / Border",
|
|||
|
|
format!(
|
|||
|
|
"{} weight {} color {:?}; {} weight {} color {:?}; model edge {}",
|
|||
|
|
handle_text(value.connection_linetype),
|
|||
|
|
value.connection_lineweight,
|
|||
|
|
value.connection_color,
|
|||
|
|
handle_text(value.border_linetype),
|
|||
|
|
value.border_lineweight,
|
|||
|
|
value.border_color,
|
|||
|
|
value.model_edge
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::SectionViewStyle(value) => PropSection {
|
|||
|
|
title: format!("Section View Style · {}", value.base.display_name),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Description", value.base.description.clone()),
|
|||
|
|
ro(
|
|||
|
|
"State",
|
|||
|
|
format!(
|
|||
|
|
"base v{} flags {}; modified {}; v{} flags {}; reserved {:?}",
|
|||
|
|
value.base.class_version,
|
|||
|
|
value.base.flags,
|
|||
|
|
value.base.modified_for_recompute,
|
|||
|
|
value.class_version,
|
|||
|
|
value.flags,
|
|||
|
|
value.reserved_flags
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Identifier / Arrows",
|
|||
|
|
format!(
|
|||
|
|
"style {} color {:?} height {:.6}; symbols {}/{} color {:?} size {:.6}; excluded '{}'; extension {:.6}",
|
|||
|
|
handle_text(value.identifier_style),
|
|||
|
|
value.identifier_color,
|
|||
|
|
value.identifier_height,
|
|||
|
|
handle_text(value.arrow_start_symbol),
|
|||
|
|
handle_text(value.arrow_end_symbol),
|
|||
|
|
value.arrow_symbol_color,
|
|||
|
|
value.arrow_symbol_size,
|
|||
|
|
value.identifier_excluded_characters,
|
|||
|
|
value.arrow_symbol_extension_length
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Plane / Bend",
|
|||
|
|
format!(
|
|||
|
|
"plane {} weight {} color {:?}; bend {} weight {} color {:?}; lengths {:.6}/{:.6}",
|
|||
|
|
handle_text(value.plane_linetype),
|
|||
|
|
value.plane_lineweight,
|
|||
|
|
value.plane_color,
|
|||
|
|
handle_text(value.bend_linetype),
|
|||
|
|
value.bend_lineweight,
|
|||
|
|
value.bend_color,
|
|||
|
|
value.bend_line_length,
|
|||
|
|
value.end_line_length
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"View Label",
|
|||
|
|
format!(
|
|||
|
|
"style {} color {:?} height {:.6}; attachment {}; offset {:.6}; alignment {}; pattern '{}'",
|
|||
|
|
handle_text(value.view_label_text_style),
|
|||
|
|
value.view_label_text_color,
|
|||
|
|
value.view_label_text_height,
|
|||
|
|
value.view_label_attachment,
|
|||
|
|
value.view_label_offset,
|
|||
|
|
value.view_label_alignment,
|
|||
|
|
value.view_label_pattern
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Hatch",
|
|||
|
|
format!(
|
|||
|
|
"color {:?}; background {:?}; pattern '{}'; scale {:.6}; transparency {}; angles [{}]",
|
|||
|
|
value.hatch_color,
|
|||
|
|
value.hatch_background_color,
|
|||
|
|
value.hatch_pattern,
|
|||
|
|
value.hatch_scale,
|
|||
|
|
value.hatch_transparency,
|
|||
|
|
bounded_join(value.hatch_angles.iter().map(|angle| format!("{angle:.6}")), 64)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Placement",
|
|||
|
|
format!(
|
|||
|
|
"identifier {} offset {:.6}; arrow {}; overshoot {:.6}",
|
|||
|
|
value.identifier_position,
|
|||
|
|
value.identifier_offset,
|
|||
|
|
value.arrow_position,
|
|||
|
|
value.end_line_overshoot
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::AcMeCommandHistory(value) => PropSection {
|
|||
|
|
title: "Model Documentation Command History".to_string(),
|
|||
|
|
props: vec![ro("Version", value.class_version.to_string())],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::AcMeScope(value) => PropSection {
|
|||
|
|
title: "Model Documentation Scope".to_string(),
|
|||
|
|
props: vec![ro("Version", value.class_version.to_string())],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::AcMeStateManager(value) => PropSection {
|
|||
|
|
title: "Model Documentation State Manager".to_string(),
|
|||
|
|
props: vec![ro("Version", value.class_version.to_string())],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::CsacDocumentOptions(value) => PropSection {
|
|||
|
|
title: "Model Documentation Options".to_string(),
|
|||
|
|
props: vec![ro("Version", value.class_version.to_string())],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepSourceManager(value) => PropSection {
|
|||
|
|
title: "View Representation Source Manager".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Has Source", value.has_source.to_string()),
|
|||
|
|
ro("Source", handle_text(value.source)),
|
|||
|
|
ro("Status", value.status.to_string()),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepStandard(value) => PropSection {
|
|||
|
|
title: "View Representation Standard".to_string(),
|
|||
|
|
props: vec![ro("Values", format!("{:?}", value.values))],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepOrientationDefinition => PropSection {
|
|||
|
|
title: "View Representation Orientation Definition".to_string(),
|
|||
|
|
props: Vec::new(),
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepOrientation(value) => PropSection {
|
|||
|
|
title: "View Representation Orientation".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Camera",
|
|||
|
|
format!("{:.8},{:.8},{:.8}", value.camera.x, value.camera.y, value.camera.z),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Target",
|
|||
|
|
format!("{:.8},{:.8},{:.8}", value.target.x, value.target.y, value.target.z),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Normal",
|
|||
|
|
format!("{:.8},{:.8},{:.8}", value.normal.x, value.normal.y, value.normal.z),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepSectionDefinition(value) => PropSection {
|
|||
|
|
title: "View Representation Section Definition".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.version.to_string()),
|
|||
|
|
ro("Depth", format!("{:.8}", value.section_depth)),
|
|||
|
|
ro("Flags", format!("{:?}", value.flags)),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepModelSpaceViewSelectionSet(value) => PropSection {
|
|||
|
|
title: "View Representation Selection Set".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Entities",
|
|||
|
|
bounded_join(
|
|||
|
|
value.entities.iter().map(|handle| handle_text(*handle)),
|
|||
|
|
128,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRep(value) => PropSection {
|
|||
|
|
title: format!("View Representation · {}", value.name),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Header",
|
|||
|
|
format!(
|
|||
|
|
"{:?}; scale {}; status {}; description '{}'",
|
|||
|
|
value.header_values, value.scale, value.header_status, value.description
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Source",
|
|||
|
|
format!(
|
|||
|
|
"id {}; enabled {}; version {}; model {}; guid {:08X}-{:04X}-{:04X}-{:?}",
|
|||
|
|
value.source_id,
|
|||
|
|
value.source_enabled,
|
|||
|
|
value.source_version,
|
|||
|
|
value.model_id,
|
|||
|
|
value.guid.data1,
|
|||
|
|
value.guid.data2,
|
|||
|
|
value.guid.data3,
|
|||
|
|
value.guid.data4
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Geometry",
|
|||
|
|
format!(
|
|||
|
|
"marker {}; transform v{} {:?}; database {}; geometry v{} marker {}; sketches {}",
|
|||
|
|
value.marker,
|
|||
|
|
value.transform_version,
|
|||
|
|
value.transform,
|
|||
|
|
value.database_id,
|
|||
|
|
value.geometry_version,
|
|||
|
|
value.geometry_marker,
|
|||
|
|
value.sketches.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"References",
|
|||
|
|
format!(
|
|||
|
|
"related {:?}; source manager {}; owned {:?}; optional {:?}; orientation {}; linked {:?}; style {}",
|
|||
|
|
value.related_objects.map(handle_text),
|
|||
|
|
handle_text(value.source_manager),
|
|||
|
|
value.owned_objects.map(handle_text),
|
|||
|
|
value.optional_objects.map(handle_text),
|
|||
|
|
handle_text(value.orientation),
|
|||
|
|
value.linked_views.map(handle_text),
|
|||
|
|
handle_text(value.style)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Placement",
|
|||
|
|
format!(
|
|||
|
|
"{:.8},{:.8}; rotation {:.8}; active {}; projection {}",
|
|||
|
|
value.position.x,
|
|||
|
|
value.position.y,
|
|||
|
|
value.rotation,
|
|||
|
|
value.is_active,
|
|||
|
|
value.projection
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Actions / Parent",
|
|||
|
|
format!(
|
|||
|
|
"mode {}; action {}; has parent {}; parent {}; section paths {}",
|
|||
|
|
value.action_mode,
|
|||
|
|
value.action.map(handle_text).unwrap_or_else(|| "None".to_string()),
|
|||
|
|
value.has_parent,
|
|||
|
|
handle_text(value.parent),
|
|||
|
|
value.section_sketches.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Tail / Block Path",
|
|||
|
|
format!(
|
|||
|
|
"version {}; state {}; id {}; path count {}; version {}; id {}; enabled {}; entries {}",
|
|||
|
|
value.tail_version,
|
|||
|
|
value.tail_state,
|
|||
|
|
value.tail_id,
|
|||
|
|
value.path_count,
|
|||
|
|
value.path_version,
|
|||
|
|
value.path_id,
|
|||
|
|
value.has_block_path,
|
|||
|
|
value.block_path.as_ref().map(|path| path.entries.len()).unwrap_or_default()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::ViewRepModelSpaceSource(value) => PropSection {
|
|||
|
|
title: "View Representation Model Source".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro(
|
|||
|
|
"Header",
|
|||
|
|
format!(
|
|||
|
|
"enabled {}; values {:?}; source v{} status {}; tail {:?}",
|
|||
|
|
value.enabled,
|
|||
|
|
value.header_values,
|
|||
|
|
value.source_version,
|
|||
|
|
value.source_status,
|
|||
|
|
value.tail_values
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro("Transform", format!("{:?}", value.transform)),
|
|||
|
|
ro(
|
|||
|
|
"References",
|
|||
|
|
format!(
|
|||
|
|
"model {}; references {:?}; orientation {}",
|
|||
|
|
handle_text(value.model),
|
|||
|
|
value.references.map(handle_text),
|
|||
|
|
handle_text(value.orientation)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"GUID",
|
|||
|
|
format!(
|
|||
|
|
"{:08X}-{:04X}-{:04X}-{:?}",
|
|||
|
|
value.guid.data1,
|
|||
|
|
value.guid.data2,
|
|||
|
|
value.guid.data3,
|
|||
|
|
value.guid.data4
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
ClassObjectData::LightList(_)
|
|||
|
|
| ClassObjectData::Sun(_)
|
|||
|
|
| ClassObjectData::RenderSettings(_)
|
|||
|
|
| ClassObjectData::MentalRayRenderSettings(_)
|
|||
|
|
| ClassObjectData::RapidRtRenderSettings(_)
|
|||
|
|
| ClassObjectData::RenderEnvironment(_)
|
|||
|
|
| ClassObjectData::RenderGlobal(_) => return None,
|
|||
|
|
};
|
|||
|
|
Some(section)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn semantic_property_text(
|
|||
|
|
value: &acadrust::objects::SemanticPropertyValue,
|
|||
|
|
) -> String {
|
|||
|
|
use acadrust::objects::SemanticPropertyValue;
|
|||
|
|
match value {
|
|||
|
|
SemanticPropertyValue::Text(value) => preview_text(value, 512),
|
|||
|
|
SemanticPropertyValue::Bool(value) => value.to_string(),
|
|||
|
|
SemanticPropertyValue::Byte(value) => value.to_string(),
|
|||
|
|
SemanticPropertyValue::Int16(value) => value.to_string(),
|
|||
|
|
SemanticPropertyValue::Int32(value) => value.to_string(),
|
|||
|
|
SemanticPropertyValue::Int64(value) => value.to_string(),
|
|||
|
|
SemanticPropertyValue::Double(value) => format!("{value:.12}"),
|
|||
|
|
SemanticPropertyValue::Handle(value) => handle_text(*value),
|
|||
|
|
SemanticPropertyValue::Binary(value) => format!("{} bytes", value.len()),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn auxiliary_object_property(
|
|||
|
|
object: &ObjectType,
|
|||
|
|
) -> Option<Property> {
|
|||
|
|
use acadrust::objects::DataObjectData;
|
|||
|
|
|
|||
|
|
let (label, value) = match object {
|
|||
|
|
ObjectType::TableContent(table) => (
|
|||
|
|
format!("Table Content {}", handle_text(table.common.handle)),
|
|||
|
|
format!(
|
|||
|
|
"{} rows × {} columns; {} merged ranges; {} fields",
|
|||
|
|
table.rows.len(),
|
|||
|
|
table.columns.len(),
|
|||
|
|
table.merged_ranges.len(),
|
|||
|
|
table.field_handles.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ObjectType::ImageDefinitionReactor(value) => (
|
|||
|
|
format!("Image Reactor {}", handle_text(value.handle)),
|
|||
|
|
format!(
|
|||
|
|
"owner {}; image {}",
|
|||
|
|
handle_text(value.owner),
|
|||
|
|
handle_text(value.image_handle)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ObjectType::BookColor(value) => (
|
|||
|
|
format!("Book Color {}", handle_text(value.handle)),
|
|||
|
|
format!("{} / {} = {:?}", value.book_name, value.color_name, value.color),
|
|||
|
|
),
|
|||
|
|
ObjectType::PlaceHolder(value) => (
|
|||
|
|
format!("Placeholder {}", handle_text(value.handle)),
|
|||
|
|
format!("owner {}", handle_text(value.owner)),
|
|||
|
|
),
|
|||
|
|
ObjectType::FieldList(value) => (
|
|||
|
|
format!("Field List {}", handle_text(value.handle)),
|
|||
|
|
format!(
|
|||
|
|
"owner {}; unknown {}; fields [{}]",
|
|||
|
|
handle_text(value.owner),
|
|||
|
|
value.unknown,
|
|||
|
|
bounded_join(value.fields.iter().map(|handle| handle_text(*handle)), 128)
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ObjectType::DataObject(value) => {
|
|||
|
|
let text = match &value.data {
|
|||
|
|
DataObjectData::BreakPointRef => "break point reference".to_string(),
|
|||
|
|
DataObjectData::BreakData(data) => format!(
|
|||
|
|
"v{} dimension {}; reserved {}; point references {}",
|
|||
|
|
data.version,
|
|||
|
|
handle_text(data.dimension_reference),
|
|||
|
|
handle_text(data.reserved_reference),
|
|||
|
|
data.point_references.len()
|
|||
|
|
),
|
|||
|
|
DataObjectData::CellStyleMap(data) => {
|
|||
|
|
format!("{} named cell styles", data.cells.len())
|
|||
|
|
}
|
|||
|
|
DataObjectData::AcDsRecord => "AcDs record".to_string(),
|
|||
|
|
DataObjectData::AcDsSchema => "AcDs schema".to_string(),
|
|||
|
|
DataObjectData::Dummy => "dummy helper".to_string(),
|
|||
|
|
DataObjectData::IdBuffer(data) => format!(
|
|||
|
|
"flags {}; objects [{}]",
|
|||
|
|
data.flags,
|
|||
|
|
bounded_join(
|
|||
|
|
data.object_ids.iter().map(|handle| handle_text(*handle)),
|
|||
|
|
128
|
|||
|
|
)
|
|||
|
|
),
|
|||
|
|
DataObjectData::Index(data) => format!(
|
|||
|
|
"updated Julian {} @ {} ms",
|
|||
|
|
data.last_updated_julian_day, data.last_updated_milliseconds
|
|||
|
|
),
|
|||
|
|
DataObjectData::LayerIndex(data) => format!(
|
|||
|
|
"updated Julian {} @ {} ms; entries [{}]",
|
|||
|
|
data.last_updated_julian_day,
|
|||
|
|
data.last_updated_milliseconds,
|
|||
|
|
bounded_join(
|
|||
|
|
data.entries.iter().map(|entry| format!(
|
|||
|
|
"{}: {} layers, buffer {}",
|
|||
|
|
entry.name,
|
|||
|
|
entry.layer_count,
|
|||
|
|
handle_text(entry.id_buffer)
|
|||
|
|
)),
|
|||
|
|
64
|
|||
|
|
)
|
|||
|
|
),
|
|||
|
|
DataObjectData::LongTransaction => "long transaction".to_string(),
|
|||
|
|
DataObjectData::ObjectPointer => "object pointer".to_string(),
|
|||
|
|
DataObjectData::PartialViewingFilter(_) => {
|
|||
|
|
"partial viewing filter".to_string()
|
|||
|
|
}
|
|||
|
|
DataObjectData::TableGeometry(data) => format!(
|
|||
|
|
"{} rows × {} columns; {} cell geometry records; {} primitives",
|
|||
|
|
data.rows,
|
|||
|
|
data.columns,
|
|||
|
|
data.cells.len(),
|
|||
|
|
data.cells.iter().map(|cell| cell.geometry.len()).sum::<usize>()
|
|||
|
|
),
|
|||
|
|
};
|
|||
|
|
(
|
|||
|
|
format!("{} {}", value.dxf_name(), handle_text(value.handle)),
|
|||
|
|
format!("owner {}; {text}", handle_text(value.owner)),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
ObjectType::RegisteredClass(value) => (
|
|||
|
|
format!(
|
|||
|
|
"{} {}",
|
|||
|
|
if value.dxf_name.is_empty() {
|
|||
|
|
value.cpp_class_name.as_str()
|
|||
|
|
} else {
|
|||
|
|
value.dxf_name.as_str()
|
|||
|
|
},
|
|||
|
|
handle_text(value.handle)
|
|||
|
|
),
|
|||
|
|
format!(
|
|||
|
|
"owner {}; properties [{}]; payload {} bits / {} records; references {}",
|
|||
|
|
handle_text(value.owner),
|
|||
|
|
bounded_join(
|
|||
|
|
value.properties.iter().map(|property| format!(
|
|||
|
|
"{}:{}={}",
|
|||
|
|
property.subclass,
|
|||
|
|
property.code,
|
|||
|
|
semantic_property_text(&property.value)
|
|||
|
|
)),
|
|||
|
|
64
|
|||
|
|
),
|
|||
|
|
value.payload.bit_count,
|
|||
|
|
value.payload.records.len(),
|
|||
|
|
value.object_ids.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ObjectType::ProxyObject(value) => (
|
|||
|
|
format!(
|
|||
|
|
"Proxy Object {}",
|
|||
|
|
handle_text(value.handle)
|
|||
|
|
),
|
|||
|
|
format!(
|
|||
|
|
"class {} / id {}; subclass '{}'; version {}/{} maintenance {}; DXF {}; payload {} + {} bits; references {}",
|
|||
|
|
value.class_id,
|
|||
|
|
value.proxy_id,
|
|||
|
|
value.dxf_subclass,
|
|||
|
|
value.version,
|
|||
|
|
value.dwg_version,
|
|||
|
|
value.maintenance_version,
|
|||
|
|
value.from_dxf,
|
|||
|
|
value.payload.bit_count,
|
|||
|
|
value.text_payload.bit_count,
|
|||
|
|
value.object_ids.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ObjectType::Unknown {
|
|||
|
|
type_name,
|
|||
|
|
handle,
|
|||
|
|
owner,
|
|||
|
|
raw_dxf_codes,
|
|||
|
|
raw_dwg_data,
|
|||
|
|
raw_dwg_handle_bits,
|
|||
|
|
..
|
|||
|
|
} => (
|
|||
|
|
format!("Unknown Object {}", handle_text(*handle)),
|
|||
|
|
format!(
|
|||
|
|
"{}; owner {}; DXF codes {}; DWG bytes {}; handle bits {}",
|
|||
|
|
type_name,
|
|||
|
|
handle_text(*owner),
|
|||
|
|
raw_dxf_codes.as_ref().map(Vec::len).unwrap_or_default(),
|
|||
|
|
raw_dwg_data.as_ref().map(Vec::len).unwrap_or_default(),
|
|||
|
|
raw_dwg_handle_bits
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
_ => return None,
|
|||
|
|
};
|
|||
|
|
Some(ro(label, value))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Drawing-level standard object data prepared on the file-open worker.
|
|||
|
|
fn build_document_sections(document: &CadDocument) -> Vec<PropSection> {
|
|||
|
|
use acadrust::objects::ClassObjectData;
|
|||
|
|
|
|||
|
|
let mut sections = vec![PropSection {
|
|||
|
|
title: "Drawing".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", format!("{:?}", document.version)),
|
|||
|
|
ro("Entities", document.entity_count().to_string()),
|
|||
|
|
ro("Objects", document.objects.len().to_string()),
|
|||
|
|
ro("Layers", document.layers.len().to_string()),
|
|||
|
|
ro("Blocks", document.block_records.len().to_string()),
|
|||
|
|
],
|
|||
|
|
}];
|
|||
|
|
|
|||
|
|
let mut objects = document.objects.iter().collect::<Vec<_>>();
|
|||
|
|
objects.sort_by_key(|(handle, _)| handle.value());
|
|||
|
|
for (_, object) in objects {
|
|||
|
|
match object {
|
|||
|
|
ObjectType::GeoData(value) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Geographic Location".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.version.to_string()),
|
|||
|
|
ro("Coordinate Type", value.coordinate_type.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Design Point",
|
|||
|
|
format!(
|
|||
|
|
"{:.8}, {:.8}, {:.8}",
|
|||
|
|
value.design_point.x,
|
|||
|
|
value.design_point.y,
|
|||
|
|
value.design_point.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Reference Point",
|
|||
|
|
format!(
|
|||
|
|
"{:.8}, {:.8}, {:.8}",
|
|||
|
|
value.reference_point.x,
|
|||
|
|
value.reference_point.y,
|
|||
|
|
value.reference_point.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"North",
|
|||
|
|
format!(
|
|||
|
|
"{:.8}, {:.8}",
|
|||
|
|
value.north_direction.x, value.north_direction.y
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Up",
|
|||
|
|
format!(
|
|||
|
|
"{:.8}, {:.8}, {:.8}",
|
|||
|
|
value.up_direction.x,
|
|||
|
|
value.up_direction.y,
|
|||
|
|
value.up_direction.z
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Units / Scale",
|
|||
|
|
format!(
|
|||
|
|
"horizontal {} × {:.12}; vertical {} × {:.12}; user {:.12}",
|
|||
|
|
value.horizontal_units,
|
|||
|
|
value.horizontal_unit_scale,
|
|||
|
|
value.vertical_units,
|
|||
|
|
value.vertical_unit_scale,
|
|||
|
|
value.user_scale_factor
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Sea Level",
|
|||
|
|
format!(
|
|||
|
|
"enabled {}; elevation {:.8}; radius {:.8}",
|
|||
|
|
value.sea_level_correction,
|
|||
|
|
value.sea_level_elevation,
|
|||
|
|
value.coordinate_projection_radius
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Coordinate System",
|
|||
|
|
preview_text(&value.coordinate_system_definition, 1024),
|
|||
|
|
),
|
|||
|
|
ro("Datum", preview_text(&value.coordinate_system_datum, 512)),
|
|||
|
|
ro("WKT", preview_text(&value.coordinate_system_wkt, 1024)),
|
|||
|
|
ro(
|
|||
|
|
"Transformation Mesh",
|
|||
|
|
format!(
|
|||
|
|
"{} points; {} faces",
|
|||
|
|
value.mesh_points.len(),
|
|||
|
|
value.mesh_faces.len()
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Observation",
|
|||
|
|
format!(
|
|||
|
|
"{} → {}; coverage {}; RSS {}",
|
|||
|
|
value.observation_from_tag,
|
|||
|
|
value.observation_to_tag,
|
|||
|
|
value.observation_coverage_tag,
|
|||
|
|
value.geo_rss_tag
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ObjectType::RasterVariables(value) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Raster Settings".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", value.class_version.to_string()),
|
|||
|
|
ro("Display Frame", value.display_image_frame.to_string()),
|
|||
|
|
ro("Quality", value.image_quality.to_string()),
|
|||
|
|
ro("Units", value.units.to_string()),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ObjectType::WipeoutVariables(value) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Wipeout Settings".to_string(),
|
|||
|
|
props: vec![ro("Display Frame", value.display_frame.to_string())],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ObjectType::ClassObject(value) => match &value.data {
|
|||
|
|
ClassObjectData::LightList(list) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Light List".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", list.class_version.to_string()),
|
|||
|
|
ro("Lights", list.lights.len().to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Entries",
|
|||
|
|
bounded_join(
|
|||
|
|
list.lights.iter().map(|light| {
|
|||
|
|
format!(
|
|||
|
|
"{}={}",
|
|||
|
|
light.name,
|
|||
|
|
handle_text(light.handle)
|
|||
|
|
)
|
|||
|
|
}),
|
|||
|
|
64,
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::Sun(sun) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Sun".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", sun.class_version.to_string()),
|
|||
|
|
ro("On", sun.is_on.to_string()),
|
|||
|
|
ro("Color", format!("{:?}", sun.color)),
|
|||
|
|
ro("Intensity", format!("{:.6}", sun.intensity)),
|
|||
|
|
ro(
|
|||
|
|
"Date / Time",
|
|||
|
|
format!(
|
|||
|
|
"Julian {}; {} ms; DST {}",
|
|||
|
|
sun.julian_day,
|
|||
|
|
sun.milliseconds,
|
|||
|
|
sun.is_daylight_savings_on
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Shadows",
|
|||
|
|
format!(
|
|||
|
|
"enabled {}; type {}; map {}; softness {}",
|
|||
|
|
sun.has_shadow,
|
|||
|
|
sun.shadow_type,
|
|||
|
|
sun.shadow_map_size,
|
|||
|
|
sun.shadow_softness
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::RenderSettings(settings) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Render Settings".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", settings.class_version.to_string()),
|
|||
|
|
ro("Name", settings.name.clone()),
|
|||
|
|
ro("Description", settings.description.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Flags",
|
|||
|
|
format!(
|
|||
|
|
"fog {}; fog background {}; backfaces {}; environment {}",
|
|||
|
|
settings.fog_enabled,
|
|||
|
|
settings.fog_background_enabled,
|
|||
|
|
settings.backfaces_enabled,
|
|||
|
|
settings.environment_image_enabled
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Environment Image",
|
|||
|
|
settings.environment_image_filename.clone(),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Display",
|
|||
|
|
format!(
|
|||
|
|
"index {}; predefined {}",
|
|||
|
|
settings.display_index, settings.has_predefined
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::MentalRayRenderSettings(settings) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Mental Ray".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Preset", settings.base.name.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Version",
|
|||
|
|
format!(
|
|||
|
|
"base {}; mental ray {}",
|
|||
|
|
settings.base.class_version, settings.version
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Preset State",
|
|||
|
|
format!(
|
|||
|
|
"description '{}'; display {}; predefined {}; fog {}/{}; backfaces {}; environment {} '{}'",
|
|||
|
|
settings.base.description,
|
|||
|
|
settings.base.display_index,
|
|||
|
|
settings.base.has_predefined,
|
|||
|
|
settings.base.fog_enabled,
|
|||
|
|
settings.base.fog_background_enabled,
|
|||
|
|
settings.base.backfaces_enabled,
|
|||
|
|
settings.base.environment_image_enabled,
|
|||
|
|
settings.base.environment_image_filename
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Sampling",
|
|||
|
|
format!(
|
|||
|
|
"{}..{}; filter {} {:.4}×{:.4}; contrast {:?}",
|
|||
|
|
settings.sampling_min,
|
|||
|
|
settings.sampling_max,
|
|||
|
|
settings.sampling_filter,
|
|||
|
|
settings.sampling_filter_width,
|
|||
|
|
settings.sampling_filter_height,
|
|||
|
|
settings.sampling_contrast
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Ray Tracing",
|
|||
|
|
format!(
|
|||
|
|
"{}; depth {:?}; shadows {} / maps {}",
|
|||
|
|
settings.ray_tracing_enabled,
|
|||
|
|
settings.ray_trace_depth,
|
|||
|
|
settings.shadow_mode,
|
|||
|
|
settings.shadow_maps_enabled
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Global Illumination",
|
|||
|
|
format!(
|
|||
|
|
"{}; samples {}; radius {} {:.6}; photons {}; trace {:?}",
|
|||
|
|
settings.global_illumination_enabled,
|
|||
|
|
settings.global_illumination_sample_count,
|
|||
|
|
settings.global_illumination_sample_radius_enabled,
|
|||
|
|
settings.global_illumination_sample_radius,
|
|||
|
|
settings.photons_per_light,
|
|||
|
|
settings.photon_trace_depth
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Final Gather",
|
|||
|
|
format!(
|
|||
|
|
"{}; rays {}; state {:?}; radius {:?}",
|
|||
|
|
settings.final_gathering_enabled,
|
|||
|
|
settings.final_gathering_ray_count,
|
|||
|
|
settings.final_gathering_sample_radius_state,
|
|||
|
|
settings.final_gathering_sample_radius
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Diagnostics",
|
|||
|
|
format!(
|
|||
|
|
"mode {}; grid {} size {:.6}; photon {}; BSP {}; samples {}; luminance {:.6}",
|
|||
|
|
settings.diagnostics_mode,
|
|||
|
|
settings.diagnostics_grid_mode,
|
|||
|
|
settings.diagnostics_grid_size,
|
|||
|
|
settings.diagnostics_photon_mode,
|
|||
|
|
settings.diagnostics_bsp_mode,
|
|||
|
|
settings.diagnostics_samples_mode,
|
|||
|
|
settings.light_luminance_scale
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Execution",
|
|||
|
|
format!(
|
|||
|
|
"export {}; description '{}'; tile {} order {}; memory {}; energy {:.6}",
|
|||
|
|
settings.export_mi_enabled,
|
|||
|
|
settings.description,
|
|||
|
|
settings.tile_size,
|
|||
|
|
settings.tile_order,
|
|||
|
|
settings.memory_limit,
|
|||
|
|
settings.energy_multiplier
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::RapidRtRenderSettings(settings) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Rapid RT".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Preset", settings.base.name.clone()),
|
|||
|
|
ro(
|
|||
|
|
"Version",
|
|||
|
|
format!(
|
|||
|
|
"base {}; Rapid RT {}",
|
|||
|
|
settings.base.class_version, settings.version
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Preset State",
|
|||
|
|
format!(
|
|||
|
|
"description '{}'; display {}; predefined {}; fog {}/{}; backfaces {}; environment {} '{}'",
|
|||
|
|
settings.base.description,
|
|||
|
|
settings.base.display_index,
|
|||
|
|
settings.base.has_predefined,
|
|||
|
|
settings.base.fog_enabled,
|
|||
|
|
settings.base.fog_background_enabled,
|
|||
|
|
settings.base.backfaces_enabled,
|
|||
|
|
settings.base.environment_image_enabled,
|
|||
|
|
settings.base.environment_image_filename
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Target / Level / Time",
|
|||
|
|
format!(
|
|||
|
|
"{} / {} / {}",
|
|||
|
|
settings.render_target,
|
|||
|
|
settings.render_level,
|
|||
|
|
settings.render_time
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Lighting / Filter",
|
|||
|
|
format!(
|
|||
|
|
"{} / {} {:.4}×{:.4}",
|
|||
|
|
settings.lighting_model,
|
|||
|
|
settings.filter_type,
|
|||
|
|
settings.filter_width,
|
|||
|
|
settings.filter_height
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::RenderEnvironment(environment) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Render Environment".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", environment.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Fog",
|
|||
|
|
format!(
|
|||
|
|
"{}; background {}; color {:?}; density {:.4}..{:.4}; distance {:.4}..{:.4}",
|
|||
|
|
environment.fog_enabled,
|
|||
|
|
environment.fog_background_enabled,
|
|||
|
|
environment.fog_color,
|
|||
|
|
environment.fog_density_near,
|
|||
|
|
environment.fog_density_far,
|
|||
|
|
environment.fog_distance_near,
|
|||
|
|
environment.fog_distance_far
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Environment Image",
|
|||
|
|
format!(
|
|||
|
|
"{} · {}",
|
|||
|
|
environment.environment_image_enabled,
|
|||
|
|
environment.environment_image_filename
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
ClassObjectData::RenderGlobal(global) => {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Render Output".to_string(),
|
|||
|
|
props: vec![
|
|||
|
|
ro("Version", global.class_version.to_string()),
|
|||
|
|
ro(
|
|||
|
|
"Procedure / Destination",
|
|||
|
|
format!("{} / {}", global.procedure, global.destination),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Image",
|
|||
|
|
format!(
|
|||
|
|
"{}×{}; save {} · {}",
|
|||
|
|
global.image_width,
|
|||
|
|
global.image_height,
|
|||
|
|
global.save_enabled,
|
|||
|
|
global.save_filename
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
ro(
|
|||
|
|
"Display",
|
|||
|
|
format!(
|
|||
|
|
"predefined first {}; high-level info {}",
|
|||
|
|
global.predefined_presets_first,
|
|||
|
|
global.high_level_info
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
other => {
|
|||
|
|
if let Some(section) = class_object_section(other) {
|
|||
|
|
sections.push(section);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
_ => {}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if !document.dgn_ls_definitions.is_empty() {
|
|||
|
|
let mut definitions = document
|
|||
|
|
.dgn_ls_definitions
|
|||
|
|
.values()
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
definitions.sort_by_key(|definition| definition.handle.value());
|
|||
|
|
let omitted = definitions.len().saturating_sub(128);
|
|||
|
|
let mut props = definitions
|
|||
|
|
.into_iter()
|
|||
|
|
.take(128)
|
|||
|
|
.map(|definition| {
|
|||
|
|
ro(
|
|||
|
|
definition.name.clone(),
|
|||
|
|
format!(
|
|||
|
|
"handle {}; root {}; components {}",
|
|||
|
|
handle_text(definition.handle),
|
|||
|
|
handle_text(definition.root_component),
|
|||
|
|
document.dgn_ls_components.len()
|
|||
|
|
),
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
if omitted != 0 {
|
|||
|
|
props.push(ro("More Definitions", format!("{omitted} omitted")));
|
|||
|
|
}
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "DGN Line Styles".to_string(),
|
|||
|
|
props,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
let mut auxiliary = document
|
|||
|
|
.objects
|
|||
|
|
.values()
|
|||
|
|
.filter_map(auxiliary_object_property)
|
|||
|
|
.collect::<Vec<_>>();
|
|||
|
|
auxiliary.sort_by(|left, right| left.label.cmp(&right.label));
|
|||
|
|
let auxiliary_omitted = auxiliary.len().saturating_sub(256);
|
|||
|
|
auxiliary.truncate(256);
|
|||
|
|
if auxiliary_omitted != 0 {
|
|||
|
|
auxiliary.push(ro(
|
|||
|
|
"More Standard Objects",
|
|||
|
|
format!("{auxiliary_omitted} omitted"),
|
|||
|
|
));
|
|||
|
|
}
|
|||
|
|
if !auxiliary.is_empty() {
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Standard Object Data".to_string(),
|
|||
|
|
props: auxiliary,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
let mut per_title = rustc_hash::FxHashMap::default();
|
|||
|
|
let mut omitted = rustc_hash::FxHashMap::default();
|
|||
|
|
sections.retain(|section| {
|
|||
|
|
if section.title == "Drawing" {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
let shown = per_title.entry(section.title.clone()).or_insert(0usize);
|
|||
|
|
if *shown < 4 {
|
|||
|
|
*shown += 1;
|
|||
|
|
true
|
|||
|
|
} else {
|
|||
|
|
*omitted.entry(section.title.clone()).or_insert(0usize) += 1;
|
|||
|
|
false
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if !omitted.is_empty() {
|
|||
|
|
let mut entries = omitted.into_iter().collect::<Vec<_>>();
|
|||
|
|
entries.sort_by(|left, right| left.0.cmp(&right.0));
|
|||
|
|
sections.push(PropSection {
|
|||
|
|
title: "Additional Standard Objects".to_string(),
|
|||
|
|
props: entries
|
|||
|
|
.into_iter()
|
|||
|
|
.map(|(name, count)| ro(name, format!("{count} more records")))
|
|||
|
|
.collect(),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
sections
|
|||
|
|
}
|