diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index ff6444d3ef..cdcd9b4dec 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -224,6 +224,12 @@ void AppConfig::set_defaults() set("preview_dim_previous_layers_brightness", std::to_string(std::max(0, std::min(brightness, 99)))); } + // ORCA: view type the G-code preview opens with. "auto" keeps the automatic choice (Filament for + // multi material prints, Line Type for single material ones), "last" restores the view type the user + // picked last, any other value is a fixed view type name, see GCodeViewer::view_type_to_config_name(). + if (get("preview_default_view_type").empty()) + set("preview_default_view_type", "auto"); + if (get("filaments_area_preferred_count").empty()) set("filaments_area_preferred_count", "10"); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 2070b988d5..b86af5c259 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -104,6 +104,31 @@ static std::string get_view_type_string(libvgcode::EViewType view_type) return ""; } +// ORCA: Stable, locale independent names used to persist a view type in the application config. +// Keep these in sync with the entries of libvgcode::EViewType exposed in the preview combo box. +static const std::vector>& view_type_config_map() +{ + static const std::vector> map = { + { "summary", libvgcode::EViewType::Summary }, + { "feature_type", libvgcode::EViewType::FeatureType }, + { "color_print", libvgcode::EViewType::ColorPrint }, + { "speed", libvgcode::EViewType::Speed }, + { "actual_speed", libvgcode::EViewType::ActualSpeed }, + { "acceleration", libvgcode::EViewType::Acceleration }, + { "jerk", libvgcode::EViewType::Jerk }, + { "height", libvgcode::EViewType::Height }, + { "width", libvgcode::EViewType::Width }, + { "volumetric_flow_rate", libvgcode::EViewType::VolumetricFlowRate }, + { "actual_volumetric_flow_rate", libvgcode::EViewType::ActualVolumetricFlowRate }, + { "layer_time_linear", libvgcode::EViewType::LayerTimeLinear }, + { "layer_time_logarithmic", libvgcode::EViewType::LayerTimeLogarithmic }, + { "fan_speed", libvgcode::EViewType::FanSpeed }, + { "temperature", libvgcode::EViewType::Temperature }, + { "pressure_advance", libvgcode::EViewType::PressureAdvance }, + }; + return map; +} + // Find an index of a value in a sorted vector, which is in . // Returns -1 if there is no such member. static int find_close_layer_idx(const std::vector &zs, double &z, double eps) @@ -1091,9 +1116,7 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle) // Default view type at first slice. // May be overridden in load() once we know how many tools are actually used in the G-code. m_nozzle_nums = preset_bundle ? preset_bundle->get_printer_extruder_count() : 1; - auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::FeatureType); - m_view_type_sel = (it != view_type_items.end()) ? std::distance(view_type_items.begin(), it) : 0; - set_view_type(libvgcode::EViewType::FeatureType); + apply_default_view_type(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": finished"); } @@ -1114,6 +1137,73 @@ void GCodeViewer::set_scale(float scale) } } +// ORCA: Preview default view type preference, see "preview_default_view_type" in the application config. +std::string GCodeViewer::view_type_to_config_name(libvgcode::EViewType type) +{ + for (const auto& [name, value] : view_type_config_map()) { + if (value == type) + return name; + } + return std::string(); +} + +bool GCodeViewer::view_type_from_config_name(const std::string& name, libvgcode::EViewType& type) +{ + for (const auto& [config_name, value] : view_type_config_map()) { + if (config_name == name) { + type = value; + return true; + } + } + return false; +} + +std::vector> GCodeViewer::default_view_type_choices() +{ + std::vector> choices = { + { "auto", _u8L("Automatic") }, + { "last", _u8L("Last used") }, + }; + for (const auto& [name, type] : view_type_config_map()) + choices.push_back({ name, get_view_type_string(type) }); + return choices; +} + +void GCodeViewer::select_view_type(libvgcode::EViewType type) +{ + auto it = std::find(view_type_items.begin(), view_type_items.end(), type); + m_view_type_sel = (it != view_type_items.end()) ? static_cast(std::distance(view_type_items.begin(), it)) : 0; + set_view_type(type); +} + +// ORCA: Pick the view type the preview opens with, following the "preview_default_view_type" preference: +// a fixed view type, the one the user picked last ("last"), or the automatic choice ("auto", the default) +// which shows Filament for multi material prints and Line Type for single material ones. +// The default is only (re)applied when it actually changes, so a view type picked by hand survives a reslice. +void GCodeViewer::apply_default_view_type() +{ + const std::string preference = wxGetApp().app_config->get("preview_default_view_type"); + + std::string key = preference; + libvgcode::EViewType type = libvgcode::EViewType::FeatureType; + if (preference == "last") { + if (!view_type_from_config_name(wxGetApp().app_config->get("preview_last_view_type"), type)) + type = libvgcode::EViewType::FeatureType; + } + else if (!view_type_from_config_name(preference, type)) { + // "auto", or an unknown value written by a newer version + const bool multi_material = m_viewer.get_used_extruders_count() > 1; + type = multi_material ? libvgcode::EViewType::ColorPrint : libvgcode::EViewType::FeatureType; + key = multi_material ? "auto_multi_material" : "auto_single_material"; + } + + if (m_applied_default_view_type_key == key) + return; + + m_applied_default_view_type_key = key; + select_view_type(type); +} + void GCodeViewer::update_by_mode(ConfigOptionMode mode) { view_type_items.clear(); @@ -1395,27 +1485,8 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const // load_toolpaths(gcode_result, build_volume, exclude_bounding_box); - // ORCA: Apply smart default view type when extruder count changes. - // Multi-color: ColorPrint (Filament), Single-color: FeatureType (Line Type). - // User selections persist within same extruder count, defaults reapply on count change. - int current_count = m_viewer.get_used_extruders_count(); - if (current_count > 1) { - if (m_last_extruder_count_default_applied != 2) { - auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::ColorPrint); - if (it != view_type_items.end()) - m_view_type_sel = std::distance(view_type_items.begin(), it); - set_view_type(libvgcode::EViewType::ColorPrint); - m_last_extruder_count_default_applied = 2; - } - } else { - if (m_last_extruder_count_default_applied != 1) { - auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::FeatureType); - if (it != view_type_items.end()) - m_view_type_sel = std::distance(view_type_items.begin(), it); - set_view_type(libvgcode::EViewType::FeatureType); - m_last_extruder_count_default_applied = 1; - } - } + // ORCA: Apply the default view type now that we know how many tools the G-code actually uses. + apply_default_view_type(); // BBS: data for rendering color arrangement recommendation m_nozzle_nums = print.config().option("nozzle_diameter")->values.size(); @@ -3581,6 +3652,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv m_view_type_sel = i; set_view_type(view_type_items[m_view_type_sel]); reset_visible(view_type_items[m_view_type_sel]); + // ORCA: remember the pick so the "Last used" preview default can restore it + const std::string view_type_name = view_type_to_config_name(view_type_items[m_view_type_sel]); + if (!view_type_name.empty()) + wxGetApp().app_config->set("preview_last_view_type", view_type_name); update_moves_slider(); #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT imgui.set_requires_extra_frame(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 2b4d4e2334..f4ebe2e81d 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -228,7 +228,8 @@ private: std::vector view_type_items; std::vector view_type_items_str; int m_view_type_sel = 0; - int m_last_extruder_count_default_applied{0}; // 0=unset, 1=single, 2+=multi + // ORCA: which default view type was last applied, see apply_default_view_type(). Empty until the first one is applied. + std::string m_applied_default_view_type_key; std::vector options_items; bool m_legend_visible{ true }; @@ -331,6 +332,16 @@ public: void set_view_type(libvgcode::EViewType type) { m_viewer.set_view_type(type); } + // ORCA: select a view type in the preview combo box and apply it + void select_view_type(libvgcode::EViewType type); + // ORCA: apply the "preview_default_view_type" preference, see the definition for the supported values + void apply_default_view_type(); + + // ORCA: stable, locale independent name of a view type, as stored in the application config + static std::string view_type_to_config_name(libvgcode::EViewType type); + static bool view_type_from_config_name(const std::string& name, libvgcode::EViewType& type); + // ORCA: (config value, translated label) pairs for the "preview_default_view_type" preference combo box + static std::vector> default_view_type_choices(); void reset_visible(libvgcode::EViewType type) { if (type == libvgcode::EViewType::FeatureType) { auto roles = m_viewer.get_extrusion_roles(); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 3a7f37e9cb..001866bfd9 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -2028,6 +2028,23 @@ void PreferencesDialog::create_items() //// GRAPHICS > G-code Preview g_sizer->Add(create_item_title(_L("G-code Preview")), 1, wxEXPAND); + // ORCA: view type the preview opens with + std::vector PreviewViewTypeLabels; + std::vector PreviewViewTypeValues; + for (const auto& [value, label] : GCodeViewer::default_view_type_choices()) { + PreviewViewTypeValues.push_back(value); + PreviewViewTypeLabels.push_back(from_u8(label)); + } + auto item_preview_view_type = create_item_combobox( + _L("Default view type"), + _L("The color scheme the sliced preview opens with.\n" + "Automatic: Filament for multi material prints, Line Type for single material ones.\n" + "Last used: the view type you selected last.\n" + "Any other value always opens that view type.\n" + "You can still switch the view type in the preview afterwards."), + "preview_default_view_type", PreviewViewTypeLabels, PreviewViewTypeValues); + g_sizer->Add(item_preview_view_type); + 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."),