Release the Reduced Set When Unused and Share the Drag Check With the Scene Cache

The reduced index buffers were only re-uploaded while the preference was on, so
the last set stayed allocated until the next load once it was switched off, and
their size was missing from get_used_gpu_memory(). They are now uploaded on every
rebuild, empty when nothing was built, and counted.

The scene cache and the solid model both asked whether the user was dragging,
with different lists: the cache knew about gizmos and the rectangle selection,
the solid model about the navigator and the sliders. One is_user_interacting()
now answers both.

The tooltip says that negative volumes are not cut out of the solid model, since
load_shells() drops every non-model-part volume, and the preferences handler
keeps the dimming comment with the branch it documents.
This commit is contained in:
Hanif Koh
2026-09-23 12:13:49 +08:00
parent 6a985744c4
commit ca83497bb6
6 changed files with 46 additions and 29 deletions
+16 -10
View File
@@ -901,6 +901,8 @@ void ViewerImpl::reset()
m_enabled_options_count = 0;
m_enabled_segments_reduced_count = 0;
m_enabled_options_reduced_count = 0;
m_enabled_segments_reduced_tex_size = 0;
m_enabled_options_reduced_tex_size = 0;
m_settings_used_for_ranges = std::nullopt;
@@ -1286,18 +1288,20 @@ void ViewerImpl::update_enabled_entities()
m_enabled_segments_reduced_count = enabled_segments_reduced.size();
m_enabled_options_reduced_count = enabled_options_reduced.size();
m_enabled_segments_reduced_tex_size = enabled_segments_reduced.size() * sizeof(uint32_t);
m_enabled_options_reduced_tex_size = enabled_options_reduced.size() * sizeof(uint32_t);
if (build_reduced) {
assert(m_enabled_segments_reduced_buf_id > 0);
glsafe(glBindBuffer(GL_TEXTURE_BUFFER, m_enabled_segments_reduced_buf_id));
glsafe(glBufferData(GL_TEXTURE_BUFFER, enabled_segments_reduced.size() * sizeof(uint32_t),
enabled_segments_reduced.empty() ? nullptr : enabled_segments_reduced.data(), GL_STATIC_DRAW));
// uploaded even when nothing was built, so that the last reduced set is released as soon as
// the preference is switched off
assert(m_enabled_segments_reduced_buf_id > 0);
glsafe(glBindBuffer(GL_TEXTURE_BUFFER, m_enabled_segments_reduced_buf_id));
glsafe(glBufferData(GL_TEXTURE_BUFFER, m_enabled_segments_reduced_tex_size,
enabled_segments_reduced.empty() ? nullptr : enabled_segments_reduced.data(), GL_STATIC_DRAW));
assert(m_enabled_options_reduced_buf_id > 0);
glsafe(glBindBuffer(GL_TEXTURE_BUFFER, m_enabled_options_reduced_buf_id));
glsafe(glBufferData(GL_TEXTURE_BUFFER, enabled_options_reduced.size() * sizeof(uint32_t),
enabled_options_reduced.empty() ? nullptr : enabled_options_reduced.data(), GL_STATIC_DRAW));
}
assert(m_enabled_options_reduced_buf_id > 0);
glsafe(glBindBuffer(GL_TEXTURE_BUFFER, m_enabled_options_reduced_buf_id));
glsafe(glBufferData(GL_TEXTURE_BUFFER, m_enabled_options_reduced_tex_size,
enabled_options_reduced.empty() ? nullptr : enabled_options_reduced.data(), GL_STATIC_DRAW));
glsafe(glBindBuffer(GL_TEXTURE_BUFFER, 0));
#endif // ENABLE_OPENGL_ES
@@ -1907,6 +1911,8 @@ size_t ViewerImpl::get_used_gpu_memory() const
ret += m_colors_tex_size;
ret += m_enabled_segments_tex_size;
ret += m_enabled_options_tex_size;
ret += m_enabled_segments_reduced_tex_size;
ret += m_enabled_options_reduced_tex_size;
#endif // ENABLE_OPENGL_ES
return ret;
}
+2
View File
@@ -528,6 +528,8 @@ private:
size_t m_colors_tex_size{ 0 };
size_t m_enabled_segments_tex_size{ 0 };
size_t m_enabled_options_tex_size{ 0 };
size_t m_enabled_segments_reduced_tex_size{ 0 };
size_t m_enabled_options_reduced_tex_size{ 0 };
// The set the next draw reads from: the reduced one while dragging, if one is built.
bool use_reduced_set() const { return m_settings.reduced_detail && m_settings.reduced_detail_enabled; }
+2
View File
@@ -372,6 +372,8 @@ public:
void set_dim_previous_layers_brightness(float value) { m_viewer.set_dim_previous_layers_brightness(value); }
float get_dim_previous_layers_brightness() const { return m_viewer.get_dim_previous_layers_brightness(); }
// whether the mouse is holding either slider's handle
bool is_slider_dragging() const { return m_layers_slider->is_dragging() || m_moves_slider->is_dragging(); }
// while the user drags the camera or a slider, draw the solid model, if the preference asks for it
void set_interacting(bool interacting);
bool is_reduced_detail() const { return m_viewer.is_reduced_detail(); }
+12 -7
View File
@@ -7737,13 +7737,20 @@ bool GLCanvas3D::_is_scene_cacheable() const
return false;
#endif
// The scene follows the cursor during a drag, under a gizmo that draws at the cursor, and while
// the cursor is on the layer height bar, where the object shader draws a band at its height.
// The scene follows the cursor while the user drags, under a gizmo that draws at the cursor, and
// while the cursor is on the layer height bar, where the object shader draws a band at its height.
const GLGizmoBase* gizmo = m_gizmos.get_current();
const bool cursor_on_layers_bar = is_layers_editing_enabled() &&
m_layers_editing.bar_rect_contains(*this, (float)m_mouse.position.x(), (float)m_mouse.position.y());
return !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging() &&
(gizmo == nullptr || !gizmo->render_follows_cursor()) && !cursor_on_layers_bar;
return !is_user_interacting() && (gizmo == nullptr || !gizmo->render_follows_cursor()) && !cursor_on_layers_bar;
}
// Whether the user is holding something that moves the scene: the camera, the navigator, a gizmo,
// the rectangle selection or a preview slider.
bool GLCanvas3D::is_user_interacting() const
{
return m_mouse.dragging || m_navigator_dragging || m_gizmos.is_dragging() || m_rectangle_selection.is_dragging() ||
m_gcode_viewer.is_slider_dragging();
}
bool GLCanvas3D::_is_frame_skipping_enabled() const
@@ -8740,11 +8747,9 @@ void GLCanvas3D::_render_wireframe_overlay()
// pass draws changed, since a frame that reuses the cached scene would hide the change.
bool GLCanvas3D::_update_preview_interaction()
{
IMSlider* layers_slider = m_gcode_viewer.get_layers_slider();
IMSlider* moves_slider = m_gcode_viewer.get_moves_slider();
const auto now = std::chrono::steady_clock::now();
const bool settling = now < m_preview_interaction_until;
const bool dragging = m_mouse.dragging || m_navigator_dragging || layers_slider->is_dragging() || moves_slider->is_dragging();
const bool dragging = is_user_interacting();
const bool was_reduced = m_gcode_viewer.is_reduced_detail();
m_gcode_viewer.set_interacting(dragging || settling);
if (settling && !dragging && m_gcode_viewer.is_reduced_detail()) {
+2
View File
@@ -1219,6 +1219,8 @@ public:
void msw_rescale() { m_gcode_viewer.invalidate_legend(); }
void request_extra_frame() { m_extra_frame_requested = true; }
// whether the user is holding the camera, the navigator, a gizmo, the rectangle selection or a preview slider
bool is_user_interacting() const;
// a wheel step is over before the next frame, so it holds the preview's solid model for a settle time
void note_preview_interaction();
+12 -12
View File
@@ -1049,16 +1049,6 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too
}
}
// ORCA: apply the preview dimming change immediately to the currently loaded preview
// apply the solid model preference immediately to the currently loaded preview
else if (param == "preview_solid_model_while_dragging") {
if (Plater* plater = wxGetApp().plater()) {
if (GLCanvas3D* canvas = plater->get_preview_canvas3D()) {
canvas->get_gcode_viewer().set_solid_model_while_dragging(app_config->get_bool(param));
canvas->set_as_dirty();
canvas->request_extra_frame();
}
}
}
else if (param == "preview_dim_previous_layers") {
if (m_dim_previous_layers_brightness_input)
m_dim_previous_layers_brightness_input->Enable(app_config->get_bool(param));
@@ -1070,6 +1060,16 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too
}
}
}
// apply the solid model preference immediately to the currently loaded preview
else if (param == "preview_solid_model_while_dragging") {
if (Plater* plater = wxGetApp().plater()) {
if (GLCanvas3D* canvas = plater->get_preview_canvas3D()) {
canvas->get_gcode_viewer().set_solid_model_while_dragging(app_config->get_bool(param));
canvas->set_as_dirty();
canvas->request_extra_frame();
}
}
}
#ifdef __WXMSW__
if (param == "associate_3mf") {
@@ -2058,8 +2058,8 @@ void PreferencesDialog::create_items()
auto item_solid_model_while_dragging = create_item_checkbox(
_L("Only render solid model when dragging"),
_L("While dragging the camera or a preview slider, or zooming with the mouse wheel, draw the sliced objects and the prime tower as solid shapes "
"in their filament colours instead of toolpaths, so that large prints stay responsive. They are cut to the visible layer range, with its bottom "
"and top layers drawn as toolpaths. Supports are not shown. The toolpaths are restored as soon as you let go."),
"in their filament colors instead of toolpaths, so that large prints stay responsive. They are cut to the visible layer range, with its bottom "
"and top layers drawn as toolpaths. Supports are not shown, and negative volumes are not cut out. The toolpaths are restored as soon as you let go."),
"preview_solid_model_while_dragging"
);
g_sizer->Add(item_solid_model_while_dragging);