diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index df5b3f5380..dcbead0ddd 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -202,6 +202,10 @@ void AppConfig::set_defaults() if (get("seq_top_layer_only").empty()) 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()) set("filaments_area_preferred_count", "10"); diff --git a/src/libvgcode/include/Viewer.hpp b/src/libvgcode/include/Viewer.hpp index fa3236fd5c..7c0a0c295a 100644 --- a/src/libvgcode/include/Viewer.hpp +++ b/src/libvgcode/include/Viewer.hpp @@ -91,6 +91,13 @@ public: // 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. // bool is_option_visible(EOptionType type) const; diff --git a/src/libvgcode/src/Settings.hpp b/src/libvgcode/src/Settings.hpp index 37ddb5a8b9..89cb9771b4 100644 --- a/src/libvgcode/src/Settings.hpp +++ b/src/libvgcode/src/Settings.hpp @@ -19,6 +19,9 @@ struct Settings EViewType view_type{ EViewType::FeatureType }; ETimeMode time_mode{ ETimeMode::Normal }; 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 }; // // Required update flags diff --git a/src/libvgcode/src/Viewer.cpp b/src/libvgcode/src/Viewer.cpp index 612a1ed0a8..a36cf011ce 100644 --- a/src/libvgcode/src/Viewer.cpp +++ b/src/libvgcode/src/Viewer.cpp @@ -72,6 +72,16 @@ void Viewer::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 { return m_impl->is_option_visible(type); diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index 1c52ffe40f..9804e12b9e 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -1223,6 +1223,20 @@ static float encode_color(const Color& color) { return static_cast(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(color[0] * keep); + const int g = static_cast(color[1] * keep); + const int b = static_cast(color[2] * keep); + const int i_color = r << 16 | g << 8 | b; + return static_cast(i_color); +} + 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 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(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 - // 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 colors(m_vertices_colors.size()); assert(colors.size() == m_vertices.size() && m_vertices_colors.size() == m_vertices.size()); - for (size_t i=0; i ViewerImpl::get_time_modes() const { std::vector ret; diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index a5740033a5..8a91d5524f 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -85,6 +85,10 @@ public: bool is_top_layer_only_view_range() const { return m_settings.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; } std::vector get_time_modes() const; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 3b3d4248e3..ac066be011 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1134,6 +1134,9 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const if (current_top_layer_only != required_top_layer_only) 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 if (m_last_result_id == gcode_result.id && wxGetApp().is_editor()) { //BBS: add logs diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 4958fc25a8..570c688987 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -333,6 +333,10 @@ public: 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& layers_z_range); bool is_legend_shown() const { return m_legend_visible && m_legend_enabled; } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 2b5787c760..bd5b7420ff 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -3,6 +3,7 @@ #include "GUI_App.hpp" #include "MainFrame.hpp" #include "Plater.hpp" +#include "GLCanvas3D.hpp" // ORCA: for live preview refresh when toggling "Dim lower layers" #include "MsgDialog.hpp" #include "I18N.hpp" #include "libslic3r/AppConfig.hpp" @@ -1049,6 +1050,16 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too 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__ if (param == "associate_3mf") { @@ -1893,11 +1904,21 @@ void PreferencesDialog::create_items() ); 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)); sizer_page->Add(g_sizer, 0, wxEXPAND); ////////////////////////// - //// ONLINE TAB + //// ONLINE TAB ///////////////////////////////////// m_pref_tabs->AppendItem(_L("Online")); f_sizers.push_back(new wxFlexGridSizer(1, 1, v_gap, 0));