forked from 1b-agent/opencadstudio-upstream
feat(ui): render BPT popup and authoring selection state
This commit is contained in:
1 parent
286bdf6426
commit
29d903d5d2
2 files changed
+116
-20
No files matched your search
+68
-11
@@ -1114,8 +1114,14 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
);
|
);
|
||||||
let point = tab.scene.camera.borrow().project(location, vp_bounds)?;
|
let point = tab.scene.camera.borrow().project(location, vp_bounds)?;
|
||||||
let point = iced::Point::new(vp_bounds.x + point.x, vp_bounds.y + point.y);
|
let point = iced::Point::new(vp_bounds.x + point.x, vp_bounds.y + point.y);
|
||||||
(point.x.is_finite() && point.y.is_finite())
|
(point.x.is_finite() && point.y.is_finite()).then(|| {
|
||||||
.then(|| (point, parameter.name.clone(), vp_bounds))
|
(
|
||||||
|
point,
|
||||||
|
parameter.name.clone(),
|
||||||
|
vp_bounds,
|
||||||
|
tab.selected_authoring == Some(parameter.handle),
|
||||||
|
)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
let authoring_points =
|
let authoring_points =
|
||||||
tab.active_block_edit_session()
|
tab.active_block_edit_session()
|
||||||
@@ -1125,7 +1131,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
session.br_handle,
|
session.br_handle,
|
||||||
)
|
)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(_, parameter)| {
|
.filter_map(|(handle, parameter)| {
|
||||||
let project = |point: codec::types::Vector3| {
|
let project = |point: codec::types::Vector3| {
|
||||||
let point = tab.scene.camera.borrow().project(
|
let point = tab.scene.camera.borrow().project(
|
||||||
glam::DVec3::new(point.x, point.y, point.z),
|
glam::DVec3::new(point.x, point.y, point.z),
|
||||||
@@ -1140,6 +1146,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
project(parameter.definition_label_point)?,
|
project(parameter.definition_label_point)?,
|
||||||
parameter.position_name.clone(),
|
parameter.position_name.clone(),
|
||||||
vp_bounds,
|
vp_bounds,
|
||||||
|
tab.selected_authoring == Some(handle),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@@ -1153,8 +1160,9 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
session.br_handle,
|
session.br_handle,
|
||||||
)
|
)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
(
|
(
|
||||||
|
p.handle,
|
||||||
crate::scene::block_distance_parameter::graphic(p),
|
crate::scene::block_distance_parameter::graphic(p),
|
||||||
p.native.definition_base_point,
|
p.native.definition_base_point,
|
||||||
)
|
)
|
||||||
@@ -1167,6 +1175,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
(
|
(
|
||||||
|
p.handle,
|
||||||
crate::scene::block_orientation_parameter::graphic(p),
|
crate::scene::block_orientation_parameter::graphic(p),
|
||||||
crate::scene::block_orientation_parameter::marker_tail(p),
|
crate::scene::block_orientation_parameter::marker_tail(p),
|
||||||
)
|
)
|
||||||
@@ -1177,10 +1186,29 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
&tab.scene.document,
|
&tab.scene.document,
|
||||||
session.br_handle,
|
session.br_handle,
|
||||||
)
|
)
|
||||||
.map(|(_, p)| {
|
.map(|(handle, p)| (handle, p.parameter.definition_point))
|
||||||
|
.or_else(|| {
|
||||||
|
let name = tab
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.block_records
|
||||||
|
.iter()
|
||||||
|
.find(|record| record.handle == session.br_handle)?
|
||||||
|
.name
|
||||||
|
.as_str();
|
||||||
|
Some((
|
||||||
|
session.br_handle,
|
||||||
|
crate::scene::render_graph::block_base_point(
|
||||||
|
&tab.scene.document,
|
||||||
|
name,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.map(|(handle, point)| {
|
||||||
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
||||||
g.base_grips.push(p.parameter.definition_point);
|
g.base_grips.push(point);
|
||||||
(g, p.parameter.definition_point)
|
g.labels.push((point, "Basepoint".into()));
|
||||||
|
(handle, g, point)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
@@ -1189,12 +1217,12 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
session.br_handle,
|
session.br_handle,
|
||||||
)
|
)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, p)| {
|
.map(|(handle, p)| {
|
||||||
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
||||||
g.lookup_grips.push(p.parameter.definition_point);
|
g.lookup_grips.push(p.parameter.definition_point);
|
||||||
g.labels
|
g.labels
|
||||||
.push((p.parameter.definition_point, p.lookup_name.clone()));
|
.push((p.parameter.definition_point, p.lookup_name.clone()));
|
||||||
(g, p.parameter.definition_point)
|
(handle, g, p.parameter.definition_point)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
@@ -1219,10 +1247,10 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
g.grips.push((action.display_location, false));
|
g.grips.push((action.display_location, false));
|
||||||
g.labels
|
g.labels
|
||||||
.push((action.display_location, action.element.name.clone()));
|
.push((action.display_location, action.element.name.clone()));
|
||||||
(g, action.display_location)
|
(handle, g, action.display_location)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.filter_map(|(graphic, marker_tail)| {
|
.filter_map(|(handle, graphic, marker_tail)| {
|
||||||
let project = |p: codec::types::Vector3| {
|
let project = |p: codec::types::Vector3| {
|
||||||
let p = tab
|
let p = tab
|
||||||
.scene
|
.scene
|
||||||
@@ -1257,6 +1285,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
})
|
})
|
||||||
.collect::<Option<Vec<_>>>()?;
|
.collect::<Option<Vec<_>>>()?;
|
||||||
Some(crate::ui::overlay::AuthoringDimension {
|
Some(crate::ui::overlay::AuthoringDimension {
|
||||||
|
selected: tab.selected_authoring == Some(handle),
|
||||||
lines,
|
lines,
|
||||||
base_grips: graphic
|
base_grips: graphic
|
||||||
.base_grips
|
.base_grips
|
||||||
@@ -2052,6 +2081,34 @@ bg={bg_ms:.1}ms n={view_count}"
|
|||||||
viewport_stack.push(position_canvas_overlay(anchor, panel.into()));
|
viewport_stack.push(position_canvas_overlay(anchor, panel.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(popup) = self.table_popup.as_ref() {
|
||||||
|
if !tab.is_start {
|
||||||
|
let mut col = column![text(popup.header.clone()).size(12)].spacing(2);
|
||||||
|
for (idx, name) in popup.rows.iter().enumerate() {
|
||||||
|
let mark: Element<'_, Message> = if popup.current == Some(idx) {
|
||||||
|
crate::ui::icons::themed_check_cell(true)
|
||||||
|
} else {
|
||||||
|
Space::new().width(11).into()
|
||||||
|
};
|
||||||
|
col = col.push(
|
||||||
|
button(
|
||||||
|
row![container(mark).width(16), text(name).size(12)]
|
||||||
|
.spacing(2)
|
||||||
|
.align_y(iced::Center),
|
||||||
|
)
|
||||||
|
.on_press(Message::TableRowPick(idx))
|
||||||
|
.padding([3, 10])
|
||||||
|
.width(Fill),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let panel =
|
||||||
|
container(iced::widget::scrollable(col).height(iced::Length::Shrink))
|
||||||
|
.padding(2);
|
||||||
|
let anchor = iced::Point::new(popup.anchor.x + 12.0, popup.anchor.y + 12.0);
|
||||||
|
viewport_stack =
|
||||||
|
viewport_stack.push(position_canvas_overlay(anchor, panel.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Selection actions: with only PDF underlays or only xrefs
|
// Selection actions: with only PDF underlays or only xrefs
|
||||||
// selected, their tools take the right edge (over the paper-space
|
// selected, their tools take the right edge (over the paper-space
|
||||||
|
|||||||
+48
-9
@@ -1037,8 +1037,8 @@ pub(crate) fn selection_overlay<'a>(
|
|||||||
constraint_glyph_selected: Arc<[bool]>,
|
constraint_glyph_selected: Arc<[bool]>,
|
||||||
constraint_glyph_tooltip: Option<String>,
|
constraint_glyph_tooltip: Option<String>,
|
||||||
constraint_cursor_badge: Option<String>,
|
constraint_cursor_badge: Option<String>,
|
||||||
authoring_visibility: Option<(Point, String, iced::Rectangle)>,
|
authoring_visibility: Option<(Point, String, iced::Rectangle, bool)>,
|
||||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle)>,
|
authoring_points: Vec<(Point, Point, String, iced::Rectangle, bool)>,
|
||||||
authoring_dimensions: Vec<AuthoringDimension>,
|
authoring_dimensions: Vec<AuthoringDimension>,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
canvas(SelectionCanvas {
|
canvas(SelectionCanvas {
|
||||||
@@ -1079,6 +1079,7 @@ pub(crate) fn selection_overlay<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct AuthoringDimension {
|
pub(crate) struct AuthoringDimension {
|
||||||
|
pub selected: bool,
|
||||||
pub lines: Vec<[Point; 2]>,
|
pub lines: Vec<[Point; 2]>,
|
||||||
pub round_grips: Vec<Point>,
|
pub round_grips: Vec<Point>,
|
||||||
pub base_grips: Vec<Point>,
|
pub base_grips: Vec<Point>,
|
||||||
@@ -1160,8 +1161,8 @@ struct SelectionCanvas {
|
|||||||
/// Symbol shown beside the cursor while it targets an entity that already
|
/// Symbol shown beside the cursor while it targets an entity that already
|
||||||
/// participates in an enabled geometric constraint.
|
/// participates in an enabled geometric constraint.
|
||||||
constraint_cursor_badge: Option<String>,
|
constraint_cursor_badge: Option<String>,
|
||||||
authoring_visibility: Option<(Point, String, iced::Rectangle)>,
|
authoring_visibility: Option<(Point, String, iced::Rectangle, bool)>,
|
||||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle)>,
|
authoring_points: Vec<(Point, Point, String, iced::Rectangle, bool)>,
|
||||||
authoring_dimensions: Vec<AuthoringDimension>,
|
authoring_dimensions: Vec<AuthoringDimension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2388,15 +2389,25 @@ impl canvas::Program<Message> for SelectionCanvas {
|
|||||||
frame.stroke(&b1, stroke.clone());
|
frame.stroke(&b1, stroke.clone());
|
||||||
frame.stroke(&b2, stroke);
|
frame.stroke(&b2, stroke);
|
||||||
}
|
}
|
||||||
if let Some((point, label, clip)) = &self.authoring_visibility {
|
if let Some((point, label, clip, selected)) = &self.authoring_visibility {
|
||||||
frame.with_clip(*clip, |frame| {
|
frame.with_clip(*clip, |frame| {
|
||||||
let color = theme.palette().primary.base.color;
|
let color = if *selected {
|
||||||
|
theme.palette().primary.strong.color
|
||||||
|
} else {
|
||||||
|
theme.palette().primary.base.color
|
||||||
|
};
|
||||||
let triangle = canvas::Path::new(|builder| {
|
let triangle = canvas::Path::new(|builder| {
|
||||||
builder.move_to(Point::new(point.x - 5.0, point.y - 3.0));
|
builder.move_to(Point::new(point.x - 5.0, point.y - 3.0));
|
||||||
builder.line_to(Point::new(point.x + 5.0, point.y - 3.0));
|
builder.line_to(Point::new(point.x + 5.0, point.y - 3.0));
|
||||||
builder.line_to(Point::new(point.x, point.y + 5.0));
|
builder.line_to(Point::new(point.x, point.y + 5.0));
|
||||||
builder.close();
|
builder.close();
|
||||||
});
|
});
|
||||||
|
if *selected {
|
||||||
|
frame.stroke(
|
||||||
|
&canvas::Path::circle(*point, 10.0),
|
||||||
|
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
frame.fill(&triangle, color);
|
frame.fill(&triangle, color);
|
||||||
frame.fill_text(canvas::Text {
|
frame.fill_text(canvas::Text {
|
||||||
content: label.clone(),
|
content: label.clone(),
|
||||||
@@ -2407,9 +2418,19 @@ impl canvas::Program<Message> for SelectionCanvas {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (point, label_point, label, clip) in &self.authoring_points {
|
for (point, label_point, label, clip, selected) in &self.authoring_points {
|
||||||
frame.with_clip(*clip, |frame| {
|
frame.with_clip(*clip, |frame| {
|
||||||
let color = theme.palette().primary.base.color;
|
let color = if *selected {
|
||||||
|
theme.palette().primary.strong.color
|
||||||
|
} else {
|
||||||
|
theme.palette().primary.base.color
|
||||||
|
};
|
||||||
|
if *selected {
|
||||||
|
frame.stroke(
|
||||||
|
&canvas::Path::circle(*point, 10.0),
|
||||||
|
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
frame.stroke(
|
frame.stroke(
|
||||||
&canvas::Path::line(*point, *label_point),
|
&canvas::Path::line(*point, *label_point),
|
||||||
canvas::Stroke::default().with_color(color),
|
canvas::Stroke::default().with_color(color),
|
||||||
@@ -2432,7 +2453,25 @@ impl canvas::Program<Message> for SelectionCanvas {
|
|||||||
}
|
}
|
||||||
for dimension in &self.authoring_dimensions {
|
for dimension in &self.authoring_dimensions {
|
||||||
frame.with_clip(dimension.clip, |frame| {
|
frame.with_clip(dimension.clip, |frame| {
|
||||||
let color = theme.palette().primary.base.color;
|
let color = if dimension.selected {
|
||||||
|
theme.palette().primary.strong.color
|
||||||
|
} else {
|
||||||
|
theme.palette().primary.base.color
|
||||||
|
};
|
||||||
|
if dimension.selected {
|
||||||
|
for point in dimension
|
||||||
|
.base_grips
|
||||||
|
.iter()
|
||||||
|
.chain(dimension.lookup_grips.iter())
|
||||||
|
.chain(dimension.round_grips.iter())
|
||||||
|
.chain(dimension.grips.iter().map(|(point, _)| point))
|
||||||
|
{
|
||||||
|
frame.stroke(
|
||||||
|
&canvas::Path::circle(*point, 10.0),
|
||||||
|
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
for [a, b] in &dimension.lines {
|
for [a, b] in &dimension.lines {
|
||||||
frame.stroke(
|
frame.stroke(
|
||||||
&canvas::Path::line(*a, *b),
|
&canvas::Path::line(*a, *b),
|
||||||
|
|||||||
Reference in new issue
Block a user