cad-editor/src/entities/traits.rs

202 lines
7.4 KiB
Rust
Raw Normal View History

2026-03-22 14:56:27 +03:00
use acadrust::{CadDocument, EntityType};
use crate::command::EntityTransform;
use crate::scene::acad_to_truck::TruckEntity;
use crate::scene::object::{GripApply, GripDef, PropSection};
use crate::scene::tess_util::FallbackGeometry;
2026-03-22 14:56:27 +03:00
pub trait TruckConvertible {
fn to_truck(&self, document: &CadDocument) -> Option<TruckEntity>;
}
/// Fallback geometry for entities not routed through the truck topology
/// pipeline (Viewport, Insert, Hatch outline, Ole2Frame). Returns
/// world-offset-relative `f32` points + snap/key vertices the
/// dispatcher wraps into a `WireModel`.
pub trait FallbackTess {
fn fallback_geometry(&self, world_offset: [f64; 3]) -> FallbackGeometry;
}
2026-03-22 14:56:27 +03:00
pub trait Grippable {
fn grips(&self) -> Vec<GripDef>;
fn apply_grip(&mut self, grip_id: usize, apply: GripApply);
}
pub trait PropertyEditable {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection;
fn apply_geom_prop(&mut self, field: &str, value: &str);
}
pub trait Transformable {
fn apply_transform(&mut self, t: &EntityTransform);
}
/// Inquiry-time mass / area / perimeter properties for entities whose
/// 2D footprint has a meaningful area or perimeter (Circle, Arc, Line,
/// LwPolyline, Ellipse). Entities outside this set get `None` via the
/// dispatcher.
#[derive(Clone, Copy, Debug)]
pub struct MassProps {
pub area: f64,
pub perimeter: f64,
pub cx: f64,
pub cy: f64,
}
pub trait MassPropsCalc {
fn mass_props(&self) -> MassProps;
}
/// Read / replace the visible string of text-like entities (Text, MText,
/// AttributeDefinition, AttributeEntity). `replace` rewrites every
/// occurrence of `search` with `rep`.
pub trait TextContent {
fn text_content(&self) -> Option<String>;
fn replace_text(&mut self, search: &str, rep: &str);
}
2026-03-22 14:56:27 +03:00
pub trait EntityTypeOps {
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity>;
fn grips(&self) -> Vec<GripDef>;
fn geometry_properties(&self, text_style_names: &[String]) -> Option<PropSection>;
fn apply_geom_prop(&mut self, field: &str, value: &str);
fn apply_grip(&mut self, grip_id: usize, apply: GripApply);
fn apply_transform(&mut self, t: &EntityTransform);
fn mass_props(&self) -> Option<MassProps>;
fn text_content(&self) -> Option<String>;
fn replace_text(&mut self, search: &str, rep: &str);
2026-03-22 14:56:27 +03:00
}
/// Per-dispatch-function entity-variant lists. Adding a new entity that
/// participates in a dispatch = adding one identifier to one list here
/// (instead of one full match arm to each of five `match self` blocks).
///
/// `dispatch!` expands `EntityType::$Variant(e) => $body` for each name.
macro_rules! dispatch {
($self:expr, |$e:ident| $body:expr, [$($variant:ident),* $(,)?], _ => $default:expr $(,)?) => {
match $self {
$(EntityType::$variant($e) => $body,)*
_ => $default,
}
};
}
2026-03-22 14:56:27 +03:00
impl EntityTypeOps for EntityType {
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity> {
dispatch!(self,
|e| TruckConvertible::to_truck(e, document),
[
Point, Line, Circle, Arc, Ellipse, Spline, LwPolyline,
Polyline, Polyline2D, Polyline3D, Ray, XLine, RasterImage,
Wipeout, AttributeDefinition, AttributeEntity, MLine,
Tolerance, Solid, Face3D, PolygonMesh, PolyfaceMesh, Mesh,
Table, Text, MText, Leader, MultiLeader, Underlay, Shape,
Ole2Frame,
],
2026-03-22 14:56:27 +03:00
_ => None,
)
2026-03-22 14:56:27 +03:00
}
fn grips(&self) -> Vec<GripDef> {
dispatch!(self,
|e| Grippable::grips(e),
[
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
Polyline3D, Ray, XLine, RasterImage, Wipeout,
AttributeDefinition, AttributeEntity, MLine, Tolerance,
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText,
Viewport, Insert, Leader, MultiLeader, Dimension, Hatch,
Underlay, Shape, Ole2Frame,
],
2026-03-22 14:56:27 +03:00
_ => vec![],
)
2026-03-22 14:56:27 +03:00
}
fn geometry_properties(&self, text_style_names: &[String]) -> Option<PropSection> {
dispatch!(self,
|e| Some(PropertyEditable::geometry_properties(e, text_style_names)),
[
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
Polyline3D, Ray, XLine, RasterImage, Wipeout,
AttributeDefinition, AttributeEntity, MLine, Tolerance,
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
PolyfaceMesh, Mesh, Table, Hatch, Point, Spline, Text, MText,
Viewport, Insert, Dimension, Leader, MultiLeader, Underlay,
Shape, Ole2Frame,
],
2026-03-22 14:56:27 +03:00
_ => None,
)
2026-03-22 14:56:27 +03:00
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
dispatch!(self,
|e| PropertyEditable::apply_geom_prop(e, field, value),
[
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
Polyline3D, Ray, XLine, RasterImage, Wipeout,
AttributeDefinition, AttributeEntity, MLine, Tolerance,
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
PolyfaceMesh, Mesh, Table, Hatch, Point, Spline, Text, MText,
Viewport, Insert, Dimension, Leader, MultiLeader, Underlay,
Shape, Ole2Frame,
],
_ => {},
)
2026-03-22 14:56:27 +03:00
}
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
dispatch!(self,
|e| Grippable::apply_grip(e, grip_id, apply),
[
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
Polyline3D, Ray, XLine, RasterImage, Wipeout,
AttributeDefinition, AttributeEntity, MLine, Tolerance,
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText,
Viewport, Insert, Leader, MultiLeader, Dimension, Hatch,
Underlay, Shape, Ole2Frame,
],
_ => {},
)
2026-03-22 14:56:27 +03:00
}
fn apply_transform(&mut self, t: &EntityTransform) {
dispatch!(self,
|e| Transformable::apply_transform(e, t),
[
Arc, Circle, Ellipse, Hatch, Insert, Line, LwPolyline,
Polyline, Polyline2D, Polyline3D, Ray, XLine, RasterImage,
Wipeout, AttributeDefinition, AttributeEntity, MLine,
Tolerance, Solid, Face3D, PolygonMesh, PolyfaceMesh, Mesh,
Table, MText, Point, Spline, Text, Viewport, Dimension,
Leader, MultiLeader, Underlay, Shape, Ole2Frame,
],
_ => {},
)
2026-03-22 14:56:27 +03:00
}
fn mass_props(&self) -> Option<MassProps> {
dispatch!(self,
|e| Some(MassPropsCalc::mass_props(e)),
[Circle, Arc, Line, LwPolyline, Ellipse],
_ => None,
)
}
fn text_content(&self) -> Option<String> {
dispatch!(self,
|e| TextContent::text_content(e),
[Text, MText, AttributeDefinition, AttributeEntity],
_ => None,
)
}
fn replace_text(&mut self, search: &str, rep: &str) {
dispatch!(self,
|e| TextContent::replace_text(e, search, rep),
[Text, MText, AttributeDefinition, AttributeEntity],
_ => {},
)
}
2026-03-22 14:56:27 +03:00
}