use crate::{
MainWindow, RetargetModel, SolidPreviewModel, ViewportModel,
bridge::render_thread::RenderContext,
gui::{solid_preview::preview_state::SolidPreviewState, tutorial_events::raise},
};
use indicatrix_editor::guide::viewing_events as events;
use slint::ComponentHandle;
use std::sync::{Arc, Mutex};
#[must_use]
const fn render_is_visible(
active_tab: i32,
render_view_tab: i32,
live_view_mode: i32,
solid_view_mode: i32,
modal_compare_open: bool,
) -> bool {
!modal_compare_open
&& active_tab == 0
&& ((render_view_tab == 0 && live_view_mode == 1)
|| (render_view_tab == 1 && (solid_view_mode == 1 || solid_view_mode == 2)))
}
pub(in crate::gui) fn recompute_tab_visible(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
) {
let visible = render_is_visible(
ui.get_active_tab(),
ui.get_render_view_tab(),
ui.global::<ViewportModel>().get_live_view_mode(),
ui.global::<SolidPreviewModel>().get_view_mode(),
ui.global::<RetargetModel>().get_is_open(),
);
let mut ctx = RenderContext::lock(render_ctx);
ctx.tab_visible = visible;
ctx.camera_drag_held = false;
}
pub(in crate::gui) fn setup_live_render_visibility_callbacks(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
) {
let render_ctx_at = render_ctx.clone();
let ui_weak_at = ui.as_weak();
ui.on_active_tab_changed(move |_tab| {
if let Some(ui) = ui_weak_at.upgrade() {
recompute_tab_visible(&ui, &render_ctx_at);
}
});
let render_ctx_rv = render_ctx.clone();
let preview_state_rv = Arc::clone(preview_state);
let ui_weak_rv = ui.as_weak();
ui.on_render_view_tab_changed(move |idx| {
if let Some(ui) = ui_weak_rv.upgrade() {
recompute_tab_visible(&ui, &render_ctx_rv);
if idx == 0 {
raise(&ui, events::LIVE_RENDER_OPENED);
}
let render_ctx_deferred = render_ctx_rv.clone();
let preview_state_deferred = Arc::clone(&preview_state_rv);
let ui_weak_deferred = ui.as_weak();
slint::Timer::single_shot(std::time::Duration::ZERO, move || {
let Some(ui) = ui_weak_deferred.upgrade() else {
return;
};
let ctx = render_ctx_deferred
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
crate::gui::render::camera_lighting::resubmit_at_current_pose(
&ui,
&ctx,
&preview_state_deferred,
);
});
}
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn live_render_sub_tab_traces_only_in_path_traced_mode() {
assert!(!render_is_visible(0, 0, 0, 0, false));
assert!(render_is_visible(0, 0, 1, 0, false));
}
#[test]
fn edit_sub_tab_traces_only_in_path_traced_or_both_mode() {
assert!(!render_is_visible(0, 1, 1, 0, false));
assert!(!render_is_visible(0, 1, 1, 3, false));
assert!(render_is_visible(0, 1, 1, 1, false));
assert!(render_is_visible(0, 1, 1, 2, false));
}
#[test]
fn never_visible_outside_the_3d_tab() {
for render_view_tab in [0, 1] {
for live_view_mode in [0, 1] {
for solid_view_mode in [0, 1, 2, 3] {
assert!(!render_is_visible(
1,
render_view_tab,
live_view_mode,
solid_view_mode,
false
));
assert!(!render_is_visible(
2,
render_view_tab,
live_view_mode,
solid_view_mode,
false
));
}
}
}
}
#[test]
fn an_open_modal_comparison_pauses_the_viewport_in_every_configuration() {
for active_tab in [0, 1, 2] {
for render_view_tab in [0, 1] {
for live_view_mode in [0, 1] {
for solid_view_mode in [0, 1, 2, 3] {
assert!(!render_is_visible(
active_tab,
render_view_tab,
live_view_mode,
solid_view_mode,
true
));
}
}
}
}
}
#[test]
fn closing_the_modal_comparison_restores_the_prior_visibility() {
assert!(render_is_visible(0, 0, 1, 0, false));
assert!(!render_is_visible(0, 0, 1, 0, true));
assert!(render_is_visible(0, 0, 1, 0, false));
}
}