Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals (pixel placeholder); Wipeout renders border or polygon clip boundary; both support insertion_point grip, brightness/contrast/fade properties, clipping toggle, and mirror transform (u/v vectors reflected) - attribute.rs: AttributeDefinition renders default_value (or [TAG] if empty) as font-tessellated text; AttributeEntity renders the live value; both support insertion grip, position/height/rotation properties, and transform operations - mod.rs + traits.rs: wire up all four new entity types through the full dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop, apply_grip, apply_transform) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4a93fc4949
commit
27c0e74468
4 changed files with 607 additions and 0 deletions
219
src/entities/attribute.rs
Normal file
219
src/entities/attribute.rs
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
use acadrust::entities::{AttributeDefinition, AttributeEntity};
|
||||
use glam::Vec3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::text_support::resolve_text_style;
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::scene::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::wire_model::SnapHint;
|
||||
use crate::scene::{cxf, transform};
|
||||
|
||||
// ── AttributeDefinition ───────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for AttributeDefinition {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
let snap_pt = Vec3::new(
|
||||
self.insertion_point.x as f32,
|
||||
self.insertion_point.y as f32,
|
||||
self.insertion_point.z as f32,
|
||||
);
|
||||
let resolved = resolve_text_style(&self.text_style, document);
|
||||
let display = if self.default_value.is_empty() {
|
||||
format!("[{}]", self.tag)
|
||||
} else {
|
||||
self.default_value.clone()
|
||||
};
|
||||
let wf = (self.width_factor as f32).max(0.01);
|
||||
let strokes = cxf::tessellate_text_ex(
|
||||
[self.insertion_point.x as f32, self.insertion_point.y as f32],
|
||||
self.height as f32,
|
||||
self.rotation as f32,
|
||||
wf * resolved.width_factor.max(0.01),
|
||||
self.oblique_angle as f32 + resolved.oblique_angle,
|
||||
&resolved.font_name,
|
||||
&display,
|
||||
);
|
||||
Some(TruckEntity {
|
||||
object: TruckObject::Text(strokes),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Grippable for AttributeDefinition {
|
||||
fn grips(&self) -> Vec<GripDef> {
|
||||
vec![square_grip(
|
||||
0,
|
||||
Vec3::new(
|
||||
self.insertion_point.x as f32,
|
||||
self.insertion_point.y as f32,
|
||||
self.insertion_point.z as f32,
|
||||
),
|
||||
)]
|
||||
}
|
||||
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
||||
if grip_id == 0 {
|
||||
match apply {
|
||||
GripApply::Translate(d) => {
|
||||
self.insertion_point.x += d.x as f64;
|
||||
self.insertion_point.y += d.y as f64;
|
||||
self.insertion_point.z += d.z as f64;
|
||||
}
|
||||
GripApply::Absolute(p) => {
|
||||
self.insertion_point.x = p.x as f64;
|
||||
self.insertion_point.y = p.y as f64;
|
||||
self.insertion_point.z = p.z as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for AttributeDefinition {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
ro("Tag", "att_tag", self.tag.clone()),
|
||||
ro("Prompt", "att_prompt", self.prompt.clone()),
|
||||
edit("Default", "att_default", 0.0), // String — handled as text
|
||||
edit("Insert X", "att_ix", self.insertion_point.x),
|
||||
edit("Insert Y", "att_iy", self.insertion_point.y),
|
||||
edit("Insert Z", "att_iz", self.insertion_point.z),
|
||||
edit("Height", "att_h", self.height),
|
||||
edit("Rotation", "att_rot", self.rotation.to_degrees()),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
||||
let Ok(v) = value.trim().parse::<f64>() else { return };
|
||||
match field {
|
||||
"att_ix" => self.insertion_point.x = v,
|
||||
"att_iy" => self.insertion_point.y = v,
|
||||
"att_iz" => self.insertion_point.z = v,
|
||||
"att_h" if v > 0.0 => self.height = v,
|
||||
"att_rot" => self.rotation = v.to_radians(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transformable for AttributeDefinition {
|
||||
fn apply_transform(&mut self, t: &EntityTransform) {
|
||||
transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
||||
transform::reflect_xy_point(
|
||||
&mut entity.insertion_point.x,
|
||||
&mut entity.insertion_point.y,
|
||||
p1,
|
||||
p2,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ── AttributeEntity ───────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for AttributeEntity {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
let snap_pt = Vec3::new(
|
||||
self.insertion_point.x as f32,
|
||||
self.insertion_point.y as f32,
|
||||
self.insertion_point.z as f32,
|
||||
);
|
||||
let resolved = resolve_text_style(&self.text_style, document);
|
||||
let wf = (self.width_factor as f32).max(0.01);
|
||||
let strokes = cxf::tessellate_text_ex(
|
||||
[self.insertion_point.x as f32, self.insertion_point.y as f32],
|
||||
self.height as f32,
|
||||
self.rotation as f32,
|
||||
wf * resolved.width_factor.max(0.01),
|
||||
self.oblique_angle as f32 + resolved.oblique_angle,
|
||||
&resolved.font_name,
|
||||
&self.value,
|
||||
);
|
||||
Some(TruckEntity {
|
||||
object: TruckObject::Text(strokes),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Grippable for AttributeEntity {
|
||||
fn grips(&self) -> Vec<GripDef> {
|
||||
vec![square_grip(
|
||||
0,
|
||||
Vec3::new(
|
||||
self.insertion_point.x as f32,
|
||||
self.insertion_point.y as f32,
|
||||
self.insertion_point.z as f32,
|
||||
),
|
||||
)]
|
||||
}
|
||||
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
||||
if grip_id == 0 {
|
||||
match apply {
|
||||
GripApply::Translate(d) => {
|
||||
self.insertion_point.x += d.x as f64;
|
||||
self.insertion_point.y += d.y as f64;
|
||||
self.insertion_point.z += d.z as f64;
|
||||
}
|
||||
GripApply::Absolute(p) => {
|
||||
self.insertion_point.x = p.x as f64;
|
||||
self.insertion_point.y = p.y as f64;
|
||||
self.insertion_point.z = p.z as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for AttributeEntity {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
ro("Tag", "atte_tag", self.tag.clone()),
|
||||
ro("Value", "atte_val", self.value.clone()),
|
||||
edit("Insert X", "atte_ix", self.insertion_point.x),
|
||||
edit("Insert Y", "atte_iy", self.insertion_point.y),
|
||||
edit("Insert Z", "atte_iz", self.insertion_point.z),
|
||||
edit("Height", "atte_h", self.height),
|
||||
edit("Rotation", "atte_rot", self.rotation.to_degrees()),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
||||
let Ok(v) = value.trim().parse::<f64>() else { return };
|
||||
match field {
|
||||
"atte_ix" => self.insertion_point.x = v,
|
||||
"atte_iy" => self.insertion_point.y = v,
|
||||
"atte_iz" => self.insertion_point.z = v,
|
||||
"atte_h" if v > 0.0 => self.height = v,
|
||||
"atte_rot" => self.rotation = v.to_radians(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transformable for AttributeEntity {
|
||||
fn apply_transform(&mut self, t: &EntityTransform) {
|
||||
transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
||||
transform::reflect_xy_point(
|
||||
&mut entity.insertion_point.x,
|
||||
&mut entity.insertion_point.y,
|
||||
p1,
|
||||
p2,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod arc;
|
||||
pub mod attribute;
|
||||
pub mod circle;
|
||||
mod common;
|
||||
pub mod dimension;
|
||||
|
|
@ -12,6 +13,7 @@ pub mod lwpolyline;
|
|||
pub mod mtext;
|
||||
pub mod point;
|
||||
pub mod polyline;
|
||||
pub mod raster_image;
|
||||
pub mod ray;
|
||||
pub mod spline;
|
||||
pub mod text;
|
||||
|
|
|
|||
350
src/entities/raster_image.rs
Normal file
350
src/entities/raster_image.rs
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
use acadrust::entities::{RasterImage, Wipeout};
|
||||
use glam::Vec3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{diamond_grip, edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::scene::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
|
||||
// ── Shared geometry helpers ───────────────────────────────────────────────────
|
||||
|
||||
/// Compute the four world-space corners of an image/wipeout from its
|
||||
/// insertion_point, u_vector, v_vector and pixel size.
|
||||
///
|
||||
/// Returns (p0, p1, p2, p3) in counter-clockwise order:
|
||||
/// p0 = origin
|
||||
/// p1 = origin + U*W
|
||||
/// p2 = origin + U*W + V*H
|
||||
/// p3 = origin + V*H
|
||||
fn image_corners(
|
||||
origin: &acadrust::types::Vector3,
|
||||
u: &acadrust::types::Vector3,
|
||||
v: &acadrust::types::Vector3,
|
||||
w: f64,
|
||||
h: f64,
|
||||
) -> [[f32; 3]; 4] {
|
||||
let ox = origin.x as f32;
|
||||
let oy = origin.y as f32;
|
||||
let oz = origin.z as f32;
|
||||
let ux = (u.x * w) as f32;
|
||||
let uy = (u.y * w) as f32;
|
||||
let uz = (u.z * w) as f32;
|
||||
let vx = (v.x * h) as f32;
|
||||
let vy = (v.y * h) as f32;
|
||||
let vz = (v.z * h) as f32;
|
||||
|
||||
[
|
||||
[ox, oy, oz],
|
||||
[ox + ux, oy + uy, oz + uz],
|
||||
[ox + ux + vx, oy + uy + vy, oz + uz + vz],
|
||||
[ox + vx, oy + vy, oz + vz],
|
||||
]
|
||||
}
|
||||
|
||||
/// Rectangle border + X diagonals — used as a placeholder for images.
|
||||
fn image_wire(corners: [[f32; 3]; 4], with_x: bool) -> Vec<[f32; 3]> {
|
||||
let [p0, p1, p2, p3] = corners;
|
||||
let mut pts = vec![p0, p1, p2, p3, p0];
|
||||
if with_x {
|
||||
pts.push([f32::NAN; 3]);
|
||||
pts.push(p0);
|
||||
pts.push(p2);
|
||||
pts.push([f32::NAN; 3]);
|
||||
pts.push(p1);
|
||||
pts.push(p3);
|
||||
}
|
||||
pts
|
||||
}
|
||||
|
||||
fn reflect_vec3(
|
||||
vx: &mut f64,
|
||||
vy: &mut f64,
|
||||
ax: f64,
|
||||
ay: f64,
|
||||
len2: f64,
|
||||
) {
|
||||
let dot = *vx * ax + *vy * ay;
|
||||
*vx = 2.0 * dot * ax / len2 - *vx;
|
||||
*vy = 2.0 * dot * ay / len2 - *vy;
|
||||
}
|
||||
|
||||
// ── RasterImage ───────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for RasterImage {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
Some(TruckEntity {
|
||||
object: TruckObject::Lines(image_wire(corners, true)),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Grippable for RasterImage {
|
||||
fn grips(&self) -> Vec<GripDef> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
vec![
|
||||
square_grip(0, Vec3::from(corners[0])),
|
||||
diamond_grip(1, Vec3::from(corners[1])),
|
||||
diamond_grip(2, Vec3::from(corners[2])),
|
||||
diamond_grip(3, Vec3::from(corners[3])),
|
||||
]
|
||||
}
|
||||
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
||||
if grip_id == 0 {
|
||||
match apply {
|
||||
GripApply::Translate(d) => {
|
||||
self.insertion_point.x += d.x as f64;
|
||||
self.insertion_point.y += d.y as f64;
|
||||
self.insertion_point.z += d.z as f64;
|
||||
}
|
||||
GripApply::Absolute(p) => {
|
||||
self.insertion_point.x = p.x as f64;
|
||||
self.insertion_point.y = p.y as f64;
|
||||
self.insertion_point.z = p.z as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Corner grips 1-3 are display-only (resizing changes u/v vectors,
|
||||
// which requires careful normalization — deferred).
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for RasterImage {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
ro("File", "ri_file", self.file_path.clone()),
|
||||
edit("Insert X", "ri_ox", self.insertion_point.x),
|
||||
edit("Insert Y", "ri_oy", self.insertion_point.y),
|
||||
edit("Insert Z", "ri_oz", self.insertion_point.z),
|
||||
edit("Brightness", "ri_bright", self.brightness as f64),
|
||||
edit("Contrast", "ri_contrast", self.contrast as f64),
|
||||
edit("Fade", "ri_fade", self.fade as f64),
|
||||
Property {
|
||||
label: "Clipping".into(),
|
||||
field: "ri_clip",
|
||||
value: PropValue::BoolToggle {
|
||||
field: "ri_clip",
|
||||
value: self.clipping_enabled,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
||||
match field {
|
||||
"ri_clip" => {
|
||||
self.clipping_enabled =
|
||||
if value == "toggle" { !self.clipping_enabled } else { value == "true" };
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let Ok(v) = value.trim().parse::<f64>() else { return };
|
||||
match field {
|
||||
"ri_ox" => self.insertion_point.x = v,
|
||||
"ri_oy" => self.insertion_point.y = v,
|
||||
"ri_oz" => self.insertion_point.z = v,
|
||||
"ri_bright" => self.brightness = v.clamp(0.0, 100.0) as u8,
|
||||
"ri_contrast" => self.contrast = v.clamp(0.0, 100.0) as u8,
|
||||
"ri_fade" => self.fade = v.clamp(0.0, 100.0) as u8,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transformable for RasterImage {
|
||||
fn apply_transform(&mut self, t: &EntityTransform) {
|
||||
crate::scene::transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
||||
crate::scene::transform::reflect_xy_point(
|
||||
&mut entity.insertion_point.x,
|
||||
&mut entity.insertion_point.y,
|
||||
p1,
|
||||
p2,
|
||||
);
|
||||
let ax = (p2.x - p1.x) as f64;
|
||||
let ay = (p2.y - p1.y) as f64;
|
||||
let len2 = ax * ax + ay * ay;
|
||||
if len2 > 1e-12 {
|
||||
reflect_vec3(&mut entity.u_vector.x, &mut entity.u_vector.y, ax, ay, len2);
|
||||
reflect_vec3(&mut entity.v_vector.x, &mut entity.v_vector.y, ax, ay, len2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ── Wipeout ───────────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for Wipeout {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
|
||||
// If clipping is enabled and there's a polygon boundary, show that.
|
||||
let pts = if self.clipping_enabled
|
||||
&& self.clip_boundary_vertices.len() >= 3
|
||||
&& matches!(
|
||||
self.clip_type,
|
||||
acadrust::entities::WipeoutClipType::Polygonal
|
||||
)
|
||||
{
|
||||
// Convert pixel-space boundary vertices to world space:
|
||||
// world = insertion_point + u_vector * v.x * size.x + v_vector * v.y * size.y
|
||||
let ox = self.insertion_point.x as f32;
|
||||
let oy = self.insertion_point.y as f32;
|
||||
let oz = self.insertion_point.z as f32;
|
||||
let mut poly: Vec<[f32; 3]> = self
|
||||
.clip_boundary_vertices
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let wx = (self.u_vector.x * v.x * self.size.x
|
||||
+ self.v_vector.x * v.y * self.size.y) as f32;
|
||||
let wy = (self.u_vector.y * v.x * self.size.x
|
||||
+ self.v_vector.y * v.y * self.size.y) as f32;
|
||||
let wz = (self.u_vector.z * v.x * self.size.x
|
||||
+ self.v_vector.z * v.y * self.size.y) as f32;
|
||||
[ox + wx, oy + wy, oz + wz]
|
||||
})
|
||||
.collect();
|
||||
// Close the polygon.
|
||||
if let Some(&first) = poly.first() {
|
||||
poly.push(first);
|
||||
}
|
||||
poly
|
||||
} else {
|
||||
// Rectangular boundary — just the border, no diagonals (mask area).
|
||||
image_wire(corners, false)
|
||||
};
|
||||
|
||||
Some(TruckEntity {
|
||||
object: TruckObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Grippable for Wipeout {
|
||||
fn grips(&self) -> Vec<GripDef> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
vec![
|
||||
square_grip(0, Vec3::from(corners[0])),
|
||||
diamond_grip(1, Vec3::from(corners[1])),
|
||||
diamond_grip(2, Vec3::from(corners[2])),
|
||||
diamond_grip(3, Vec3::from(corners[3])),
|
||||
]
|
||||
}
|
||||
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
||||
if grip_id == 0 {
|
||||
match apply {
|
||||
GripApply::Translate(d) => {
|
||||
self.insertion_point.x += d.x as f64;
|
||||
self.insertion_point.y += d.y as f64;
|
||||
self.insertion_point.z += d.z as f64;
|
||||
}
|
||||
GripApply::Absolute(p) => {
|
||||
self.insertion_point.x = p.x as f64;
|
||||
self.insertion_point.y = p.y as f64;
|
||||
self.insertion_point.z = p.z as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for Wipeout {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
edit("Insert X", "wo_ox", self.insertion_point.x),
|
||||
edit("Insert Y", "wo_oy", self.insertion_point.y),
|
||||
edit("Insert Z", "wo_oz", self.insertion_point.z),
|
||||
edit("Brightness", "wo_bright", self.brightness as f64),
|
||||
edit("Contrast", "wo_contrast", self.contrast as f64),
|
||||
edit("Fade", "wo_fade", self.fade as f64),
|
||||
Property {
|
||||
label: "Clipping".into(),
|
||||
field: "wo_clip",
|
||||
value: PropValue::BoolToggle {
|
||||
field: "wo_clip",
|
||||
value: self.clipping_enabled,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
||||
match field {
|
||||
"wo_clip" => {
|
||||
self.clipping_enabled =
|
||||
if value == "toggle" { !self.clipping_enabled } else { value == "true" };
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let Ok(v) = value.trim().parse::<f64>() else { return };
|
||||
match field {
|
||||
"wo_ox" => self.insertion_point.x = v,
|
||||
"wo_oy" => self.insertion_point.y = v,
|
||||
"wo_oz" => self.insertion_point.z = v,
|
||||
"wo_bright" => self.brightness = v.clamp(0.0, 100.0) as u8,
|
||||
"wo_contrast" => self.contrast = v.clamp(0.0, 100.0) as u8,
|
||||
"wo_fade" => self.fade = v.clamp(0.0, 100.0) as u8,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transformable for Wipeout {
|
||||
fn apply_transform(&mut self, t: &EntityTransform) {
|
||||
crate::scene::transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
||||
crate::scene::transform::reflect_xy_point(
|
||||
&mut entity.insertion_point.x,
|
||||
&mut entity.insertion_point.y,
|
||||
p1,
|
||||
p2,
|
||||
);
|
||||
let ax = (p2.x - p1.x) as f64;
|
||||
let ay = (p2.y - p1.y) as f64;
|
||||
let len2 = ax * ax + ay * ay;
|
||||
if len2 > 1e-12 {
|
||||
reflect_vec3(&mut entity.u_vector.x, &mut entity.u_vector.y, ax, ay, len2);
|
||||
reflect_vec3(&mut entity.v_vector.x, &mut entity.v_vector.y, ax, ay, len2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,10 @@ impl EntityTypeOps for EntityType {
|
|||
EntityType::Polyline3D(pl) => TruckConvertible::to_truck(pl, document),
|
||||
EntityType::Ray(ray) => TruckConvertible::to_truck(ray, document),
|
||||
EntityType::XLine(xl) => TruckConvertible::to_truck(xl, document),
|
||||
EntityType::RasterImage(img) => TruckConvertible::to_truck(img, document),
|
||||
EntityType::Wipeout(wo) => TruckConvertible::to_truck(wo, document),
|
||||
EntityType::AttributeDefinition(a) => TruckConvertible::to_truck(a, document),
|
||||
EntityType::AttributeEntity(a) => TruckConvertible::to_truck(a, document),
|
||||
EntityType::Text(text) => TruckConvertible::to_truck(text, document),
|
||||
EntityType::MText(text) => TruckConvertible::to_truck(text, document),
|
||||
EntityType::Leader(leader) => TruckConvertible::to_truck(leader, document),
|
||||
|
|
@ -66,6 +70,10 @@ impl EntityTypeOps for EntityType {
|
|||
EntityType::Polyline3D(pl) => Grippable::grips(pl),
|
||||
EntityType::Ray(ray) => Grippable::grips(ray),
|
||||
EntityType::XLine(xl) => Grippable::grips(xl),
|
||||
EntityType::RasterImage(img) => Grippable::grips(img),
|
||||
EntityType::Wipeout(wo) => Grippable::grips(wo),
|
||||
EntityType::AttributeDefinition(a) => Grippable::grips(a),
|
||||
EntityType::AttributeEntity(a) => Grippable::grips(a),
|
||||
EntityType::Point(pt) => Grippable::grips(pt),
|
||||
EntityType::Spline(spline) => Grippable::grips(spline),
|
||||
EntityType::Text(text) => Grippable::grips(text),
|
||||
|
|
@ -119,6 +127,22 @@ impl EntityTypeOps for EntityType {
|
|||
xl,
|
||||
text_style_names,
|
||||
)),
|
||||
EntityType::RasterImage(img) => Some(PropertyEditable::geometry_properties(
|
||||
img,
|
||||
text_style_names,
|
||||
)),
|
||||
EntityType::Wipeout(wo) => Some(PropertyEditable::geometry_properties(
|
||||
wo,
|
||||
text_style_names,
|
||||
)),
|
||||
EntityType::AttributeDefinition(a) => Some(PropertyEditable::geometry_properties(
|
||||
a,
|
||||
text_style_names,
|
||||
)),
|
||||
EntityType::AttributeEntity(a) => Some(PropertyEditable::geometry_properties(
|
||||
a,
|
||||
text_style_names,
|
||||
)),
|
||||
EntityType::Hatch(hatch) => Some(PropertyEditable::geometry_properties(
|
||||
hatch,
|
||||
text_style_names,
|
||||
|
|
@ -174,6 +198,10 @@ impl EntityTypeOps for EntityType {
|
|||
EntityType::Polyline3D(pl) => PropertyEditable::apply_geom_prop(pl, field, value),
|
||||
EntityType::Ray(ray) => PropertyEditable::apply_geom_prop(ray, field, value),
|
||||
EntityType::XLine(xl) => PropertyEditable::apply_geom_prop(xl, field, value),
|
||||
EntityType::RasterImage(img) => PropertyEditable::apply_geom_prop(img, field, value),
|
||||
EntityType::Wipeout(wo) => PropertyEditable::apply_geom_prop(wo, field, value),
|
||||
EntityType::AttributeDefinition(a) => PropertyEditable::apply_geom_prop(a, field, value),
|
||||
EntityType::AttributeEntity(a) => PropertyEditable::apply_geom_prop(a, field, value),
|
||||
EntityType::Hatch(hatch) => PropertyEditable::apply_geom_prop(hatch, field, value),
|
||||
EntityType::Point(pt) => PropertyEditable::apply_geom_prop(pt, field, value),
|
||||
EntityType::Spline(spline) => PropertyEditable::apply_geom_prop(spline, field, value),
|
||||
|
|
@ -200,6 +228,10 @@ impl EntityTypeOps for EntityType {
|
|||
EntityType::Polyline3D(pl) => Grippable::apply_grip(pl, grip_id, apply),
|
||||
EntityType::Ray(ray) => Grippable::apply_grip(ray, grip_id, apply),
|
||||
EntityType::XLine(xl) => Grippable::apply_grip(xl, grip_id, apply),
|
||||
EntityType::RasterImage(img) => Grippable::apply_grip(img, grip_id, apply),
|
||||
EntityType::Wipeout(wo) => Grippable::apply_grip(wo, grip_id, apply),
|
||||
EntityType::AttributeDefinition(a) => Grippable::apply_grip(a, grip_id, apply),
|
||||
EntityType::AttributeEntity(a) => Grippable::apply_grip(a, grip_id, apply),
|
||||
EntityType::Point(pt) => Grippable::apply_grip(pt, grip_id, apply),
|
||||
EntityType::Spline(spline) => Grippable::apply_grip(spline, grip_id, apply),
|
||||
EntityType::Text(text) => Grippable::apply_grip(text, grip_id, apply),
|
||||
|
|
@ -226,6 +258,10 @@ impl EntityTypeOps for EntityType {
|
|||
EntityType::Polyline3D(pl) => Transformable::apply_transform(pl, t),
|
||||
EntityType::Ray(ray) => Transformable::apply_transform(ray, t),
|
||||
EntityType::XLine(xl) => Transformable::apply_transform(xl, t),
|
||||
EntityType::RasterImage(img) => Transformable::apply_transform(img, t),
|
||||
EntityType::Wipeout(wo) => Transformable::apply_transform(wo, t),
|
||||
EntityType::AttributeDefinition(a) => Transformable::apply_transform(a, t),
|
||||
EntityType::AttributeEntity(a) => Transformable::apply_transform(a, t),
|
||||
EntityType::MText(text) => Transformable::apply_transform(text, t),
|
||||
EntityType::Point(pt) => Transformable::apply_transform(pt, t),
|
||||
EntityType::Spline(spline) => Transformable::apply_transform(spline, t),
|
||||
|
|
|
|||
Loading…
Reference in a new issue