forked from 1b-agent/opencadstudio-upstream
feat(input): lock the next point to a typed <angle
Typing <angle at a point prompt (e.g. <30) now fixes the direction of the next point from the last one until a point is placed: the cursor moves along that direction, and a bare number entered next is the distance along it. The angle is read in the drawing's angle base and direction and turned into the current UCS. Works from the command line and from scripts or the automation token input alike. Fixes #1464 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
29c0d1df9a
commit
0eec9c450f
28 files changed
+77
-1
No files matched your search
@@ -294,6 +294,7 @@ command-copy =
|
||||
.mode = COPY أدخل خيار وضع النسخ [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = تجاوز الزاوية: __ocs_fmt_0__
|
||||
.plot-preview-task = معاينة الطباعة
|
||||
.link-a-csv-data-source = ربط مصدر بيانات CSV
|
||||
.csv-files = ملفات CSV
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.displacement = COPY Задайте преместване:
|
||||
.mode = COPY Въведете режим на копиране [Single/Multiple] <Multiple>:
|
||||
common =
|
||||
.angle-override-shown = Замяна на ъгъла: __ocs_fmt_0__
|
||||
.plot-preview-task = Преглед на печата
|
||||
.link-a-csv-data-source = Свързване на CSV източник на данни
|
||||
.csv-files = CSV файлове
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Zadejte režim kopírování [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Přepsání úhlu: __ocs_fmt_0__
|
||||
.plot-preview-task = Náhled tisku
|
||||
.link-a-csv-data-source = Propojit zdroj dat CSV
|
||||
.csv-files = Soubory CSV
|
||||
|
||||
@@ -282,6 +282,7 @@ command-copy =
|
||||
.mode = COPY Kopiermodus eingeben [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Winkelvorgabe: __ocs_fmt_0__
|
||||
.plot-preview-task = Plotvorschau
|
||||
.link-a-csv-data-source = CSV-Datenquelle verknüpfen
|
||||
.csv-files = CSV-Dateien
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Επιλέξτε λειτουργία αντιγραφής [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Παράκαμψη γωνίας: __ocs_fmt_0__
|
||||
.plot-preview-task = Προεπισκόπηση εκτύπωσης
|
||||
.link-a-csv-data-source = Σύνδεση πηγής δεδομένων CSV
|
||||
.csv-files = Αρχεία CSV
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Enter a copy mode option [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Angle Override: __ocs_fmt_0__
|
||||
.browser-cannot-open-typed-path = The browser cannot open a typed path; pick the file instead.
|
||||
.recover-drawing = Recover Drawing
|
||||
.requires-0-or-1-or-keyword = Requires 0 or 1 only, or option keyword.
|
||||
|
||||
@@ -282,6 +282,7 @@ command-copy =
|
||||
.mode = COPY Indique modo de copia [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Modificación de ángulo: __ocs_fmt_0__
|
||||
.plot-preview-task = Vista previa de trazado
|
||||
.link-a-csv-data-source = Vincular un origen de datos CSV
|
||||
.csv-files = Archivos CSV
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Valitse kopiointitila [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Kulman ohitus: __ocs_fmt_0__
|
||||
.plot-preview-task = Tulostuksen esikatselu
|
||||
.link-a-csv-data-source = Linkitä CSV-tietolähde
|
||||
.csv-files = CSV-tiedostot
|
||||
|
||||
@@ -282,6 +282,7 @@ command-copy =
|
||||
.mode = COPY Entrez le mode de copie [Single/Multiple] <Multiple> :
|
||||
|
||||
common =
|
||||
.angle-override-shown = Remplacement d’angle : __ocs_fmt_0__
|
||||
.plot-preview-task = Aperçu du tracé
|
||||
.link-a-csv-data-source = Lier une source de données CSV
|
||||
.csv-files = Fichiers CSV
|
||||
|
||||
@@ -270,6 +270,7 @@ command-copy =
|
||||
.mode = COPY कॉपी मोड विकल्प दर्ज करें [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = कोण ओवरराइड: __ocs_fmt_0__
|
||||
.plot-preview-task = प्लॉट पूर्वावलोकन
|
||||
.link-a-csv-data-source = CSV डेटा स्रोत लिंक करें
|
||||
.csv-files = CSV फ़ाइलें
|
||||
|
||||
@@ -280,6 +280,7 @@ command-copy =
|
||||
.mode = COPY Adja meg a másolási módot [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Szög felülbírálása: __ocs_fmt_0__
|
||||
.parametric-coincident = Egybeeső
|
||||
.parametric-colinear = Egy egyenesbe eső
|
||||
.parametric-concentric = Koncentrikus
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Specificare modalità di copia [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Sostituzione angolo: __ocs_fmt_0__
|
||||
.plot-preview-task = Anteprima di stampa
|
||||
.link-a-csv-data-source = Collega un'origine dati CSV
|
||||
.csv-files = File CSV
|
||||
|
||||
@@ -272,6 +272,7 @@ command-copy =
|
||||
.mode = COPY コピーモードを入力 [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = 角度の優先: __ocs_fmt_0__
|
||||
.plot-preview-task = 印刷プレビュー
|
||||
.link-a-csv-data-source = CSV データ ソースをリンク
|
||||
.csv-files = CSV ファイル
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY 복사 모드 옵션 입력 [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = 각도 재지정: __ocs_fmt_0__
|
||||
.plot-preview-task = 플롯 미리 보기
|
||||
.link-a-csv-data-source = CSV 데이터 원본 연결
|
||||
.csv-files = CSV 파일
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY ປ້ອນຕົວເລືອກໂໝດການຄັດລອກ [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = ກຳນົດມຸມແທນ: __ocs_fmt_0__
|
||||
.remote-image-url-could-not-be-fetched-the-request-timed-out = ບໍ່ສາມາດດຶງຮູບພາບທາງໄກ "__ocs_fmt_0__" ໄດ້: ການຮ້ອງຂໍໝົດເວລາ.
|
||||
.remote-image-url-was-not-loaded-it-exceeds-the-64-mb-remote-image-limit = ບໍ່ໄດ້ໂຫຼດຮູບພາບທາງໄກ "__ocs_fmt_0__": ມັນເກີນຂີດຈຳກັດ 64 MB ຂອງຮູບພາບທາງໄກ.
|
||||
.remote-image-url-could-not-be-fetched-the-server-returned-http-status = ບໍ່ສາມາດດຶງຮູບພາບທາງໄກ "__ocs_fmt_0__" ໄດ້: ເຊີບເວີຕອບກັບ HTTP __ocs_fmt_1__.
|
||||
|
||||
@@ -282,6 +282,7 @@ command-copy =
|
||||
.mode = COPY Geef kopieermodus op [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Hoekoverschrijving: __ocs_fmt_0__
|
||||
.plot-preview-task = Plotvoorbeeld
|
||||
.link-a-csv-data-source = CSV-gegevensbron koppelen
|
||||
.csv-files = CSV-bestanden
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY Podaj tryb kopiowania [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Zastąpienie kąta: __ocs_fmt_0__
|
||||
.plot-preview-task = Podgląd wydruku
|
||||
.link-a-csv-data-source = Połącz źródło danych CSV
|
||||
.csv-files = Pliki CSV
|
||||
|
||||
@@ -282,6 +282,7 @@ command-copy =
|
||||
.mode = COPY Informe o modo de cópia [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Substituição de ângulo: __ocs_fmt_0__
|
||||
.plot-preview-task = Visualização da plotagem
|
||||
.link-a-csv-data-source = Vincular uma fonte de dados CSV
|
||||
.csv-files = Arquivos CSV
|
||||
|
||||
@@ -285,6 +285,7 @@ command-copy =
|
||||
.mode = COPY Задайте режим копирования [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Переопределение угла: __ocs_fmt_0__
|
||||
.plot-preview-task = Предварительный просмотр печати
|
||||
.link-a-csv-data-source = Связать источник данных CSV
|
||||
.csv-files = Файлы CSV
|
||||
|
||||
@@ -267,6 +267,7 @@ command-copy =
|
||||
.mode = COPY Kopyalama modu seçin [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = Açı geçersiz kılma: __ocs_fmt_0__
|
||||
.plot-preview-task = Çizim önizleme
|
||||
.link-a-csv-data-source = CSV veri kaynağı bağla
|
||||
.csv-files = CSV Dosyaları
|
||||
|
||||
@@ -269,6 +269,7 @@ command-copy =
|
||||
.mode = COPY 输入复制模式选项 [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = 角度替代:__ocs_fmt_0__
|
||||
.plot-preview-task = 打印预览
|
||||
.link-a-csv-data-source = 链接 CSV 数据源
|
||||
.csv-files = CSV 文件
|
||||
|
||||
@@ -281,6 +281,7 @@ command-copy =
|
||||
.mode = COPY 輸入複製模式選項 [Single/Multiple] <Multiple>:
|
||||
|
||||
common =
|
||||
.angle-override-shown = 角度取代:__ocs_fmt_0__
|
||||
.plot-preview-task = 出圖預覽
|
||||
.link-a-csv-data-source = 連結 CSV 資料來源
|
||||
.csv-files = CSV 檔案
|
||||
|
||||
@@ -98,6 +98,7 @@ impl OpenCADStudio {
|
||||
self.otrack_cross = None;
|
||||
self.otrack_kind = None;
|
||||
self.axis_lock_dir = None;
|
||||
self.angle_override = None;
|
||||
self.dyn_user_reshaped = false;
|
||||
self.dyn_coord_absolute = false;
|
||||
self.grip_hover = None;
|
||||
@@ -595,6 +596,7 @@ impl OpenCADStudio {
|
||||
if !self.command_point_allowed(i, *point) {
|
||||
return (Task::none(), true);
|
||||
}
|
||||
self.angle_override = None;
|
||||
// Typed / dynamic-input / headless points carry no snap, but the
|
||||
// accepted-snap list must stay index-parallel with the points the
|
||||
// command collects. Interactive picks record themselves in
|
||||
@@ -1130,6 +1132,9 @@ impl OpenCADStudio {
|
||||
self.apply_snap_override(kind);
|
||||
return Task::none();
|
||||
}
|
||||
if self.try_angle_override(token) {
|
||||
return Task::none();
|
||||
}
|
||||
if let Some((coord, kind)) = crate::app::helpers::parse_coord(token) {
|
||||
// Match the GUI command line: typed coordinates are in the active
|
||||
// UCS (relative offsets are rotated by the UCS axes), so a multi-
|
||||
@@ -1161,7 +1166,13 @@ impl OpenCADStudio {
|
||||
// bare number is the step's own value, not a distance — ROTATE's
|
||||
// angle, SCALE's factor, CIRCLE's radius. Only a token no step
|
||||
// claims becomes direct distance entry, measured along the cursor
|
||||
// direction from the command's anchor.
|
||||
// direction from the command's anchor. Under a typed `<angle`
|
||||
// the number is the distance along it first.
|
||||
if self.angle_override.is_some() {
|
||||
if let Some(distance) = self.try_direct_distance_entry(token) {
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
let (task, consumed) = self.feed_command_consumed(StepInput::Text(token.to_string()));
|
||||
if consumed {
|
||||
return task;
|
||||
|
||||
@@ -1218,6 +1218,9 @@ pub(super) struct OpenCADStudio {
|
||||
/// osnap hits included — projects onto this ray from `last_point` (or the
|
||||
/// grip origin). Cleared when Shift releases.
|
||||
axis_lock_dir: Option<glam::DVec3>,
|
||||
/// A direction typed as `<angle` at a point prompt: the next point stays
|
||||
/// on it until a point is placed.
|
||||
angle_override: Option<glam::DVec3>,
|
||||
/// Inline rename state: (original_name, current_edit_value).
|
||||
layout_rename_state: Option<(String, String)>,
|
||||
/// Timestamp of the previous viewport left-click release (for double-click detection).
|
||||
@@ -4775,6 +4778,7 @@ impl OpenCADStudio {
|
||||
text_inline: None,
|
||||
snap_override_popup: None,
|
||||
axis_lock_dir: None,
|
||||
angle_override: None,
|
||||
layout_rename_state: None,
|
||||
last_vp_click_time: None,
|
||||
last_vp_click_pos: None,
|
||||
|
||||
@@ -868,6 +868,13 @@ impl OpenCADStudio {
|
||||
if let Some(task) = self.try_selection_keyword(&text) {
|
||||
return task;
|
||||
}
|
||||
// Under a typed `<angle` a bare number is the distance along it,
|
||||
// before the step reads it as a value of its own.
|
||||
if self.angle_override.is_some() {
|
||||
if let Some(task) = self.try_direct_distance_entry(&text) {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
if self.tabs[i]
|
||||
.active_cmd
|
||||
.as_ref()
|
||||
@@ -895,6 +902,10 @@ impl OpenCADStudio {
|
||||
return self.feed_command(crate::command::StepInput::Enter);
|
||||
}
|
||||
|
||||
if self.try_angle_override(&text) {
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
// OTRACK and Extension both allow a bare scalar to act as a
|
||||
// distance measured along the active reference ray.
|
||||
if self.active_distance_ray(i).is_some() {
|
||||
@@ -1001,6 +1012,25 @@ impl OpenCADStudio {
|
||||
/// has an established anchor, and `text` parses as a scalar distance,
|
||||
/// project along the active reference ray (if any) or the current cursor
|
||||
/// direction in the active UCS plane.
|
||||
/// `<angle` at a point prompt locks the next point's direction from the
|
||||
/// last point; a bare distance then runs along it. True when consumed.
|
||||
pub(in crate::app) fn try_angle_override(&mut self, text: &str) -> bool {
|
||||
let (Some(angle), Some(_)) = (text.trim().strip_prefix('<'), self.last_point) else {
|
||||
return false;
|
||||
};
|
||||
let Some(angle) = crate::entities::common::parse_typed_direction(angle) else {
|
||||
return false;
|
||||
};
|
||||
let local = glam::DVec3::new(angle.cos(), angle.sin(), 0.0);
|
||||
self.angle_override = Some(match &self.tabs[self.active_tab].active_ucs {
|
||||
Some(ucs) => ucs_rotate_vec(local, ucs),
|
||||
None => local,
|
||||
});
|
||||
let shown = crate::entities::common::format_direction(angle);
|
||||
self.command_line.push_output(crate::tf!("Angle Override: {shown}").as_ref());
|
||||
true
|
||||
}
|
||||
|
||||
pub(in crate::app) fn try_direct_distance_entry(
|
||||
&mut self,
|
||||
text: &str,
|
||||
|
||||
@@ -29,6 +29,10 @@ impl OpenCADStudio {
|
||||
&self,
|
||||
i: usize,
|
||||
) -> Option<(glam::DVec3, glam::DVec3)> {
|
||||
// A typed `<angle` locks the way from the last point.
|
||||
if let (Some(dir), Some(base)) = (self.angle_override, self.last_point) {
|
||||
return Some((base, dir));
|
||||
}
|
||||
// OTRACK already exposes its acquired world-space ray.
|
||||
if let Some((base, dir)) = self.otrack_active {
|
||||
return Some((base, dir));
|
||||
|
||||
@@ -340,6 +340,10 @@ impl OpenCADStudio {
|
||||
base: glam::DVec3,
|
||||
allowed: bool,
|
||||
) -> Option<glam::DVec3> {
|
||||
if let Some(direction) = self.angle_override.filter(|_| allowed) {
|
||||
self.axis_lock_dir = Some(direction);
|
||||
return self.axis_lock_dir;
|
||||
}
|
||||
if self.shift_down && allowed {
|
||||
if self.axis_lock_dir.is_none() {
|
||||
let ucs = self.tabs[tab].ucs_xform();
|
||||
|
||||
@@ -5844,6 +5844,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Requires 0 or 1 only." => Some(("count-feature", "requires-0-or-1")),
|
||||
"Requires 0 or 1 only, or option keyword." => Some(("common", "requires-0-or-1-or-keyword")),
|
||||
"Requires a number." => Some(("common", "requires-a-number")),
|
||||
"Angle Override: {shown}" => Some(("common", "angle-override-shown")),
|
||||
"{name} ...... {n}" => Some(("count-feature", "target-count")),
|
||||
"MTEXT Current text style: \"{}\" Text height: {:.4}" => Some(("count-feature", "mtext-current-style")),
|
||||
"{found} field(s) found." => Some(("count-feature", "fields-found")),
|
||||
|
||||
Reference in new issue
Block a user