Dim lower layers (#14705)

This commit is contained in:
Ian Bassi
2026-07-20 18:14:01 -03:00
committed by GitHub
parent e28b5dae94
commit 4e4e867502
9 changed files with 103 additions and 6 deletions
+4
View File
@@ -202,6 +202,10 @@ void AppConfig::set_defaults()
if (get("seq_top_layer_only").empty()) if (get("seq_top_layer_only").empty())
set("seq_top_layer_only", "1"); set("seq_top_layer_only", "1");
// ORCA: darken layers below the current one while scrubbing the preview (ported from preFlight)
if (get("preview_dim_previous_layers").empty())
set_bool("preview_dim_previous_layers", false);
if (get("filaments_area_preferred_count").empty()) if (get("filaments_area_preferred_count").empty())
set("filaments_area_preferred_count", "10"); set("filaments_area_preferred_count", "10");
+7
View File
@@ -91,6 +91,13 @@ public:
// //
void toggle_top_layer_only_view_range(); void toggle_top_layer_only_view_range();
// //
// Dim previous layers (ORCA, ported from preFlight)
// Whether the layers below the current top layer are rendered darkened while
// scrubbing below the full print, so only the current layer is shown at full brightness.
//
bool is_dim_previous_layers() const;
void set_dim_previous_layers(bool value);
//
// Returns true if the given option is visible. // Returns true if the given option is visible.
// //
bool is_option_visible(EOptionType type) const; bool is_option_visible(EOptionType type) const;
+3
View File
@@ -19,6 +19,9 @@ struct Settings
EViewType view_type{ EViewType::FeatureType }; EViewType view_type{ EViewType::FeatureType };
ETimeMode time_mode{ ETimeMode::Normal }; ETimeMode time_mode{ ETimeMode::Normal };
bool top_layer_only_view_range{ false }; bool top_layer_only_view_range{ false };
// ORCA: when enabled, all layers below the current top layer are rendered
// darkened (keeping their color) while scrubbing below the full print (ported from preFlight)
bool dim_previous_layers{ false };
bool spiral_vase_mode{ false }; bool spiral_vase_mode{ false };
// //
// Required update flags // Required update flags
+10
View File
@@ -72,6 +72,16 @@ void Viewer::toggle_top_layer_only_view_range()
m_impl->toggle_top_layer_only_view_range(); m_impl->toggle_top_layer_only_view_range();
} }
bool Viewer::is_dim_previous_layers() const
{
return m_impl->is_dim_previous_layers();
}
void Viewer::set_dim_previous_layers(bool value)
{
m_impl->set_dim_previous_layers(value);
}
bool Viewer::is_option_visible(EOptionType type) const bool Viewer::is_option_visible(EOptionType type) const
{ {
return m_impl->is_option_visible(type); return m_impl->is_option_visible(type);
+46 -5
View File
@@ -1223,6 +1223,20 @@ static float encode_color(const Color& color) {
return static_cast<float>(i_color); return static_cast<float>(i_color);
} }
// ORCA: how much the layers below the current top layer are darkened when
// Settings::dim_previous_layers is enabled (ported from preFlight). 0.0 = no change, 1.0 = black.
static constexpr float PREVIOUS_LAYER_DARKEN_FACTOR = 0.60f;
// ORCA: returns the encoded color scaled towards black by 'factor', preserving its hue
static float encode_color_darkened(const Color& color, float factor) {
const float keep = 1.0f - factor;
const int r = static_cast<int>(color[0] * keep);
const int g = static_cast<int>(color[1] * keep);
const int b = static_cast<int>(color[2] * keep);
const int i_color = r << 16 | g << 8 | b;
return static_cast<float>(i_color);
}
void ViewerImpl::update_colors_texture() void ViewerImpl::update_colors_texture()
{ {
@@ -1234,14 +1248,30 @@ void ViewerImpl::update_colors_texture()
const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0;
const bool color_top_layer_only = m_view_range.get_full()[1] != m_view_range.get_visible()[1]; const bool color_top_layer_only = m_view_range.get_full()[1] != m_view_range.get_visible()[1];
// ORCA: when dim_previous_layers is enabled, darken every layer below the current top layer
// (keeping its color) whenever we are not rendering the whole print, so that only the layer
// being scrubbed to is shown at full brightness (ported from preFlight). This shares
// top_layer_id with the greying path, so it only applies while in top-layer-only mode - that
// way the moves slider still animates normally across all layers when that mode is disabled.
const bool dim_previous_layers = m_settings.dim_previous_layers && !m_layers.empty();
const bool full_render = (m_layers.get_view_range()[0] == 0) &&
(m_layers.get_view_range()[1] >= static_cast<uint32_t>(m_layers.count()) - 1) &&
(m_view_range.get_visible()[1] == m_view_range.get_full()[1]);
// Based on current settings and slider position, we might want to render some // Based on current settings and slider position, we might want to render some
// vertices as dark grey. Use either that or the normal color (from the cache). // vertices as dark grey (or darkened, see above). Use either that or the normal color (from the cache).
std::vector<float> colors(m_vertices_colors.size()); std::vector<float> colors(m_vertices_colors.size());
assert(colors.size() == m_vertices.size() && m_vertices_colors.size() == m_vertices.size()); assert(colors.size() == m_vertices.size() && m_vertices_colors.size() == m_vertices.size());
for (size_t i=0; i<m_vertices.size(); ++i) for (size_t i=0; i<m_vertices.size(); ++i) {
colors[i] = (color_top_layer_only && m_vertices[i].layer_id < top_layer_id && const PathVertex& v = m_vertices[i];
(!m_settings.spiral_vase_mode || i != m_view_range.get_enabled()[0])) ? const bool keep_spiral_seam = m_settings.spiral_vase_mode && i == m_view_range.get_enabled()[0];
encode_color(DUMMY_COLOR) : m_vertices_colors[i]; if (dim_previous_layers && !full_render && v.layer_id < top_layer_id && !keep_spiral_seam)
colors[i] = encode_color_darkened(get_vertex_color(v), PREVIOUS_LAYER_DARKEN_FACTOR);
else if (color_top_layer_only && v.layer_id < top_layer_id && !keep_spiral_seam)
colors[i] = encode_color(DUMMY_COLOR);
else
colors[i] = m_vertices_colors[i];
}
#ifdef ENABLE_OPENGL_ES #ifdef ENABLE_OPENGL_ES
if (!colors.empty()) if (!colors.empty())
@@ -1349,6 +1379,17 @@ void ViewerImpl::toggle_top_layer_only_view_range()
update_colors_texture(); update_colors_texture();
} }
// ORCA: enable/disable darkening of the layers below the current top layer (ported from preFlight)
void ViewerImpl::set_dim_previous_layers(bool value)
{
if (m_settings.dim_previous_layers == value)
return;
m_settings.dim_previous_layers = value;
// defer the actual color/texture rebuild to the next render(), when the GL context is current
// (this may be toggled from the Preferences dialog, outside the canvas context)
m_settings.update_colors = true;
}
std::vector<ETimeMode> ViewerImpl::get_time_modes() const std::vector<ETimeMode> ViewerImpl::get_time_modes() const
{ {
std::vector<ETimeMode> ret; std::vector<ETimeMode> ret;
+4
View File
@@ -85,6 +85,10 @@ public:
bool is_top_layer_only_view_range() const { return m_settings.top_layer_only_view_range; } bool is_top_layer_only_view_range() const { return m_settings.top_layer_only_view_range; }
void toggle_top_layer_only_view_range(); void toggle_top_layer_only_view_range();
// ORCA: darken layers below the current top layer while scrubbing (ported from preFlight)
bool is_dim_previous_layers() const { return m_settings.dim_previous_layers; }
void set_dim_previous_layers(bool value);
bool is_spiral_vase_mode() const { return m_settings.spiral_vase_mode; } bool is_spiral_vase_mode() const { return m_settings.spiral_vase_mode; }
std::vector<ETimeMode> get_time_modes() const; std::vector<ETimeMode> get_time_modes() const;
+3
View File
@@ -1134,6 +1134,9 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
if (current_top_layer_only != required_top_layer_only) if (current_top_layer_only != required_top_layer_only)
m_viewer.toggle_top_layer_only_view_range(); m_viewer.toggle_top_layer_only_view_range();
// ORCA: darken layers below the current one while scrubbing the preview (ported from preFlight)
m_viewer.set_dim_previous_layers(get_app_config()->get_bool("preview_dim_previous_layers"));
// avoid processing if called with the same gcode_result // avoid processing if called with the same gcode_result
if (m_last_result_id == gcode_result.id && wxGetApp().is_editor()) { if (m_last_result_id == gcode_result.id && wxGetApp().is_editor()) {
//BBS: add logs //BBS: add logs
+4
View File
@@ -333,6 +333,10 @@ public:
libvgcode::EViewType get_view_type() const { return m_viewer.get_view_type(); } libvgcode::EViewType get_view_type() const { return m_viewer.get_view_type(); }
// ORCA: darken layers below the current top layer while scrubbing the preview (ported from preFlight)
void set_dim_previous_layers(bool value) { m_viewer.set_dim_previous_layers(value); }
bool is_dim_previous_layers() const { return m_viewer.is_dim_previous_layers(); }
void set_layers_z_range(const std::array<unsigned int, 2>& layers_z_range); void set_layers_z_range(const std::array<unsigned int, 2>& layers_z_range);
bool is_legend_shown() const { return m_legend_visible && m_legend_enabled; } bool is_legend_shown() const { return m_legend_visible && m_legend_enabled; }
+22 -1
View File
@@ -3,6 +3,7 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "GLCanvas3D.hpp" // ORCA: for live preview refresh when toggling "Dim lower layers"
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
@@ -1049,6 +1050,16 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too
wxGetApp().mainframe->m_webview->SendCloudProvidersInfo(); wxGetApp().mainframe->m_webview->SendCloudProvidersInfo();
} }
} }
// ORCA: apply the preview dimming change immediately to the currently loaded preview (ported from preFlight)
else if (param == "preview_dim_previous_layers") {
if (Plater* plater = wxGetApp().plater()) {
if (GLCanvas3D* canvas = plater->get_preview_canvas3D()) {
canvas->get_gcode_viewer().set_dim_previous_layers(app_config->get_bool(param));
canvas->set_as_dirty();
canvas->request_extra_frame();
}
}
}
#ifdef __WXMSW__ #ifdef __WXMSW__
if (param == "associate_3mf") { if (param == "associate_3mf") {
@@ -1893,11 +1904,21 @@ void PreferencesDialog::create_items()
); );
g_sizer->Add(item_fps_overlay); g_sizer->Add(item_fps_overlay);
//// GRAPHICS > G-code Preview
g_sizer->Add(create_item_title(_L("G-code Preview")), 1, wxEXPAND);
auto item_dim_previous_layers = create_item_checkbox(
_L("Dim lower layers"),
_L("When scrubbing the layer slider in the sliced preview, render the layers below the current one darkened so that only the layer being viewed is shown at full brightness."),
"preview_dim_previous_layers"
);
g_sizer->Add(item_dim_previous_layers);
g_sizer->AddSpacer(FromDIP(10)); g_sizer->AddSpacer(FromDIP(10));
sizer_page->Add(g_sizer, 0, wxEXPAND); sizer_page->Add(g_sizer, 0, wxEXPAND);
////////////////////////// //////////////////////////
//// ONLINE TAB //// ONLINE TAB
///////////////////////////////////// /////////////////////////////////////
m_pref_tabs->AppendItem(_L("Online")); m_pref_tabs->AppendItem(_L("Online"));
f_sizers.push_back(new wxFlexGridSizer(1, 1, v_gap, 0)); f_sizers.push_back(new wxFlexGridSizer(1, 1, v_gap, 0));