feat(viewport): model-space tiled split (▤ / ▥ buttons)

Model layout artık tiled viewport destekliyor. Scene.model_tiles
normalized ekran rect'i + kamera tutan tile listesi; active_viewports
model layout'ta her tile için bir ViewportInstance üretiyor (aktif tile
canlı scene.camera'yı, inaktif tile'lar saklı snapshot'ı kullanıyor).

Render-mode picker'ın yanına iki buton eklendi: ▤ aktif tile'ı yatay
(üst/alt), ▥ dikey (sol/sağ) ikiye böler. split_active_model_tile
bölmeyi yapıyor; her iki yarı aktif kameranın kopyasını alıyor.

set_active_model_tile_at (cursor → aktif tile, kamera swap) ve
reset_model_tiles eklendi ama henüz bağlanmadı — aktif tile cursor
seçimi + pick yönlendirme sonraki adımda.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.7 committed 2026-05-27 22:33:36 +03:00
1 parent c83726c037
commit c45146bbda
4 files changed
+205 -13

No files matched your search

+3
View File
@@ -355,6 +355,9 @@ pub enum Message {
CommandBackspace,
/// TAB pressed: move focus to the next dynamic-input field (wraps).
DynTabNext,
/// Split the active Model viewport in two. `true` → horizontal divider
/// (top / bottom); `false` → vertical divider (left / right).
SplitModelViewport(bool),
/// Recall previous command in history (↑ arrow key).
CommandHistoryPrev,
/// Recall next command in history (↓ arrow key).
+7
View File
@@ -916,6 +916,13 @@ impl OpenCADStudio {
self.focus_cmd_input()
}
Message::SplitModelViewport(horizontal) => {
let i = self.active_tab;
self.tabs[i].scene.split_active_model_tile(horizontal);
self.tabs[i].scene.camera_generation += 1;
Task::none()
}
Message::CommandHistoryPrev => {
// While autocomplete is showing suggestions, ↑ walks up
// that list. Otherwise it falls back to recall history.
+47 -1
View File
@@ -483,8 +483,54 @@ impl OpenCADStudio {
// viewport drawing / selection is unaffected. In a paper layout
// the active viewport gets its own picker (below) instead.
if !is_paper && !tab.is_start {
// Render-mode picker + viewport-split buttons (horizontal /
// vertical divider of the active Model tile).
let split_btn = |glyph: &'static str, horizontal: bool| {
button(text(glyph).size(13).color(Color {
r: 0.85,
g: 0.85,
b: 0.85,
a: 1.0,
}))
.on_press(Message::SplitModelViewport(horizontal))
.padding([4, 8])
.style(|_: &Theme, status| iced::widget::button::Style {
background: Some(Background::Color(match status {
iced::widget::button::Status::Hovered => Color {
r: 0.20,
g: 0.20,
b: 0.20,
a: 0.85,
},
_ => Color {
r: 0.10,
g: 0.10,
b: 0.10,
a: 0.75,
},
})),
border: Border {
color: Color {
r: 0.35,
g: 0.35,
b: 0.35,
a: 1.0,
},
width: 1.0,
radius: 4.0.into(),
},
text_color: Color {
r: 0.85,
g: 0.85,
b: 0.85,
a: 1.0,
},
..Default::default()
})
};
let bar = row![info, split_btn("▤", true), split_btn("▥", false)].spacing(4);
viewport_stack = viewport_stack.push(
container(iced::widget::opaque(info))
container(iced::widget::opaque(bar))
.width(Fill)
.height(Fill)
.align_x(iced::alignment::Horizontal::Left)