@@ -6610,6 +6610,102 @@ namespace lfs::vis::gui {
66106610 now >= next_vram_hud_publish_);
66116611 }
66126612
6613+ void GuiManager::syncVisiblePanelsBeforeSceneRender () {
6614+ const std::uint64_t sync_generation = lfs::python::pre_scene_panel_sync_generation ();
6615+ if (sync_generation == 0 ||
6616+ sync_generation == last_pre_scene_panel_sync_generation_)
6617+ return ;
6618+ last_pre_scene_panel_sync_generation_ = sync_generation;
6619+
6620+ if (!viewer_ || !show_main_panel_ || ui_hidden_) {
6621+ return ;
6622+ }
6623+
6624+ auto & reg = PanelRegistry::instance ();
6625+ const auto main_tabs = reg.get_panels_for_space (PanelSpace::MainPanelTab);
6626+ if (main_tabs.empty ()) {
6627+ return ;
6628+ }
6629+
6630+ panel_layout_.syncActiveTab (main_tabs, focus_panel_name_);
6631+ const std::string& active_tab = panel_layout_.getActiveTab ();
6632+ if (active_tab.empty ()) {
6633+ return ;
6634+ }
6635+
6636+ const ImGuiViewport* const mvp = ImGui::GetMainViewport ();
6637+ if (!mvp || mvp->WorkSize .x <= 0 .0f || mvp->WorkSize .y <= 0 .0f ) {
6638+ return ;
6639+ }
6640+
6641+ auto & editor_ctx = viewer_->getEditorContext ();
6642+ auto * scene_manager = viewer_->getSceneManager ();
6643+ auto * trainer_manager = viewer_->getTrainerManager ();
6644+ editor_ctx.update (scene_manager, trainer_manager);
6645+
6646+ UIContext ctx{
6647+ .viewer = viewer_,
6648+ .window_states = &window_states_,
6649+ .editor = &editor_ctx,
6650+ .sequencer_controller = &sequencer_ui_.controller (),
6651+ .rml_manager = &rmlui_manager_,
6652+ .fonts = buildFontSet ()};
6653+
6654+ lfs::core::Scene* scene = nullptr ;
6655+ if (scene_manager)
6656+ scene = &scene_manager->getScene ();
6657+
6658+ PanelDrawContext draw_ctx;
6659+ draw_ctx.ui = &ctx;
6660+ draw_ctx.viewport = &viewport_layout_;
6661+ draw_ctx.scene = scene;
6662+ draw_ctx.ui_hidden = ui_hidden_;
6663+ draw_ctx.scene_generation = python::get_scene_generation ();
6664+ if (scene_manager)
6665+ draw_ctx.has_selection = scene_manager->hasSelectedNode ();
6666+ if (auto * cc = lfs::event::command_center ())
6667+ draw_ctx.is_training = cc->snapshot ().is_running ;
6668+
6669+ PanelInputState input;
6670+ input.mouse_x = -1 .0e9f;
6671+ input.mouse_y = -1 .0e9f;
6672+ input.screen_x = mvp->Pos .x ;
6673+ input.screen_y = mvp->Pos .y ;
6674+ input.screen_w = static_cast <int >(mvp->Size .x );
6675+ input.screen_h = static_cast <int >(mvp->Size .y );
6676+
6677+ const float dpi = lfs::python::get_shared_dpi_scale ();
6678+ const float panel_h = mvp->WorkSize .y - PanelLayoutManager::STATUS_BAR_HEIGHT * dpi;
6679+ if (panel_h <= 0 .0f ) {
6680+ return ;
6681+ }
6682+
6683+ constexpr float kPanelPad = 8 .0f ;
6684+ constexpr float kPreloadMaxHeight = 100000 .0f ;
6685+ const float content_w = panel_layout_.getRightPanelWidth () - 2 .0f * kPanelPad ;
6686+ if (content_w <= 0 .0f ) {
6687+ return ;
6688+ }
6689+
6690+ const float splitter_h = PanelLayoutManager::SPLITTER_H * dpi;
6691+ const float tab_bar_h = PanelLayoutManager::TAB_BAR_H * dpi;
6692+ const float avail_h = panel_h - 2 .0f * kPanelPad ;
6693+ const float scene_h =
6694+ std::max (80 .0f * dpi,
6695+ avail_h * panel_layout_.getScenePanelRatio () - splitter_h * 0 .5f );
6696+ const float content_top = mvp->WorkPos .y + kPanelPad ;
6697+ const float tab_content_y = content_top + scene_h + splitter_h + tab_bar_h;
6698+ const float tab_content_h =
6699+ std::max (0 .0f , content_top + avail_h - tab_content_y);
6700+ const float clip_y_min = tab_content_y;
6701+ const float clip_y_max = tab_content_y + tab_content_h;
6702+
6703+ reg.preload_single_panel_direct (active_tab, content_w, kPreloadMaxHeight , draw_ctx,
6704+ clip_y_min, clip_y_max, &input);
6705+ reg.preload_child_panels_direct (active_tab, content_w, kPreloadMaxHeight , draw_ctx,
6706+ clip_y_min, clip_y_max, &input);
6707+ }
6708+
66136709 bool GuiManager::needsAnimationFrame () const {
66146710 if (isViewportExportLocked ())
66156711 return true ;
0 commit comments