feat(viewport): interactive VPORTS model tiled presets
Model space'de VPORTS artık iki aşamalı: bare VPORTS bir yapılandırma istiyor (SIngle/2H/2V/4), sonraki komut-satırı girdisi düzeni kuruyor (boş giriş = SINGLE). set_model_tile_layout normalized rect listesiyle tiled düzeni değiştiriyor: - SINGLE: tek tam-ekran - 2H: üst/alt - 2V: sol/sağ - 4: 2x2 awaiting_vports app flag'i prompt sonrası girdiyi yakalıyor. Paper-space VPORTS davranışı değişmedi. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
41c75dbb9b
commit
6fe25e4b5f
4 changed files with 79 additions and 13 deletions
|
|
@ -2663,8 +2663,48 @@ impl OpenCADStudio {
|
||||||
let sub = cmd.split_whitespace().nth(1).unwrap_or("").to_uppercase();
|
let sub = cmd.split_whitespace().nth(1).unwrap_or("").to_uppercase();
|
||||||
let scene = &self.tabs[i].scene;
|
let scene = &self.tabs[i].scene;
|
||||||
if scene.current_layout == "Model" {
|
if scene.current_layout == "Model" {
|
||||||
self.command_line
|
// Bare VPORTS → ask for the configuration interactively;
|
||||||
.push_error("VPORTS: switch to a paper space layout first.");
|
// the next command-line entry supplies it.
|
||||||
|
if sub.is_empty() {
|
||||||
|
self.awaiting_vports = true;
|
||||||
|
self.command_line
|
||||||
|
.push_info("VPORTS Configuration [SIngle/2H/2V/4]:");
|
||||||
|
return self.focus_cmd_input();
|
||||||
|
}
|
||||||
|
// Model space: split the tiled viewport layout.
|
||||||
|
use iced::Rectangle as R;
|
||||||
|
let full = R { x: 0.0, y: 0.0, width: 1.0, height: 1.0 };
|
||||||
|
let rects: Option<Vec<R>> = match sub.as_str() {
|
||||||
|
"SINGLE" | "SI" | "1" => Some(vec![full]),
|
||||||
|
"2H" | "2" => Some(vec![
|
||||||
|
R { x: 0.0, y: 0.0, width: 1.0, height: 0.5 },
|
||||||
|
R { x: 0.0, y: 0.5, width: 1.0, height: 0.5 },
|
||||||
|
]),
|
||||||
|
"2V" => Some(vec![
|
||||||
|
R { x: 0.0, y: 0.0, width: 0.5, height: 1.0 },
|
||||||
|
R { x: 0.5, y: 0.0, width: 0.5, height: 1.0 },
|
||||||
|
]),
|
||||||
|
"4" => Some(vec![
|
||||||
|
R { x: 0.0, y: 0.0, width: 0.5, height: 0.5 },
|
||||||
|
R { x: 0.5, y: 0.0, width: 0.5, height: 0.5 },
|
||||||
|
R { x: 0.0, y: 0.5, width: 0.5, height: 0.5 },
|
||||||
|
R { x: 0.5, y: 0.5, width: 0.5, height: 0.5 },
|
||||||
|
]),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
match rects {
|
||||||
|
Some(rects) => {
|
||||||
|
let n = rects.len();
|
||||||
|
self.tabs[i].scene.set_model_tile_layout(rects);
|
||||||
|
self.tabs[i].scene.camera_generation += 1;
|
||||||
|
self.command_line
|
||||||
|
.push_output(&format!("VPORTS: {n} viewport(s)."));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.command_line
|
||||||
|
.push_error("VPORTS: use SINGLE | 2H | 2V | 4.");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if sub.is_empty() {
|
} else if sub.is_empty() {
|
||||||
// ── List existing viewports ──────────────────────────
|
// ── List existing viewports ──────────────────────────
|
||||||
let layout_block = scene.current_layout_block_handle_pub();
|
let layout_block = scene.current_layout_block_handle_pub();
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,9 @@ pub(super) struct OpenCADStudio {
|
||||||
show_grid: bool,
|
show_grid: bool,
|
||||||
/// Dynamic input overlay (F12): show coordinate tooltip near cursor.
|
/// Dynamic input overlay (F12): show coordinate tooltip near cursor.
|
||||||
dyn_input: bool,
|
dyn_input: bool,
|
||||||
|
/// `true` after a bare `VPORTS` in model space — the next command-line
|
||||||
|
/// entry is treated as the tiled-config option (SIngle/2H/2V/4).
|
||||||
|
awaiting_vports: bool,
|
||||||
/// Show the UCS icon in the bottom-left corner of model space (UCSICON).
|
/// Show the UCS icon in the bottom-left corner of model space (UCSICON).
|
||||||
show_ucs_icon: bool,
|
show_ucs_icon: bool,
|
||||||
/// Whether the ViewCube 3D gizmo is visible in model space (NAVVCUBE).
|
/// Whether the ViewCube 3D gizmo is visible in model space (NAVVCUBE).
|
||||||
|
|
@ -743,6 +746,7 @@ impl OpenCADStudio {
|
||||||
polar_increment_deg: 45.0,
|
polar_increment_deg: 45.0,
|
||||||
show_grid: false,
|
show_grid: false,
|
||||||
dyn_input: true,
|
dyn_input: true,
|
||||||
|
awaiting_vports: false,
|
||||||
show_ucs_icon: true,
|
show_ucs_icon: true,
|
||||||
show_viewcube: true,
|
show_viewcube: true,
|
||||||
show_properties: true,
|
show_properties: true,
|
||||||
|
|
|
||||||
|
|
@ -963,6 +963,15 @@ impl OpenCADStudio {
|
||||||
// dropdown so the dispatched command's new prompt is
|
// dropdown so the dispatched command's new prompt is
|
||||||
// immediately visible on the overlay.
|
// immediately visible on the overlay.
|
||||||
self.command_line.close_history();
|
self.command_line.close_history();
|
||||||
|
// Interactive VPORTS: the entry after a bare `VPORTS` is the
|
||||||
|
// tiled configuration. Empty input defaults to SINGLE.
|
||||||
|
if self.awaiting_vports {
|
||||||
|
self.awaiting_vports = false;
|
||||||
|
let cfg = self.command_line.input.trim().to_string();
|
||||||
|
self.command_line.input.clear();
|
||||||
|
let cfg = if cfg.is_empty() { "SINGLE".to_string() } else { cfg };
|
||||||
|
return self.dispatch_command(&format!("VPORTS {cfg}"));
|
||||||
|
}
|
||||||
// If the user navigated the autocomplete list with the
|
// If the user navigated the autocomplete list with the
|
||||||
// arrow keys, Enter dispatches the highlighted command
|
// arrow keys, Enter dispatches the highlighted command
|
||||||
// rather than the partial text actually in the buffer.
|
// rather than the partial text actually in the buffer.
|
||||||
|
|
|
||||||
|
|
@ -4362,18 +4362,31 @@ impl Scene {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset the Model layout to a single full-window tile.
|
/// Replace the Model tiled layout with the given normalized rectangles
|
||||||
pub fn reset_model_tiles(&self) {
|
/// (each in 0..1). Every tile inherits the current camera; the first
|
||||||
|
/// tile becomes active. Used by VPORTS presets and `reset_model_tiles`.
|
||||||
|
pub fn set_model_tile_layout(&self, rects: Vec<iced::Rectangle>) {
|
||||||
let cam_now = self.camera.borrow().clone();
|
let cam_now = self.camera.borrow().clone();
|
||||||
*self.model_tiles.borrow_mut() = vec![ModelTile {
|
let tiles: Vec<ModelTile> = rects
|
||||||
rect: iced::Rectangle {
|
.into_iter()
|
||||||
x: 0.0,
|
.map(|rect| ModelTile {
|
||||||
y: 0.0,
|
rect,
|
||||||
width: 1.0,
|
camera: cam_now.clone(),
|
||||||
height: 1.0,
|
})
|
||||||
},
|
.collect();
|
||||||
camera: cam_now,
|
*self.model_tiles.borrow_mut() = if tiles.is_empty() {
|
||||||
}];
|
vec![ModelTile {
|
||||||
|
rect: iced::Rectangle {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: 1.0,
|
||||||
|
height: 1.0,
|
||||||
|
},
|
||||||
|
camera: cam_now,
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
tiles
|
||||||
|
};
|
||||||
self.active_model_tile.set(0);
|
self.active_model_tile.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue