Порт редактора SimVulcan на Rust
Та же программа на ash + winit + egui: орбитальная камера, три плоскости сетки, загрузка .obj, три режима отображения, единый проход динамического рендеринга с глубинным вложением и submit через synchronization2. Шейдеры общие с C++-версией — build.rs компилирует их из shaders/ и вшивает SPIR-V в бинарь. Пять крейтов повторяют карту целей CMake, но инвариант «весь Vulkan в одном месте» теперь проверяет компилятор: у simv-mesh и simv-editor нет ash в зависимостях. Расхождения, вынужденные языком, а не вкусом: * App переехал в исполняемый крейт — в C++ граф целей цикличен (core владеет vk, vk принимает core::Window&), и держится это лишь на том, что simv_vk видит заголовки core, не линкуя цель; Cargo такой цикл отвергает; * состояние сцены возвращается из замыкания интерфейса, а не ставится сеттерами: замыкание вызывается из метода рендерера, трогать рендерер оттуда нельзя; * выгрузка меша на видеокарту уехала из середины записи кадра, где C++-версия зовёт vkDeviceWaitIdle уже после захвата образа цепочки показа. Vulkan-контекст и цепочка показа написаны руками: замены vk-bootstrap в экосистеме Rust нет. Обёртки Buffer и Image, лежащие в C++-версии без применения, здесь задействованы всеми потребителями. 13 тестов, из них три перенесены из Catch2 дословно. cargo clippy -D warnings чист, слой валидации молчит. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
//! Панель вьюпорта — перенос `simv::editor::EditorUI`.
|
||||
//!
|
||||
//! Про [`DisplayMode`]. Панель обязана как-то сообщить рендереру выбранный режим, но
|
||||
//! `simv_vk::RenderMode` ей недоступен: `simv-editor` не зависит от `simv-vk`, и это
|
||||
//! проверяет компилятор. C++ обходит ту же границу, возвращая из `EditorUI` голый
|
||||
//! `int`, который `main.cpp` приводит через `static_cast` к `vk::RenderMode` —
|
||||
//! связь между двумя перечислениями там держится на честном слове. Здесь у панели
|
||||
//! свой типизированный режим, а разбор в `simv_vk::RenderMode` делает `simv-app`
|
||||
//! обычным `match`: добавите вариант — компилятор укажет, где его дописать.
|
||||
|
||||
use crate::camera::{Camera, ViewPlane};
|
||||
|
||||
/// Как отображать модель. Соответствует `simv_vk::RenderMode`, но живёт по эту
|
||||
/// сторону границы модулей.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
pub enum DisplayMode {
|
||||
#[default]
|
||||
Solid,
|
||||
Wireframe,
|
||||
SolidWire,
|
||||
}
|
||||
|
||||
pub struct EditorUi {
|
||||
display_mode: DisplayMode,
|
||||
grid_visible: bool,
|
||||
}
|
||||
|
||||
impl Default for EditorUi {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
display_mode: DisplayMode::Solid,
|
||||
grid_visible: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EditorUi {
|
||||
pub fn display_mode(&self) -> DisplayMode {
|
||||
self.display_mode
|
||||
}
|
||||
|
||||
pub fn grid_visible(&self) -> bool {
|
||||
self.grid_visible
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, ctx: &egui::Context, camera: &mut Camera) {
|
||||
egui::Window::new("Viewport")
|
||||
.default_size([280.0, 200.0])
|
||||
.show(ctx, |ui| {
|
||||
ui.label(egui::RichText::new("Камера").weak());
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Спереди").clicked() {
|
||||
camera.align_to_plane(ViewPlane::Front);
|
||||
}
|
||||
if ui.button("Сверху").clicked() {
|
||||
camera.align_to_plane(ViewPlane::Top);
|
||||
}
|
||||
if ui.button("Сбоку").clicked() {
|
||||
camera.align_to_plane(ViewPlane::Side);
|
||||
}
|
||||
});
|
||||
ui.label(
|
||||
egui::RichText::new("Перетаскивание — поворот, колесо — приближение").weak(),
|
||||
);
|
||||
|
||||
ui.separator();
|
||||
ui.label(egui::RichText::new("Отображение модели").weak());
|
||||
ui.radio_value(&mut self.display_mode, DisplayMode::Solid, "Заливка");
|
||||
ui.radio_value(&mut self.display_mode, DisplayMode::Wireframe, "Каркас");
|
||||
ui.radio_value(
|
||||
&mut self.display_mode,
|
||||
DisplayMode::SolidWire,
|
||||
"Заливка с каркасом",
|
||||
);
|
||||
|
||||
ui.separator();
|
||||
ui.checkbox(&mut self.grid_visible, "Показывать сетку");
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user