forked from 1b-agent/opencadstudio-upstream
style: apply cargo fmt across workspace
This commit is contained in:
1 parent
85710e5454
commit
9cf9ff2c5c
531 files changed
+57740
-33906
No files matched your search
+148
-55
@@ -1,15 +1,17 @@
|
||||
//! PRESSPULL scene integration. Resolve first; build and validate the complete
|
||||
//! batch before recording undo or changing any persistent entity.
|
||||
|
||||
use codec::entities::{AcisData, EmbeddedEntity, Solid3D, Surface, SurfaceKind, Wire};
|
||||
use codec::objects::{DynamicBlockData, ObjectType, SolidHistoryNodeBase, SolidHistoryOperation, SolidHistorySweep};
|
||||
use codec::types::Vector3;
|
||||
use codec::{EntityType, Handle};
|
||||
use kernel::brep::{self, Body, PlanarFaceProfile, PresspullMode};
|
||||
use glam::DVec3;
|
||||
use crate::scene::model::{solid_history, sweep_model};
|
||||
use crate::scene::model::mesh_model::MeshLodSet;
|
||||
use crate::scene::model::presspull_model::{self, PresspullTarget, PresspullTargetKind};
|
||||
use crate::scene::model::{solid_history, sweep_model};
|
||||
use codec::entities::{AcisData, EmbeddedEntity, Solid3D, Surface, SurfaceKind, Wire};
|
||||
use codec::objects::{
|
||||
DynamicBlockData, ObjectType, SolidHistoryNodeBase, SolidHistoryOperation, SolidHistorySweep,
|
||||
};
|
||||
use codec::types::Vector3;
|
||||
use codec::{EntityType, Handle};
|
||||
use glam::DVec3;
|
||||
use kernel::brep::{self, Body, PlanarFaceProfile, PresspullMode};
|
||||
|
||||
struct PreparedPresspull {
|
||||
owner: Option<Handle>,
|
||||
@@ -19,7 +21,11 @@ struct PreparedPresspull {
|
||||
display: (MeshLodSet, Vec<Wire>, [f64; 3]),
|
||||
}
|
||||
|
||||
fn extrusion_history(entity: &EntityType, direction: DVec3, anchor: DVec3) -> Option<SolidHistoryOperation> {
|
||||
fn extrusion_history(
|
||||
entity: &EntityType,
|
||||
direction: DVec3,
|
||||
anchor: DVec3,
|
||||
) -> Option<SolidHistoryOperation> {
|
||||
if let EntityType::Region(region) = entity {
|
||||
let mut base = SolidHistoryNodeBase::new(1);
|
||||
base.transform = glam::DMat4::IDENTITY.to_cols_array();
|
||||
@@ -42,9 +48,13 @@ fn extrusion_history(entity: &EntityType, direction: DVec3, anchor: DVec3) -> Op
|
||||
impl super::OpenCADStudio {
|
||||
fn restore_presspull_bodies(&mut self) {
|
||||
let scene = &mut self.tabs[self.active_tab].scene;
|
||||
let handles = scene.document.entities().filter_map(|entity| {
|
||||
matches!(entity, EntityType::Solid3D(_)).then_some(entity.common().handle)
|
||||
}).collect::<Vec<_>>();
|
||||
let handles = scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|entity| {
|
||||
matches!(entity, EntityType::Solid3D(_)).then_some(entity.common().handle)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
scene.restore_solid_models(&handles);
|
||||
}
|
||||
|
||||
@@ -52,20 +62,28 @@ impl super::OpenCADStudio {
|
||||
self.restore_presspull_bodies();
|
||||
let tab = &self.tabs[self.active_tab];
|
||||
let plane = tab.ucs_xform().working_plane();
|
||||
tab.scene.selected_handles_in_order().into_iter().filter_map(|handle| {
|
||||
let entity = tab.scene.document.get_entity(handle)?;
|
||||
let (profile_plane, loops, _) = presspull_model::profile_geometry(entity)?;
|
||||
let first = loops.first()?.first()?.point_at(0.0);
|
||||
let anchor = DVec3::from_array(profile_plane.point_at(first));
|
||||
presspull_model::resolve_target(&tab.scene, Some(handle), anchor, plane, false).ok()
|
||||
}).collect()
|
||||
tab.scene
|
||||
.selected_handles_in_order()
|
||||
.into_iter()
|
||||
.filter_map(|handle| {
|
||||
let entity = tab.scene.document.get_entity(handle)?;
|
||||
let (profile_plane, loops, _) = presspull_model::profile_geometry(entity)?;
|
||||
let first = loops.first()?.first()?.point_at(0.0);
|
||||
let anchor = DVec3::from_array(profile_plane.point_at(first));
|
||||
presspull_model::resolve_target(&tab.scene, Some(handle), anchor, plane, false).ok()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(super) fn presspull_pick(&mut self, handle: Option<Handle>, point: DVec3, offset: bool) {
|
||||
self.restore_presspull_bodies();
|
||||
let i = self.active_tab;
|
||||
let target = presspull_model::resolve_target(
|
||||
&self.tabs[i].scene, handle, point, self.tabs[i].ucs_xform().working_plane(), offset,
|
||||
&self.tabs[i].scene,
|
||||
handle,
|
||||
point,
|
||||
self.tabs[i].ucs_xform().working_plane(),
|
||||
offset,
|
||||
);
|
||||
match target {
|
||||
Ok(target) => {
|
||||
@@ -87,18 +105,31 @@ impl super::OpenCADStudio {
|
||||
self.sync_dyn_fields();
|
||||
}
|
||||
|
||||
fn prepare_presspull(&self, targets: &[PresspullTarget], distance: f64) -> Result<Vec<PreparedPresspull>, String> {
|
||||
fn prepare_presspull(
|
||||
&self,
|
||||
targets: &[PresspullTarget],
|
||||
distance: f64,
|
||||
) -> Result<Vec<PreparedPresspull>, String> {
|
||||
if targets.is_empty() || !distance.is_finite() || distance.abs() <= 1e-9 {
|
||||
return Err("PRESSPULL: enter a finite non-zero height.".into());
|
||||
}
|
||||
let scene = &self.tabs[self.active_tab].scene;
|
||||
let mut results: Vec<(Option<Handle>, EntityType, Body, SolidHistoryOperation)> = Vec::new();
|
||||
let mut results: Vec<(Option<Handle>, EntityType, Body, SolidHistoryOperation)> =
|
||||
Vec::new();
|
||||
for target in targets {
|
||||
let owner = match &target.kind {
|
||||
PresspullTargetKind::Profile { source, entity, owner } => {
|
||||
PresspullTargetKind::Profile {
|
||||
source,
|
||||
entity,
|
||||
owner,
|
||||
} => {
|
||||
if let Some(source) = source {
|
||||
if scene.is_layer_locked(*source) || scene.document.get_entity(*source) != Some(entity) {
|
||||
return Err("PRESSPULL: a selected source changed. Select it again.".into());
|
||||
if scene.is_layer_locked(*source)
|
||||
|| scene.document.get_entity(*source) != Some(entity)
|
||||
{
|
||||
return Err(
|
||||
"PRESSPULL: a selected source changed. Select it again.".into()
|
||||
);
|
||||
}
|
||||
}
|
||||
*owner
|
||||
@@ -108,37 +139,57 @@ impl super::OpenCADStudio {
|
||||
if owner.is_some_and(|handle| scene.is_layer_locked(handle)) {
|
||||
return Err("PRESSPULL: the solid is on a locked layer.".into());
|
||||
}
|
||||
let previous = owner.and_then(|handle| results.iter().position(|result| result.0 == Some(handle)));
|
||||
let current = previous.map(|index| &results[index].2)
|
||||
let previous =
|
||||
owner.and_then(|handle| results.iter().position(|result| result.0 == Some(handle)));
|
||||
let current = previous
|
||||
.map(|index| &results[index].2)
|
||||
.or_else(|| owner.and_then(|handle| scene.solid_models.get(&handle)));
|
||||
let (body, history, mut entity) = match &target.kind {
|
||||
PresspullTargetKind::Profile { entity, .. } => {
|
||||
let (plane, loops, closed) = presspull_model::profile_geometry(entity)
|
||||
.ok_or("PRESSPULL: the profile could not be recovered exactly.")?;
|
||||
if owner.is_some() {
|
||||
let current = current.ok_or("PRESSPULL: the original solid could not be restored.")?;
|
||||
let current = current
|
||||
.ok_or("PRESSPULL: the original solid could not be restored.")?;
|
||||
if !closed {
|
||||
return Err("PRESSPULL: an attached region must be closed.".into());
|
||||
}
|
||||
let profile = PlanarFaceProfile { plane, loops, outward: target.direction.to_array() };
|
||||
let body = brep::presspull_region(current, &profile, distance)
|
||||
.ok_or("PRESSPULL: the region could not be added to or cut from the solid.")?;
|
||||
let profile = PlanarFaceProfile {
|
||||
plane,
|
||||
loops,
|
||||
outward: target.direction.to_array(),
|
||||
};
|
||||
let body = brep::presspull_region(current, &profile, distance).ok_or(
|
||||
"PRESSPULL: the region could not be added to or cut from the solid.",
|
||||
)?;
|
||||
let history = solid_history::brep_op(&body);
|
||||
(body, history, scene.document.get_entity(owner.unwrap()).cloned()
|
||||
.ok_or("PRESSPULL: the original solid no longer exists.")?)
|
||||
(
|
||||
body,
|
||||
history,
|
||||
scene
|
||||
.document
|
||||
.get_entity(owner.unwrap())
|
||||
.cloned()
|
||||
.ok_or("PRESSPULL: the original solid no longer exists.")?,
|
||||
)
|
||||
} else {
|
||||
let direction = target.direction * distance;
|
||||
let body = presspull_model::extrusion_body(entity, direction.to_array())
|
||||
.ok_or("PRESSPULL: the profile could not be extruded with this height.")?;
|
||||
let history = extrusion_history(entity, direction, target.anchor)
|
||||
.ok_or("PRESSPULL: the editable extrusion profile could not be retained.")?;
|
||||
.ok_or(
|
||||
"PRESSPULL: the profile could not be extruded with this height.",
|
||||
)?;
|
||||
let history = extrusion_history(entity, direction, target.anchor).ok_or(
|
||||
"PRESSPULL: the editable extrusion profile could not be retained.",
|
||||
)?;
|
||||
let entity = if closed {
|
||||
EntityType::Solid3D(Solid3D::new())
|
||||
} else {
|
||||
let mut surface = Surface::new(SurfaceKind::Extruded);
|
||||
if let SolidHistoryOperation::Extrusion(record) = &history {
|
||||
surface.surface_data = solid_history::extrusion_surface_data(record)
|
||||
.ok_or("PRESSPULL: the surface parameters could not be retained.")?;
|
||||
surface.surface_data =
|
||||
solid_history::extrusion_surface_data(record).ok_or(
|
||||
"PRESSPULL: the surface parameters could not be retained.",
|
||||
)?;
|
||||
}
|
||||
EntityType::Surface(Box::new(surface))
|
||||
};
|
||||
@@ -146,23 +197,44 @@ impl super::OpenCADStudio {
|
||||
}
|
||||
}
|
||||
PresspullTargetKind::Face { face, offset, .. } => {
|
||||
let current = current.ok_or("PRESSPULL: the original solid could not be restored.")?;
|
||||
let current =
|
||||
current.ok_or("PRESSPULL: the original solid could not be restored.")?;
|
||||
// Earlier targets in the same batch may have rebuilt face keys.
|
||||
let face = if previous.is_some() {
|
||||
brep::planar_face_at_point(current, target.anchor.to_array(), 1e-6)
|
||||
.ok_or("PRESSPULL: an earlier selected region changed this face.")?
|
||||
} else { *face };
|
||||
let body = brep::presspull_face(current, face, distance,
|
||||
if *offset { PresspullMode::Offset } else { PresspullMode::Extrude })
|
||||
.ok_or("PRESSPULL: the requested face operation would invalidate the solid.")?;
|
||||
} else {
|
||||
*face
|
||||
};
|
||||
let body = brep::presspull_face(
|
||||
current,
|
||||
face,
|
||||
distance,
|
||||
if *offset {
|
||||
PresspullMode::Offset
|
||||
} else {
|
||||
PresspullMode::Extrude
|
||||
},
|
||||
)
|
||||
.ok_or("PRESSPULL: the requested face operation would invalidate the solid.")?;
|
||||
let history = solid_history::brep_op(&body);
|
||||
(body, history, scene.document.get_entity(owner.unwrap()).cloned()
|
||||
.ok_or("PRESSPULL: the original solid no longer exists.")?)
|
||||
(
|
||||
body,
|
||||
history,
|
||||
scene
|
||||
.document
|
||||
.get_entity(owner.unwrap())
|
||||
.cloned()
|
||||
.ok_or("PRESSPULL: the original solid no longer exists.")?,
|
||||
)
|
||||
}
|
||||
};
|
||||
let sat = crate::scene::convert::acis_export::solid_to_sat(&body)
|
||||
.ok_or("PRESSPULL: the result could not be encoded. The original objects were retained.")?;
|
||||
if owner.is_none() { entity.common_mut().plotstyle_flags = 2; }
|
||||
let sat = crate::scene::convert::acis_export::solid_to_sat(&body).ok_or(
|
||||
"PRESSPULL: the result could not be encoded. The original objects were retained.",
|
||||
)?;
|
||||
if owner.is_none() {
|
||||
entity.common_mut().plotstyle_flags = 2;
|
||||
}
|
||||
match &mut entity {
|
||||
EntityType::Solid3D(solid) => {
|
||||
solid.history_handle = None;
|
||||
@@ -177,7 +249,11 @@ impl super::OpenCADStudio {
|
||||
_ => return Err("PRESSPULL: unsupported result object.".into()),
|
||||
}
|
||||
let result = (owner, entity, body, history);
|
||||
if let Some(index) = previous { results[index] = result; } else { results.push(result); }
|
||||
if let Some(index) = previous {
|
||||
results[index] = result;
|
||||
} else {
|
||||
results.push(result);
|
||||
}
|
||||
}
|
||||
results.into_iter().map(|(owner, entity, body, history)| {
|
||||
let display = scene.prepare_solid_model_display(owner.unwrap_or(Handle::NULL), &body)
|
||||
@@ -210,34 +286,51 @@ impl super::OpenCADStudio {
|
||||
self.tabs[i].scene.update_entity(result.entity);
|
||||
handle
|
||||
} else {
|
||||
self.commit_entity_handle(result.entity).expect("validated solid/surface insertion")
|
||||
self.commit_entity_handle(result.entity)
|
||||
.expect("validated solid/surface insertion")
|
||||
};
|
||||
self.tabs[i].scene.create_solid_history(handle, result.history);
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.create_solid_history(handle, result.history);
|
||||
// PRESSPULL keeps editable construction parameters without enabling
|
||||
// recording of subsequent solid operations by default.
|
||||
if result.owner.is_none() {
|
||||
let document = &mut self.tabs[i].scene.document;
|
||||
if let Some(graph) = document.solid_history_graph(handle) {
|
||||
if let Some(ObjectType::DynamicBlock(object)) = document.objects.get_mut(&graph.root) {
|
||||
if let Some(ObjectType::DynamicBlock(object)) =
|
||||
document.objects.get_mut(&graph.root)
|
||||
{
|
||||
if let DynamicBlockData::SolidHistory(history) = &mut object.data {
|
||||
history.record_history = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.tabs[i].scene.register_prepared_solid_model(handle, result.body, result.display);
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.register_prepared_solid_model(handle, result.body, result.display);
|
||||
handles.push(handle);
|
||||
}
|
||||
self.tabs[i].scene.deselect_all();
|
||||
for handle in &handles { self.tabs[i].scene.select_entity(*handle, false); }
|
||||
for handle in &handles {
|
||||
self.tabs[i].scene.select_entity(*handle, false);
|
||||
}
|
||||
self.tabs[i].dirty = true;
|
||||
if let Some(pending) = pending { self.commit_undo_delta(i, pending); }
|
||||
if let Some(pending) = pending {
|
||||
self.commit_undo_delta(i, pending);
|
||||
}
|
||||
self.tabs[i].scene.clear_preview_wire();
|
||||
self.tabs[i].snap_result = None;
|
||||
if let Some(command) = self.tabs[i].active_cmd.as_mut() {
|
||||
command.on_presspull_applied(true);
|
||||
}
|
||||
self.command_line.push_output(crate::tf!("PRESSPULL: {count} object(s) updated.", count = handles.len()).as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!(
|
||||
"PRESSPULL: {count} object(s) updated.",
|
||||
count = handles.len()
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
self.refresh_properties();
|
||||
self.refresh_presspull_prompt();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user