Thanks @DuBearte.
This commit is contained in:
1 parent
e49770bd24
commit
fd073620ae
8 files changed
+65
No files matched your search
@@ -32,6 +32,7 @@
|
||||
"Duration": "Dauer",
|
||||
"Edges": "Kanten",
|
||||
"Edit Profile Sketch": "Profile-Skizze bearbeiten",
|
||||
"Explode Text": "Text auflösen",
|
||||
"Export Animation…": "Animation exportieren…",
|
||||
"Export Current View as DXF": "Aktuelle Ansicht als DXF exportieren",
|
||||
"Export Current View as DXF…": "Aktuelle Ansicht als DXF exportieren…",
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"Enable rule": "Enable rule",
|
||||
"Enabled": "Enabled",
|
||||
"Explode": "Explode",
|
||||
"Explode Text": "Explode Text",
|
||||
"Export Animation…": "Export Animation…",
|
||||
"Export Current View as DXF": "Export Current View as DXF",
|
||||
"Export Current View as DXF…": "Export Current View as DXF…",
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"Enable rule": "ルールを有効化",
|
||||
"Enabled": "有効",
|
||||
"Explode": "分解",
|
||||
"Explode Text": "テキストを分解",
|
||||
"Export Animation…": "アニメーションをエクスポート…",
|
||||
"Export Current View as DXF": "現在の表示をDXFでエクスポート",
|
||||
"Export Current View as DXF…": "現在の表示をDXFでエクスポート…",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"Duration": "지속 시간",
|
||||
"Edges": "모서리",
|
||||
"Edit Profile Sketch": "윤곽 스케치 편집",
|
||||
"Explode Text": "텍스트 분해",
|
||||
"Export Animation…": "애니메이션 내보내기…",
|
||||
"Export Current View as DXF": "현재 뷰를 DXF로 내보내기",
|
||||
"Export Current View as DXF…": "현재 뷰를 DXF로 내보내기…",
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"Enable rule": "启用规则",
|
||||
"Enabled": "已启用",
|
||||
"Explode": "爆炸",
|
||||
"Explode Text": "分解文字",
|
||||
"Export Animation…": "导出动画…",
|
||||
"Export Current View as DXF": "将当前视图导出为DXF",
|
||||
"Export Current View as DXF…": "将当前视图导出为DXF…",
|
||||
|
||||
@@ -719,6 +719,13 @@ fn component_items(app: &SolveApp, id: u64) -> Vec<Item> {
|
||||
v
|
||||
}
|
||||
|
||||
/// Explode Text (#1842): the selected text's outlines become normal sketch lines, arcs and
|
||||
/// curves, no longer tied to the text, so they can be picked, trimmed and edited one by one.
|
||||
fn explode_text(app: &SolveApp) -> Option<Item> {
|
||||
let link = crate::sketch_text::selected_link(app)?;
|
||||
Some(cmd(app, "sketch.break_link", "Explode Text").with(json!({ "link": link })))
|
||||
}
|
||||
|
||||
/// Sketch entity items: construction, fix, delete, dimension and the constraints the selection
|
||||
/// can take.
|
||||
fn sketch_entity_items(app: &SolveApp) -> Vec<Item> {
|
||||
@@ -754,6 +761,7 @@ fn sketch_entity_items(app: &SolveApp) -> Vec<Item> {
|
||||
if curves.is_empty() && points.is_empty() {
|
||||
if crate::sketch_text::selected_entity(app).is_some() {
|
||||
v.push(cmd(app, "sketch.edit_text", "Edit Text"));
|
||||
v.extend(explode_text(app));
|
||||
}
|
||||
v.push(cmd(app, "sketch.line", "Line"));
|
||||
v.push(cmd(app, "sketch.rectangle.two_point", "Rectangle"));
|
||||
@@ -773,6 +781,7 @@ fn sketch_entity_items(app: &SolveApp) -> Vec<Item> {
|
||||
}
|
||||
if crate::sketch_text::selected_entity(app).is_some() {
|
||||
v.push(cmd(app, "sketch.edit_text", "Edit Text"));
|
||||
v.extend(explode_text(app));
|
||||
}
|
||||
v.push(cmd(app, "sketch.move", "Move/Copy").key("M"));
|
||||
v.push(act("ui.cut", "Cut", "").key("Ctrl+X"));
|
||||
|
||||
@@ -183,6 +183,13 @@ pub(crate) fn selected_entity(app: &SolveApp) -> Option<String> {
|
||||
selected
|
||||
}
|
||||
|
||||
/// The link of the one text the selection belongs to (see [`selected_entity`]).
|
||||
pub(crate) fn selected_link(app: &SolveApp) -> Option<String> {
|
||||
let entity = selected_entity(app)?;
|
||||
let sk = app.session.doc.sketch(app.session.active_sketch?).ok()?;
|
||||
sk.curves.iter().find(|curve| curve.id == entity)?.link.clone()
|
||||
}
|
||||
|
||||
/// Show every outline affected by the open editor without changing feature selections.
|
||||
pub(crate) fn highlighted(app: &SolveApp) -> Vec<Sel> {
|
||||
let Some(Kind::Text(tx)) = app.dialog.as_ref().map(|dialog| &dialog.kind) else { return Vec::new() };
|
||||
@@ -752,6 +759,45 @@ mod tests {
|
||||
assert!(highlighted(&h.app).is_empty());
|
||||
}
|
||||
|
||||
/// Explode Text (#1842): the text's outlines stay where they are as ordinary sketch curves,
|
||||
/// the text itself goes, and one undo brings it back.
|
||||
#[test]
|
||||
fn explode_text_leaves_its_outlines_as_normal_curves() {
|
||||
let (mut h, link, _) = setup();
|
||||
h.app.run("sketch.edit_text", json!({"link":link,"text":"TO"})).unwrap();
|
||||
let sid = h.app.session.active_sketch.unwrap();
|
||||
let outline = |h: &Harness| {
|
||||
let sk = h.app.session.doc.sketch(sid).unwrap();
|
||||
let mut ids: Vec<(String, Option<String>)> = sk.curves.iter().map(|c| (c.id.clone(), c.link.clone())).collect();
|
||||
ids.sort();
|
||||
ids
|
||||
};
|
||||
let before = outline(&h);
|
||||
assert!(before.len() > 4 && before.iter().all(|(_, l)| l.as_deref() == Some(link.as_str())));
|
||||
let profiles = h.app.session.world_state().sketch(sid).unwrap().profiles.len();
|
||||
h.app.session.selection = vec![Sel::SketchCurve { id: before[0].0.clone() }];
|
||||
let undo = h.app.session.undo.len();
|
||||
let item = crate::context_menu::items(&h.app, &crate::context_menu::Target::Viewport)
|
||||
.into_iter()
|
||||
.find(|item| item.label == "Explode Text")
|
||||
.expect("Explode Text is offered for a selected text");
|
||||
assert!(item.enabled);
|
||||
crate::context_menu::run_item(&mut h.app, &item, egui::Pos2::ZERO);
|
||||
h.frames(2);
|
||||
let after = outline(&h);
|
||||
assert_eq!(after.iter().map(|c| &c.0).collect::<Vec<_>>(), before.iter().map(|c| &c.0).collect::<Vec<_>>(), "every outline stays");
|
||||
assert!(after.iter().all(|(_, l)| l.is_none()), "no outline belongs to the text");
|
||||
let sk = h.app.session.doc.sketch(sid).unwrap();
|
||||
assert!(sk.link(&link).is_none(), "the text is gone");
|
||||
assert_eq!(h.app.session.world_state().sketch(sid).unwrap().profiles.len(), profiles, "the letters still make the same profiles");
|
||||
assert_eq!(h.app.session.undo.len(), undo + 1);
|
||||
// No longer text: nothing to edit or explode.
|
||||
assert!(selected_entity(&h.app).is_none());
|
||||
assert!(!crate::context_menu::items(&h.app, &crate::context_menu::Target::Viewport).iter().any(|item| item.label == "Explode Text"));
|
||||
h.app.run("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(outline(&h), before, "undo brings the text back");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edit_text_tool_accepts_a_letter_interior_without_preselection() {
|
||||
let (mut h, link, _) = setup();
|
||||
|
||||
@@ -66,6 +66,11 @@ keeps the original text. Position and height use the document's units. The four
|
||||
expressions: one that names a parameter (`plate_width / 2`) stays an expression, is shown as typed
|
||||
when the dialog is opened again, and keeps the text following the parameter.
|
||||
|
||||
To work on the letters' shapes themselves, right-click the text and choose **Explode Text**
|
||||
(`sketch.break_link` with the text's `link`). Its outlines stay where they are as ordinary
|
||||
lines, arcs and curves that can be picked, trimmed, dimensioned and extruded one by one; the
|
||||
text itself is gone, so it can no longer be edited as text or follow parameters. Undo brings it back.
|
||||
|
||||
A text can follow a curve of its sketch (its **Path**). That curve becomes construction: the
|
||||
letters stand on it and their descenders cross it, so as a normal curve it would cut them into
|
||||
pieces, and picking the text would pick those pieces. Taking the text off the curve leaves it
|
||||
|
||||
Reference in new issue
Block a user