Restore the upstream idle-loop dirty handling

This commit is contained in:
SoftFever
2026-08-28 02:19:41 +08:00
parent b9f8e825ac
commit 62f49bd105
2 changed files with 14 additions and 31 deletions
+13 -28
View File
@@ -3237,19 +3237,9 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
// BBS // BBS
//m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); //m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state(); m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state();
// ONLY THE CANVAS THE USER IS LOOKING AT MAY CONSUME THE 3D-MOUSE QUEUE. apply() DRAINS the // apply() DRAINS the 3D-mouse queue, so only the canvas actually on screen may call it: a
// queue, and every bound canvas idles — but a hidden canvas's render() early-returns on // hidden canvas renders nothing, so the motion it swallowed moves the shared camera without
// _is_shown_on_screen(), so the motion it swallowed is applied to the SHARED camera and never // ever being drawn and the next visible frame jumps several states at once.
// drawn. The next visible frame then jumps by more than one state change at once.
//
// The plater avoids this by binding exactly one of its three views at a time (Plater.cpp,
// around the current_panel switch). The Design tab's canvas binds once at construction and
// never unbinds, so from the moment it exists two canvases drain the same queue. Reported
// upstream as the SpaceMouse being "more severe lag, and jerkyness vs really smooth on the
// other tab ... its more than 1 state change" (OrcaSlicer PR #15238).
//
// Guarding here rather than at the bind sites fixes the whole class: whatever is bound, only
// the visible canvas takes motion off the queue.
bool mouse3d_controller_applied = _is_shown_on_screen() bool mouse3d_controller_applied = _is_shown_on_screen()
&& wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); && wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
m_dirty |= mouse3d_controller_applied; m_dirty |= mouse3d_controller_applied;
@@ -3288,10 +3278,7 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
m_last_frame_start_time = now; m_last_frame_start_time = now;
} }
// Not on screen yet (e.g. the notebook is still showing this page): nothing was rendered, _refresh_if_shown_on_screen();
// so keep the frame pending instead of dropping it — clearing m_dirty here leaves the
// canvas blank until some later event happens to dirty it again.
const bool rendered = _refresh_if_shown_on_screen();
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
if (m_extra_frame_requested || mouse3d_controller_applied || imgui_requires_extra_frame || wxGetApp().imgui()->requires_extra_frame()) { if (m_extra_frame_requested || mouse3d_controller_applied || imgui_requires_extra_frame || wxGetApp().imgui()->requires_extra_frame()) {
@@ -3303,7 +3290,7 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
evt.RequestMore(); evt.RequestMore();
} }
else else
m_dirty = !rendered; m_dirty = false;
} }
void GLCanvas3D::on_char(wxKeyEvent& evt) void GLCanvas3D::on_char(wxKeyEvent& evt)
@@ -7376,18 +7363,16 @@ void GLCanvas3D::_update_camera_zoom(double zoom)
m_dirty = true; m_dirty = true;
} }
bool GLCanvas3D::_refresh_if_shown_on_screen() void GLCanvas3D::_refresh_if_shown_on_screen()
{ {
if (!_is_shown_on_screen()) if (_is_shown_on_screen()) {
return false; const Size& cnv_size = get_canvas_size();
_resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
const Size& cnv_size = get_canvas_size(); // Because of performance problems on macOS, where PaintEvents are not delivered
_resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height()); // frequently enough, we call render() here directly when we can.
render();
// Because of performance problems on macOS, where PaintEvents are not delivered }
// frequently enough, we call render() here directly when we can.
render();
return true;
} }
void GLCanvas3D::_picking_pass() void GLCanvas3D::_picking_pass()
+1 -3
View File
@@ -1279,9 +1279,7 @@ private:
void _zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultCameraZoomToBoxMarginFactor); void _zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultCameraZoomToBoxMarginFactor);
void _update_camera_zoom(double zoom); void _update_camera_zoom(double zoom);
// Returns false when the canvas is not on screen yet and therefore nothing was rendered, void _refresh_if_shown_on_screen();
// so callers can keep it dirty instead of dropping the pending frame.
bool _refresh_if_shown_on_screen();
void _picking_pass(); void _picking_pass();
void _rectangular_selection_picking_pass(); void _rectangular_selection_picking_pass();