forked from 1b-agent/opencadstudio-upstream
Align BOX properties and history controls
This commit is contained in:
1 parent
e7eb487cd8
commit
27f648d2bb
4 files changed
+307
-13
No files matched your search
+22
-7
@@ -434,8 +434,21 @@ impl OpenCADStudio {
|
|||||||
let display_entity = dispatch::entity_in_working_plane(contextual.as_ref(), plane);
|
let display_entity = dispatch::entity_in_working_plane(contextual.as_ref(), plane);
|
||||||
let entity = &display_entity;
|
let entity = &display_entity;
|
||||||
let group_names = self.tabs[i].scene.group_names_for_entity(handle);
|
let group_names = self.tabs[i].scene.group_names_for_entity(handle);
|
||||||
|
let box_primitive =
|
||||||
|
crate::scene::model::solid_history::is_box_primitive(
|
||||||
|
&self.tabs[i].scene.document,
|
||||||
|
handle,
|
||||||
|
);
|
||||||
let mut sections =
|
let mut sections =
|
||||||
dispatch::properties_sectioned(handle, entity, &text_style_names);
|
dispatch::properties_sectioned(handle, entity, &text_style_names);
|
||||||
|
if box_primitive {
|
||||||
|
sections.retain(|section| {
|
||||||
|
!section.props.iter().any(|property| {
|
||||||
|
property.field.starts_with("acis_")
|
||||||
|
|| property.field.starts_with("s3d_")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
sections.extend(
|
sections.extend(
|
||||||
crate::scene::model::solid_history::primitive_properties(
|
crate::scene::model::solid_history::primitive_properties(
|
||||||
&self.tabs[i].scene.document,
|
&self.tabs[i].scene.document,
|
||||||
@@ -600,7 +613,7 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(
|
if !box_primitive && matches!(
|
||||||
entity,
|
entity,
|
||||||
acadrust::EntityType::Solid3D(_)
|
acadrust::EntityType::Solid3D(_)
|
||||||
| acadrust::EntityType::Region(_)
|
| acadrust::EntityType::Region(_)
|
||||||
@@ -674,12 +687,14 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sections.extend(crate::entities::object_data::sections(
|
if !box_primitive {
|
||||||
&self.tabs[i].scene.document,
|
sections.extend(crate::entities::object_data::sections(
|
||||||
&self.tabs[i].scene.object_data_cache,
|
&self.tabs[i].scene.document,
|
||||||
handle,
|
&self.tabs[i].scene.object_data_cache,
|
||||||
entity,
|
handle,
|
||||||
));
|
entity,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
use crate::entities::common::ro_prop;
|
use crate::entities::common::ro_prop;
|
||||||
|
|||||||
@@ -1900,7 +1900,16 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
|||||||
}
|
}
|
||||||
self.push_undo_snapshot(i, "CHPROP");
|
self.push_undo_snapshot(i, "CHPROP");
|
||||||
|
|
||||||
if field == "tol_text_style" {
|
if crate::scene::model::solid_history::is_history_choice(field) {
|
||||||
|
for &handle in &handles {
|
||||||
|
if self.tabs[i].scene.is_layer_locked(handle) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.tabs[i]
|
||||||
|
.scene
|
||||||
|
.apply_solid_history_choice(handle, field, &value);
|
||||||
|
}
|
||||||
|
} else if field == "tol_text_style" {
|
||||||
use crate::entities::dim_override as dov;
|
use crate::entities::dim_override as dov;
|
||||||
use acadrust::xdata::XDataValue;
|
use acadrust::xdata::XDataValue;
|
||||||
let style_handle = self.tabs[i]
|
let style_handle = self.tabs[i]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use acadrust::entities::Solid3D;
|
use acadrust::entities::Solid3D;
|
||||||
use acadrust::objects::{
|
use acadrust::objects::{
|
||||||
SolidHistoryBox, SolidHistoryBrep, SolidHistoryCylinder,
|
DynamicBlockData, ObjectType, SolidHistoryBox, SolidHistoryBrep,
|
||||||
SolidHistoryNodeBase, SolidHistoryOperation, SolidHistoryPyramid,
|
SolidHistoryCylinder, SolidHistoryNodeBase, SolidHistoryOperation,
|
||||||
SolidHistorySphere, SolidHistoryTorus,
|
SolidHistoryPyramid, SolidHistorySphere, SolidHistoryTorus,
|
||||||
};
|
};
|
||||||
use cadkernel::brep::Body;
|
use cadkernel::brep::Body;
|
||||||
|
|
||||||
@@ -27,6 +27,12 @@ pub const PROP_RADIUS: &str = "solid_history_radius";
|
|||||||
pub const PROP_OUTER_RADIUS: &str = "solid_history_outer_radius";
|
pub const PROP_OUTER_RADIUS: &str = "solid_history_outer_radius";
|
||||||
pub const PROP_INNER_RADIUS: &str = "solid_history_inner_radius";
|
pub const PROP_INNER_RADIUS: &str = "solid_history_inner_radius";
|
||||||
pub const PROP_SIDES: &str = "solid_history_sides";
|
pub const PROP_SIDES: &str = "solid_history_sides";
|
||||||
|
pub const PROP_POSITION_X: &str = "solid_history_position_x";
|
||||||
|
pub const PROP_POSITION_Y: &str = "solid_history_position_y";
|
||||||
|
pub const PROP_POSITION_Z: &str = "solid_history_position_z";
|
||||||
|
pub const PROP_ROTATION: &str = "solid_history_rotation";
|
||||||
|
pub const PROP_HISTORY: &str = "solid_history_record";
|
||||||
|
pub const PROP_SHOW_HISTORY: &str = "solid_history_show";
|
||||||
|
|
||||||
fn history_prop(label: &str, field: &'static str, value: impl ToString) -> Property {
|
fn history_prop(label: &str, field: &'static str, value: impl ToString) -> Property {
|
||||||
Property {
|
Property {
|
||||||
@@ -36,6 +42,132 @@ fn history_prop(label: &str, field: &'static str, value: impl ToString) -> Prope
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn history_flags(
|
||||||
|
document: &acadrust::CadDocument,
|
||||||
|
handle: acadrust::Handle,
|
||||||
|
) -> Option<(bool, bool)> {
|
||||||
|
let graph = document.solid_history_graph(handle)?;
|
||||||
|
let ObjectType::DynamicBlock(object) = document.objects.get(&graph.root)? else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let DynamicBlockData::SolidHistory(history) = &object.data else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
Some((history.record_history, history.show_history))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_box_primitive(
|
||||||
|
document: &acadrust::CadDocument,
|
||||||
|
handle: acadrust::Handle,
|
||||||
|
) -> bool {
|
||||||
|
matches!(
|
||||||
|
document.solid_history_operation(handle),
|
||||||
|
Some(SolidHistoryOperation::Box(_))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reference_point(operation: &SolidHistoryOperation) -> Option<glam::DVec3> {
|
||||||
|
match operation {
|
||||||
|
SolidHistoryOperation::Box(value) => world_point(
|
||||||
|
value.base.transform,
|
||||||
|
[value.length * 0.5, value.width * 0.5, 0.0],
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn box_properties(
|
||||||
|
document: &acadrust::CadDocument,
|
||||||
|
handle: acadrust::Handle,
|
||||||
|
value: &SolidHistoryBox,
|
||||||
|
) -> Vec<PropSection> {
|
||||||
|
let Some(position) = world_point(
|
||||||
|
value.base.transform,
|
||||||
|
[value.length * 0.5, value.width * 0.5, 0.0],
|
||||||
|
) else {
|
||||||
|
return Vec::new();
|
||||||
|
};
|
||||||
|
let rotation = matrix(value.base.transform)
|
||||||
|
.map(|matrix| matrix.x_axis.y.atan2(matrix.x_axis.x))
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let (record_history, show_history) = history_flags(document, handle).unwrap_or((false, false));
|
||||||
|
let show_value = if show_history { "Yes" } else { "No" };
|
||||||
|
vec![
|
||||||
|
PropSection {
|
||||||
|
title: t!("Geometry").into_owned(),
|
||||||
|
props: vec![
|
||||||
|
Property {
|
||||||
|
label: t!("Solid type").into_owned(),
|
||||||
|
field: "solid_history_type",
|
||||||
|
value: PropValue::ReadOnly(t!("Box").into_owned()),
|
||||||
|
},
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Position X").as_ref(),
|
||||||
|
PROP_POSITION_X,
|
||||||
|
position.x,
|
||||||
|
),
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Position Y").as_ref(),
|
||||||
|
PROP_POSITION_Y,
|
||||||
|
position.y,
|
||||||
|
),
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Position Z").as_ref(),
|
||||||
|
PROP_POSITION_Z,
|
||||||
|
position.z,
|
||||||
|
),
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Length").as_ref(),
|
||||||
|
PROP_LENGTH,
|
||||||
|
value.length,
|
||||||
|
),
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Width").as_ref(),
|
||||||
|
PROP_WIDTH,
|
||||||
|
value.width,
|
||||||
|
),
|
||||||
|
crate::entities::common::edit_prop(
|
||||||
|
t!("Height").as_ref(),
|
||||||
|
PROP_HEIGHT,
|
||||||
|
value.height,
|
||||||
|
),
|
||||||
|
Property {
|
||||||
|
label: t!("Rotation").into_owned(),
|
||||||
|
field: PROP_ROTATION,
|
||||||
|
value: PropValue::EditText(
|
||||||
|
crate::entities::common::format_direction(rotation),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
PropSection {
|
||||||
|
title: t!("Solid History").into_owned(),
|
||||||
|
props: vec![
|
||||||
|
Property {
|
||||||
|
label: t!("History").into_owned(),
|
||||||
|
field: PROP_HISTORY,
|
||||||
|
value: PropValue::Choice {
|
||||||
|
selected: if record_history { "Record" } else { "None" }.to_string(),
|
||||||
|
options: vec!["None".to_string(), "Record".to_string()],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Property {
|
||||||
|
label: t!("Show History").into_owned(),
|
||||||
|
field: PROP_SHOW_HISTORY,
|
||||||
|
value: if record_history {
|
||||||
|
PropValue::Choice {
|
||||||
|
selected: show_value.to_string(),
|
||||||
|
options: vec!["No".to_string(), "Yes".to_string()],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PropValue::ReadOnly(show_value.to_string())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn primitive_properties(
|
pub fn primitive_properties(
|
||||||
document: &acadrust::CadDocument,
|
document: &acadrust::CadDocument,
|
||||||
handle: acadrust::Handle,
|
handle: acadrust::Handle,
|
||||||
@@ -44,7 +176,8 @@ pub fn primitive_properties(
|
|||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
let props = match operation {
|
let props = match operation {
|
||||||
SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) => vec![
|
SolidHistoryOperation::Box(value) => return box_properties(document, handle, value),
|
||||||
|
SolidHistoryOperation::Wedge(value) => vec![
|
||||||
history_prop(t!("Length").as_ref(), PROP_LENGTH, value.length),
|
history_prop(t!("Length").as_ref(), PROP_LENGTH, value.length),
|
||||||
history_prop(t!("Width").as_ref(), PROP_WIDTH, value.width),
|
history_prop(t!("Width").as_ref(), PROP_WIDTH, value.width),
|
||||||
history_prop(t!("Height").as_ref(), PROP_HEIGHT, value.height),
|
history_prop(t!("Height").as_ref(), PROP_HEIGHT, value.height),
|
||||||
@@ -93,15 +226,107 @@ pub fn is_primitive_property(field: &str) -> bool {
|
|||||||
| PROP_OUTER_RADIUS
|
| PROP_OUTER_RADIUS
|
||||||
| PROP_INNER_RADIUS
|
| PROP_INNER_RADIUS
|
||||||
| PROP_SIDES
|
| PROP_SIDES
|
||||||
|
| PROP_POSITION_X
|
||||||
|
| PROP_POSITION_Y
|
||||||
|
| PROP_POSITION_Z
|
||||||
|
| PROP_ROTATION
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_history_choice(field: &str) -> bool {
|
||||||
|
matches!(field, PROP_HISTORY | PROP_SHOW_HISTORY)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_history_choice(
|
||||||
|
document: &mut acadrust::CadDocument,
|
||||||
|
handle: acadrust::Handle,
|
||||||
|
field: &str,
|
||||||
|
value: &str,
|
||||||
|
) -> bool {
|
||||||
|
let Some(graph) = document.solid_history_graph(handle) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(ObjectType::DynamicBlock(object)) = document.objects.get_mut(&graph.root) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let DynamicBlockData::SolidHistory(history) = &mut object.data else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
match field {
|
||||||
|
PROP_HISTORY => {
|
||||||
|
history.record_history = value.eq_ignore_ascii_case("Record");
|
||||||
|
if !history.record_history {
|
||||||
|
history.show_history = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PROP_SHOW_HISTORY if history.record_history => {
|
||||||
|
history.show_history = value.eq_ignore_ascii_case("Yes");
|
||||||
|
}
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_box_geometry_property(
|
||||||
|
value: &mut SolidHistoryBox,
|
||||||
|
field: &str,
|
||||||
|
text: &str,
|
||||||
|
) -> Option<bool> {
|
||||||
|
if field == PROP_ROTATION {
|
||||||
|
let target = crate::entities::common::parse_direction(text)?;
|
||||||
|
let current = matrix(value.base.transform)?;
|
||||||
|
let center = current.transform_point3(glam::DVec3::new(
|
||||||
|
value.length * 0.5,
|
||||||
|
value.width * 0.5,
|
||||||
|
0.0,
|
||||||
|
));
|
||||||
|
let (sin, cos) = target.sin_cos();
|
||||||
|
let x_axis = glam::DVec3::new(cos, sin, 0.0);
|
||||||
|
let y_axis = glam::DVec3::new(-sin, cos, 0.0);
|
||||||
|
let origin = center - x_axis * value.length * 0.5 - y_axis * value.width * 0.5;
|
||||||
|
value.base.transform = glam::DMat4::from_cols(
|
||||||
|
x_axis.extend(0.0),
|
||||||
|
y_axis.extend(0.0),
|
||||||
|
glam::DVec3::Z.extend(0.0),
|
||||||
|
origin.extend(1.0),
|
||||||
|
)
|
||||||
|
.to_cols_array();
|
||||||
|
return Some(true);
|
||||||
|
}
|
||||||
|
let axis = match field {
|
||||||
|
PROP_POSITION_X => 0,
|
||||||
|
PROP_POSITION_Y => 1,
|
||||||
|
PROP_POSITION_Z => 2,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
let target = crate::entities::common::parse_length(text)?;
|
||||||
|
let current = matrix(value.base.transform)?;
|
||||||
|
let center = current.transform_point3(glam::DVec3::new(
|
||||||
|
value.length * 0.5,
|
||||||
|
value.width * 0.5,
|
||||||
|
0.0,
|
||||||
|
));
|
||||||
|
let mut delta = glam::DVec3::ZERO;
|
||||||
|
delta[axis] = target - center[axis];
|
||||||
|
value.base.transform = (glam::DMat4::from_translation(delta) * current).to_cols_array();
|
||||||
|
Some(true)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply_primitive_property(
|
pub fn apply_primitive_property(
|
||||||
operation: &mut SolidHistoryOperation,
|
operation: &mut SolidHistoryOperation,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: &str,
|
value: &str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let Ok(number) = value.trim().parse::<f64>() else {
|
if let SolidHistoryOperation::Box(box_value) = operation {
|
||||||
|
if let Some(applied) = apply_box_geometry_property(box_value, field, value) {
|
||||||
|
return applied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Some(number) = (if field == PROP_SIDES {
|
||||||
|
value.trim().parse::<f64>().ok()
|
||||||
|
} else {
|
||||||
|
crate::entities::common::parse_length(value)
|
||||||
|
}) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if !number.is_finite() {
|
if !number.is_finite() {
|
||||||
|
|||||||
@@ -773,6 +773,7 @@ impl Scene {
|
|||||||
handle: Handle,
|
handle: Handle,
|
||||||
operation: acadrust::objects::SolidHistoryOperation,
|
operation: acadrust::objects::SolidHistoryOperation,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let box_primitive = matches!(operation, acadrust::objects::SolidHistoryOperation::Box(_));
|
||||||
let Some(graph) = self.document.create_solid_history(handle, operation) else {
|
let Some(graph) = self.document.create_solid_history(handle, operation) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -780,9 +781,36 @@ impl Scene {
|
|||||||
for node in graph.nodes {
|
for node in graph.nodes {
|
||||||
self.record_undo_object_before(node, None);
|
self.record_undo_object_before(node, None);
|
||||||
}
|
}
|
||||||
|
if box_primitive {
|
||||||
|
let _ = crate::scene::model::solid_history::apply_history_choice(
|
||||||
|
&mut self.document,
|
||||||
|
handle,
|
||||||
|
crate::scene::model::solid_history::PROP_HISTORY,
|
||||||
|
"None",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.sync_solid_reference_point(handle);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sync_solid_reference_point(&mut self, handle: Handle) {
|
||||||
|
let reference = self
|
||||||
|
.document
|
||||||
|
.solid_history_operation(handle)
|
||||||
|
.and_then(crate::scene::model::solid_history::reference_point);
|
||||||
|
let Some(reference) = reference else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(EntityType::Solid3D(entity)) = self.document.get_entity_mut(handle) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
entity.point_of_reference = acadrust::types::Vector3::new(
|
||||||
|
reference.x,
|
||||||
|
reference.y,
|
||||||
|
reference.z,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn copy_solid_history(&mut self, source: Handle, target: Handle) -> bool {
|
fn copy_solid_history(&mut self, source: Handle, target: Handle) -> bool {
|
||||||
let Some(graph) = self.document.copy_solid_history(source, target) else {
|
let Some(graph) = self.document.copy_solid_history(source, target) else {
|
||||||
return false;
|
return false;
|
||||||
@@ -822,6 +850,7 @@ impl Scene {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
entity.set_sat_document(&document);
|
entity.set_sat_document(&document);
|
||||||
|
self.sync_solid_reference_point(handle);
|
||||||
self.register_solid_model(handle, body);
|
self.register_solid_model(handle, body);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -840,6 +869,7 @@ impl Scene {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
entity.set_sat_document(&document);
|
entity.set_sat_document(&document);
|
||||||
|
self.sync_solid_reference_point(handle);
|
||||||
self.register_solid_model(handle, body);
|
self.register_solid_model(handle, body);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -894,6 +924,21 @@ impl Scene {
|
|||||||
self.rebuild_solid_history(handle, operation)
|
self.rebuild_solid_history(handle, operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_solid_history_choice(
|
||||||
|
&mut self,
|
||||||
|
handle: Handle,
|
||||||
|
field: &str,
|
||||||
|
value: &str,
|
||||||
|
) -> bool {
|
||||||
|
self.record_solid_history_before(handle);
|
||||||
|
crate::scene::model::solid_history::apply_history_choice(
|
||||||
|
&mut self.document,
|
||||||
|
handle,
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn apply_solid_history_grip(
|
fn apply_solid_history_grip(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
|
|||||||
Reference in new issue
Block a user