forked from 1b-agent/opencadstudio-upstream
Complete LOFT commands, surfaces, previews and editable history
This commit is contained in:
1 parent
8e3d851133
commit
479bf87988
15 files changed
+1505
-161
No files matched your search
@@ -0,0 +1,95 @@
|
||||
//! LOFT command/history integration. Geometry and validation live in the kernel.
|
||||
|
||||
use acadrust::entities::{EmbeddedEntity, Point, Surface, SurfaceData, SurfaceKind};
|
||||
use acadrust::objects::{SolidHistoryLoft, SolidHistoryLoftParameters, SolidHistoryNodeBase};
|
||||
use acadrust::{EntityType, Handle};
|
||||
use cadkernel::brep::Body;
|
||||
use crate::command::{ExtrudeMode, LoftOptions, LoftSectionSelection};
|
||||
use super::sweep_model::embedded_path;
|
||||
|
||||
fn embedded_section(entity: &EntityType) -> Option<EmbeddedEntity> {
|
||||
match entity {
|
||||
EntityType::Region(region) => Some(EmbeddedEntity::Region(region.clone())),
|
||||
EntityType::Point(point) => Some(EmbeddedEntity::Point(point.clone())),
|
||||
_ => embedded_path(entity),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_section(entity: &EntityType) -> bool {
|
||||
embedded_section(entity).is_some_and(|entity|
|
||||
cadkernel::acis::loft_section_geometry(&[entity]).is_ok())
|
||||
}
|
||||
|
||||
pub fn is_guide_or_path(entity: &EntityType) -> bool {
|
||||
embedded_path(entity).is_some_and(|entity| cadkernel::acis::loft_path_geometry(&entity).is_ok())
|
||||
}
|
||||
|
||||
pub fn record(
|
||||
sections: &[LoftSectionSelection], guides: &[Handle], path: Option<Handle>,
|
||||
available: &[(Handle, EntityType)], mode: ExtrudeMode, options: LoftOptions,
|
||||
) -> Result<SolidHistoryLoft, String> {
|
||||
let find = |handle| available.iter().find(|(candidate, _)| *candidate == handle)
|
||||
.map(|(_, entity)| entity).ok_or_else(|| "A selected loft source no longer exists.".to_string());
|
||||
let mut cross_sections = Vec::new();
|
||||
let mut section_counts = Vec::new();
|
||||
let mut surface = mode == ExtrudeMode::Surface;
|
||||
for section in sections {
|
||||
let members = match section {
|
||||
LoftSectionSelection::Entity(handle) => vec![embedded_section(find(*handle)?)
|
||||
.ok_or("Unsupported loft section.")?],
|
||||
LoftSectionSelection::Point(point) => vec![EmbeddedEntity::Point(Point::from_coords(point.x, point.y, point.z))],
|
||||
LoftSectionSelection::Join(handles) => handles.iter().map(|handle| {
|
||||
embedded_section(find(*handle)?).ok_or_else(|| "Unsupported joined loft edge.".to_string())
|
||||
}).collect::<Result<Vec<_>, _>>()?,
|
||||
};
|
||||
if let cadkernel::brep::LoftSection::Profile { closed, .. } = cadkernel::acis::loft_section_geometry(&members)? {
|
||||
surface |= !closed;
|
||||
}
|
||||
section_counts.push(members.len());
|
||||
cross_sections.extend(members);
|
||||
}
|
||||
let guides = guides.iter().map(|handle| embedded_path(find(*handle)?)
|
||||
.ok_or_else(|| "Unsupported loft guide.".to_string())).collect::<Result<Vec<_>, _>>()?;
|
||||
let path_entity = path.map(|handle| embedded_path(find(handle)?)
|
||||
.ok_or_else(|| "Unsupported loft path.".to_string())).transpose()?;
|
||||
Ok(SolidHistoryLoft {
|
||||
base: SolidHistoryNodeBase::new(1), operation_major: 1,
|
||||
cross_sections, guides,
|
||||
parameters: Some(SolidHistoryLoftParameters {
|
||||
path_entity, normals: options.normals,
|
||||
start_draft_angle: options.start_draft_angle, end_draft_angle: options.end_draft_angle,
|
||||
start_magnitude: options.start_magnitude, end_magnitude: options.end_magnitude,
|
||||
start_continuity: options.start_continuity, end_continuity: options.end_continuity,
|
||||
start_bulge: options.start_bulge, end_bulge: options.end_bulge,
|
||||
closed: options.closed, periodic: options.periodic, surface, align_direction: options.align_direction, section_counts,
|
||||
}),
|
||||
..SolidHistoryLoft::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_body(
|
||||
sections: &[LoftSectionSelection], guides: &[Handle], path: Option<Handle>,
|
||||
available: &[(Handle, EntityType)], mode: ExtrudeMode, options: LoftOptions,
|
||||
) -> Result<Body, String> {
|
||||
cadkernel::acis::rebuild_loft_with_options(&record(sections, guides, path, available, mode, options)?)
|
||||
}
|
||||
|
||||
pub fn surface_entity(record: &SolidHistoryLoft) -> EntityType {
|
||||
let settings = record.parameters.clone().unwrap_or_else(|| SolidHistoryLoftParameters {
|
||||
normals: 0, ..Default::default()
|
||||
});
|
||||
let mut surface = Surface::new(SurfaceKind::Lofted);
|
||||
surface.surface_data = SurfaceData::Lofted {
|
||||
loft_transform: record.base.transform,
|
||||
cross_section_entities: record.cross_sections.clone(), guide_entities: record.guides.clone(),
|
||||
path_entity: settings.path_entity,
|
||||
plane_normal_lofting_type: settings.normals,
|
||||
start_draft_angle: settings.start_draft_angle, end_draft_angle: settings.end_draft_angle,
|
||||
start_draft_magnitude: settings.start_magnitude, end_draft_magnitude: settings.end_magnitude,
|
||||
arc_length_parameterization: true, no_twist: true, align_direction: settings.align_direction,
|
||||
simple_surfaces: true, closed_surfaces: settings.closed, solid: false,
|
||||
ruled_surface: settings.normals == 0, virtual_guide: false,
|
||||
cross_sections: Vec::new(), guide_curves: Vec::new(), path_curve: None,
|
||||
};
|
||||
EntityType::Surface(surface)
|
||||
}
|
||||
@@ -11,6 +11,7 @@ pub mod mesh_model;
|
||||
pub mod solid_model;
|
||||
pub mod solid_history;
|
||||
pub mod sweep_model;
|
||||
pub mod loft_command_model;
|
||||
mod sweep_command_model;
|
||||
pub mod visual_style_model;
|
||||
pub mod object;
|
||||
@@ -1,7 +1,7 @@
|
||||
use acadrust::entities::{EmbeddedEntity, Solid3D};
|
||||
use acadrust::objects::{
|
||||
DynamicBlockData, ObjectType, SolidHistoryBox, SolidHistoryBrep, SolidHistoryCone,
|
||||
SolidHistoryCylinder, SolidHistoryLoft, SolidHistoryNodeBase, SolidHistoryOperation,
|
||||
SolidHistoryCylinder, SolidHistoryLoft, SolidHistoryLoftParameters, SolidHistoryNodeBase, SolidHistoryOperation,
|
||||
SolidHistoryPyramid, SolidHistoryRevolve, SolidHistorySphere, SolidHistorySweep,
|
||||
SolidHistoryTorus,
|
||||
};
|
||||
@@ -76,6 +76,15 @@ pub const PROP_AXIS_DIRECTION_X: &str = "solid_history_axis_direction_x";
|
||||
pub const PROP_AXIS_DIRECTION_Y: &str = "solid_history_axis_direction_y";
|
||||
pub const PROP_AXIS_DIRECTION_Z: &str = "solid_history_axis_direction_z";
|
||||
pub const PROP_PYRAMID_TYPE: &str = "solid_history_pyramid_type";
|
||||
pub const PROP_LOFT_TYPE: &str = "solid_history_loft_type";
|
||||
pub const PROP_LOFT_SECTION_COUNT: &str = "solid_history_loft_section_count";
|
||||
pub const PROP_LOFT_NORMALS: &str = "solid_history_loft_normals";
|
||||
pub const PROP_LOFT_START_DRAFT_ANGLE: &str = "solid_history_loft_start_draft_angle";
|
||||
pub const PROP_LOFT_END_DRAFT_ANGLE: &str = "solid_history_loft_end_draft_angle";
|
||||
pub const PROP_LOFT_START_MAGNITUDE: &str = "solid_history_loft_start_magnitude";
|
||||
pub const PROP_LOFT_END_MAGNITUDE: &str = "solid_history_loft_end_magnitude";
|
||||
pub const PROP_LOFT_CLOSED: &str = "solid_history_loft_closed";
|
||||
pub const PROP_LOFT_PERIODIC: &str = "solid_history_loft_periodic";
|
||||
pub const PROP_HISTORY: &str = "solid_history_record";
|
||||
pub const PROP_SHOW_HISTORY: &str = "solid_history_show";
|
||||
|
||||
@@ -195,6 +204,7 @@ pub fn has_specialized_primitive_properties(
|
||||
| SolidHistoryOperation::Torus(_)
|
||||
| SolidHistoryOperation::Pyramid(_)
|
||||
| SolidHistoryOperation::Sweep(_)
|
||||
| SolidHistoryOperation::Loft(_)
|
||||
| SolidHistoryOperation::Extrusion(_)
|
||||
| SolidHistoryOperation::Revolve(_)
|
||||
)
|
||||
@@ -519,6 +529,161 @@ fn sweep_properties(
|
||||
]
|
||||
}
|
||||
|
||||
const LOFT_NORMAL_CHOICES: [&str; 7] = [
|
||||
"Ruled",
|
||||
"Smooth",
|
||||
"First normal",
|
||||
"Last normal",
|
||||
"Ends normal",
|
||||
"All normal",
|
||||
"Use draft angles",
|
||||
];
|
||||
|
||||
fn loft_parameters(value: &SolidHistoryLoft) -> SolidHistoryLoftParameters {
|
||||
value.parameters.clone().unwrap_or_else(|| SolidHistoryLoftParameters {
|
||||
// Older history predates the options extension and rebuilds as ruled.
|
||||
// Displaying or editing it must not silently change it to smooth.
|
||||
normals: 0,
|
||||
..SolidHistoryLoftParameters::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn loft_section_count(value: &SolidHistoryLoft) -> usize {
|
||||
value.parameters.as_ref()
|
||||
.filter(|parameters| !parameters.section_counts.is_empty())
|
||||
.map_or(value.cross_sections.len(), |parameters| parameters.section_counts.len())
|
||||
}
|
||||
|
||||
pub fn loft_closed_editable(value: &SolidHistoryLoft) -> bool {
|
||||
loft_section_count(value) >= 3
|
||||
&& !value.cross_sections.iter().any(|section| matches!(section, EmbeddedEntity::Point(_)))
|
||||
}
|
||||
|
||||
fn loft_properties(
|
||||
document: &acadrust::CadDocument,
|
||||
handle: acadrust::Handle,
|
||||
value: &SolidHistoryLoft,
|
||||
) -> Vec<PropSection> {
|
||||
let parameters = loft_parameters(value);
|
||||
let kind = if parameters.path_entity.is_some() {
|
||||
t!("Loft with path").into_owned()
|
||||
} else if !value.guides.is_empty() {
|
||||
t!("Loft with guides").into_owned()
|
||||
} else {
|
||||
t!("Loft with cross sections only").into_owned()
|
||||
};
|
||||
let mut geometry = vec![
|
||||
Property {
|
||||
label: t!("Solid type").into_owned(),
|
||||
field: PROP_LOFT_TYPE,
|
||||
value: PropValue::ReadOnly(kind),
|
||||
},
|
||||
Property {
|
||||
label: t!("Number of Cross sections").into_owned(),
|
||||
field: PROP_LOFT_SECTION_COUNT,
|
||||
value: PropValue::ReadOnly(loft_section_count(value).to_string()),
|
||||
},
|
||||
Property {
|
||||
label: t!("Surface Normals").into_owned(),
|
||||
field: PROP_LOFT_NORMALS,
|
||||
value: PropValue::Choice {
|
||||
selected: LOFT_NORMAL_CHOICES.get(parameters.normals as usize)
|
||||
.map_or_else(|| parameters.normals.to_string(), |name| (*name).to_string()),
|
||||
options: LOFT_NORMAL_CHOICES.iter().map(|name| (*name).to_string()).collect(),
|
||||
},
|
||||
},
|
||||
];
|
||||
if parameters.normals == 6 {
|
||||
geometry.extend([
|
||||
Property {
|
||||
label: t!("Start draft angle").into_owned(),
|
||||
field: PROP_LOFT_START_DRAFT_ANGLE,
|
||||
value: PropValue::EditText(crate::entities::common::format_angle(parameters.start_draft_angle)),
|
||||
},
|
||||
Property {
|
||||
label: t!("End draft angle").into_owned(),
|
||||
field: PROP_LOFT_END_DRAFT_ANGLE,
|
||||
value: PropValue::EditText(crate::entities::common::format_angle(parameters.end_draft_angle)),
|
||||
},
|
||||
Property {
|
||||
label: t!("Start magnitude").into_owned(),
|
||||
field: PROP_LOFT_START_MAGNITUDE,
|
||||
value: PropValue::EditText(parameters.start_magnitude.to_string()),
|
||||
},
|
||||
Property {
|
||||
label: t!("End magnitude").into_owned(),
|
||||
field: PROP_LOFT_END_MAGNITUDE,
|
||||
value: PropValue::EditText(parameters.end_magnitude.to_string()),
|
||||
},
|
||||
]);
|
||||
}
|
||||
let (record_history, object_show_history, show_history_mode) =
|
||||
history_flags(document, handle).unwrap_or((false, false, 1));
|
||||
let (show_history, show_history_editable) =
|
||||
displayed_history_state(object_show_history, show_history_mode);
|
||||
let show_value = if show_history { "Yes" } else { "No" }.to_string();
|
||||
let closed_value = if parameters.closed { "Yes" } else { "No" }.to_string();
|
||||
let mut sections = vec![
|
||||
PropSection {
|
||||
title: t!("Geometry").into_owned(),
|
||||
props: geometry,
|
||||
},
|
||||
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!["Record".to_string(), "None".to_string()],
|
||||
},
|
||||
},
|
||||
Property {
|
||||
label: t!("Show History").into_owned(),
|
||||
field: PROP_SHOW_HISTORY,
|
||||
value: if show_history_editable {
|
||||
PropValue::Choice {
|
||||
selected: show_value,
|
||||
options: vec!["Yes".to_string(), "No".to_string()],
|
||||
}
|
||||
} else {
|
||||
PropValue::ReadOnly(show_value)
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
PropSection {
|
||||
title: t!("Misc").into_owned(),
|
||||
props: vec![
|
||||
Property {
|
||||
label: t!("Closed").into_owned(),
|
||||
field: PROP_LOFT_CLOSED,
|
||||
value: if loft_closed_editable(value) {
|
||||
PropValue::Choice {
|
||||
selected: closed_value,
|
||||
options: vec!["Yes".to_string(), "No".to_string()],
|
||||
}
|
||||
} else {
|
||||
PropValue::ReadOnly(closed_value)
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
if parameters.closed {
|
||||
sections[2].props.push(Property {
|
||||
label: t!("Periodic").into_owned(),
|
||||
field: PROP_LOFT_PERIODIC,
|
||||
value: PropValue::Choice {
|
||||
selected: if parameters.periodic { "Yes" } else { "No" }.to_string(),
|
||||
options: vec!["Yes".to_string(), "No".to_string()],
|
||||
},
|
||||
});
|
||||
}
|
||||
sections
|
||||
}
|
||||
|
||||
fn sweep_path_length(value: &SolidHistorySweep) -> Option<f64> {
|
||||
use acadrust::entities::EmbeddedEntity;
|
||||
use acadrust::EntityType;
|
||||
@@ -1209,6 +1374,7 @@ pub fn primitive_properties(
|
||||
SolidHistoryOperation::Pyramid(value) => pyramid_properties(document, handle, value),
|
||||
SolidHistoryOperation::Torus(value) => torus_properties(document, handle, value),
|
||||
SolidHistoryOperation::Sweep(value) => sweep_properties(document, handle, value),
|
||||
SolidHistoryOperation::Loft(value) => loft_properties(document, handle, value),
|
||||
SolidHistoryOperation::Extrusion(value) => {
|
||||
extrusion_properties(document, handle, value)
|
||||
}
|
||||
@@ -1253,6 +1419,13 @@ pub fn is_primitive_property(field: &str) -> bool {
|
||||
| PROP_AXIS_DIRECTION_Y
|
||||
| PROP_AXIS_DIRECTION_Z
|
||||
| PROP_PYRAMID_TYPE
|
||||
| PROP_LOFT_NORMALS
|
||||
| PROP_LOFT_START_DRAFT_ANGLE
|
||||
| PROP_LOFT_END_DRAFT_ANGLE
|
||||
| PROP_LOFT_START_MAGNITUDE
|
||||
| PROP_LOFT_END_MAGNITUDE
|
||||
| PROP_LOFT_CLOSED
|
||||
| PROP_LOFT_PERIODIC
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1260,8 +1433,13 @@ pub fn is_history_choice(field: &str) -> bool {
|
||||
matches!(field, PROP_HISTORY | PROP_SHOW_HISTORY)
|
||||
}
|
||||
|
||||
pub fn is_loft_geometry_choice(field: &str) -> bool {
|
||||
matches!(field, PROP_LOFT_NORMALS | PROP_LOFT_CLOSED | PROP_LOFT_PERIODIC)
|
||||
}
|
||||
|
||||
pub fn is_specialized_property(field: &str) -> bool {
|
||||
matches!(field, "solid_history_type" | PROP_BANK | PROP_SWEEP_LENGTH)
|
||||
matches!(field, "solid_history_type" | PROP_BANK | PROP_SWEEP_LENGTH
|
||||
| PROP_LOFT_TYPE | PROP_LOFT_SECTION_COUNT)
|
||||
|| is_primitive_property(field)
|
||||
|| is_history_choice(field)
|
||||
}
|
||||
@@ -1688,6 +1866,85 @@ fn apply_sweep_geometry_property(
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_loft_geometry_property(
|
||||
value: &mut SolidHistoryLoft,
|
||||
field: &str,
|
||||
text: &str,
|
||||
) -> Option<bool> {
|
||||
let current = loft_parameters(value);
|
||||
let mut parameters = current.clone();
|
||||
match field {
|
||||
PROP_LOFT_NORMALS => {
|
||||
let Some(index) = LOFT_NORMAL_CHOICES.iter()
|
||||
.position(|name| name.eq_ignore_ascii_case(text.trim()))
|
||||
else {
|
||||
return Some(false);
|
||||
};
|
||||
parameters.normals = index as i32;
|
||||
}
|
||||
PROP_LOFT_START_DRAFT_ANGLE | PROP_LOFT_END_DRAFT_ANGLE => {
|
||||
if parameters.normals != 6 {
|
||||
return Some(false);
|
||||
}
|
||||
let Some(angle) = crate::entities::common::parse_angle(text)
|
||||
.filter(|angle| angle.is_finite() && (0.0..=std::f64::consts::PI).contains(angle))
|
||||
else {
|
||||
return Some(false);
|
||||
};
|
||||
if field == PROP_LOFT_START_DRAFT_ANGLE {
|
||||
parameters.start_draft_angle = angle;
|
||||
} else {
|
||||
parameters.end_draft_angle = angle;
|
||||
}
|
||||
}
|
||||
PROP_LOFT_START_MAGNITUDE | PROP_LOFT_END_MAGNITUDE => {
|
||||
if parameters.normals != 6 {
|
||||
return Some(false);
|
||||
}
|
||||
let Some(magnitude) = text.trim().replace(',', ".").parse::<f64>().ok()
|
||||
.filter(|magnitude| magnitude.is_finite() && *magnitude >= 0.0)
|
||||
else {
|
||||
return Some(false);
|
||||
};
|
||||
if field == PROP_LOFT_START_MAGNITUDE {
|
||||
parameters.start_magnitude = magnitude;
|
||||
} else {
|
||||
parameters.end_magnitude = magnitude;
|
||||
}
|
||||
}
|
||||
PROP_LOFT_CLOSED => {
|
||||
if !loft_closed_editable(value) {
|
||||
return Some(false);
|
||||
}
|
||||
parameters.closed = if text.trim().eq_ignore_ascii_case("Yes") {
|
||||
true
|
||||
} else if text.trim().eq_ignore_ascii_case("No") {
|
||||
false
|
||||
} else {
|
||||
return Some(false);
|
||||
};
|
||||
}
|
||||
PROP_LOFT_PERIODIC => {
|
||||
if !parameters.closed {
|
||||
return Some(false);
|
||||
}
|
||||
parameters.periodic = if text.trim().eq_ignore_ascii_case("Yes") {
|
||||
true
|
||||
} else if text.trim().eq_ignore_ascii_case("No") {
|
||||
false
|
||||
} else {
|
||||
return Some(false);
|
||||
};
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
if parameters == current {
|
||||
return Some(false);
|
||||
}
|
||||
value.parameters = Some(parameters);
|
||||
Some(true)
|
||||
}
|
||||
|
||||
fn apply_torus_position_property(
|
||||
value: &mut SolidHistoryTorus,
|
||||
field: &str,
|
||||
@@ -1881,6 +2138,11 @@ pub fn apply_primitive_property(
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
if let SolidHistoryOperation::Loft(loft_value) = operation {
|
||||
if let Some(applied) = apply_loft_geometry_property(loft_value, field, value) {
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
if let SolidHistoryOperation::Extrusion(extrusion_value) = operation {
|
||||
if let Some(applied) =
|
||||
apply_extrusion_geometry_property(extrusion_value, field, value)
|
||||
@@ -2188,6 +2450,51 @@ fn embedded_entity(value: &EmbeddedEntity) -> Option<EntityType> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Visible LOFT construction curves, owned by the parent display entity.
|
||||
/// Copies are transformed to WCS and never inserted into the document.
|
||||
pub fn loft_visible_history_entities(
|
||||
document: &acadrust::CadDocument,
|
||||
handle: acadrust::Handle,
|
||||
) -> Vec<EntityType> {
|
||||
let Some((_, object_show_history, show_history_mode)) = history_flags(document, handle) else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !displayed_history_state(object_show_history, show_history_mode).0 {
|
||||
return Vec::new();
|
||||
}
|
||||
let Some(SolidHistoryOperation::Loft(value)) = document.solid_history_operation(handle) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some(parent) = document.get_entity(handle) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some(transform) = matrix(value.base.transform) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let columns = transform.to_cols_array_2d();
|
||||
let affine = acadrust::types::Transform::from_matrix(
|
||||
acadrust::types::Matrix4 {
|
||||
m: std::array::from_fn(|row| std::array::from_fn(|column| columns[column][row])),
|
||||
},
|
||||
);
|
||||
value.cross_sections.iter()
|
||||
.chain(&value.guides)
|
||||
.chain(value.parameters.as_ref().and_then(|parameters| parameters.path_entity.as_ref()))
|
||||
.filter_map(|source| {
|
||||
let mut entity = embedded_entity(source)?;
|
||||
entity.apply_transform(&affine);
|
||||
// Construction sources belong to the visible parent's layer and
|
||||
// selection identity, not a deleted source or hidden source layer.
|
||||
let common = entity.common_mut();
|
||||
common.handle = handle;
|
||||
common.owner_handle = parent.common().owner_handle;
|
||||
common.layer = parent.common().layer.clone();
|
||||
common.invisible = parent.common().invisible;
|
||||
Some(entity)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn into_embedded_entity(value: EntityType) -> Option<EmbeddedEntity> {
|
||||
Some(match value {
|
||||
EntityType::Point(value) => EmbeddedEntity::Point(value),
|
||||
|
||||
Reference in new issue
Block a user