mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
Fix: generic filaments not showing on list (#13037)
This commit is contained in:
@@ -653,7 +653,7 @@ public:
|
|||||||
int match_quality = -1;
|
int match_quality = -1;
|
||||||
for (; i < n; ++i)
|
for (; i < n; ++i)
|
||||||
// Since we use the filament selection from Wizard, it's needed to control the preset visibility too
|
// Since we use the filament selection from Wizard, it's needed to control the preset visibility too
|
||||||
if (m_presets[i].is_compatible) {
|
if (m_presets[i].is_compatible && m_presets[i].is_visible) {
|
||||||
int this_match_quality = prefered_condition(m_presets[i]);
|
int this_match_quality = prefered_condition(m_presets[i]);
|
||||||
if (this_match_quality > match_quality) {
|
if (this_match_quality > match_quality) {
|
||||||
if (match_quality == std::numeric_limits<int>::max())
|
if (match_quality == std::numeric_limits<int>::max())
|
||||||
|
|||||||
@@ -734,10 +734,17 @@ void PresetBundle::reset_project_embedded_presets()
|
|||||||
Preset& current_printer = this->printers.get_selected_preset();
|
Preset& current_printer = this->printers.get_selected_preset();
|
||||||
const std::vector<std::string> &prefered_filament_profiles = current_printer.config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
const std::vector<std::string> &prefered_filament_profiles = current_printer.config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
||||||
const std::string prefered_filament_profile = prefered_filament_profiles.empty() ? std::string() : prefered_filament_profiles.front();
|
const std::string prefered_filament_profile = prefered_filament_profiles.empty() ? std::string() : prefered_filament_profiles.front();
|
||||||
if (!prefered_filament_profile.empty())
|
if (!prefered_filament_profile.empty()) {
|
||||||
filament_presets[i] = prefered_filament_profile;
|
// Check if preferred filament exists and is visible
|
||||||
else
|
const Preset* preferred_preset = this->filaments.find_preset(prefered_filament_profile, false);
|
||||||
filament_presets[i] = this->filaments.first_visible().name;
|
if (preferred_preset && preferred_preset->is_visible) {
|
||||||
|
filament_presets[i] = prefered_filament_profile;
|
||||||
|
} else {
|
||||||
|
// Fall back to first visible filament
|
||||||
|
filament_presets[i] = this->filaments.first_visible().name;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
filament_presets[i] = this->filaments.first_visible().name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1970,8 +1977,14 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
|
|||||||
initial_print_profile_name = prefered_print_profile;
|
initial_print_profile_name = prefered_print_profile;
|
||||||
|
|
||||||
const std::vector<std::string>& prefered_filament_profiles = preferred_printer->config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
const std::vector<std::string>& prefered_filament_profiles = preferred_printer->config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
||||||
if ((!initial_filament_profile_name.compare("Default Filament")) && (prefered_filament_profiles.size() > 0))
|
if ((!initial_filament_profile_name.compare("Default Filament")) && (prefered_filament_profiles.size() > 0)) {
|
||||||
initial_filament_profile_name = prefered_filament_profiles[0];
|
// Check if preferred filament is visible
|
||||||
|
const Preset* preferred_preset = this->filaments.find_preset(prefered_filament_profiles[0], false);
|
||||||
|
if (preferred_preset && preferred_preset->is_visible) {
|
||||||
|
initial_filament_profile_name = prefered_filament_profiles[0];
|
||||||
|
}
|
||||||
|
// If not visible, keep the default "Default Filament" which will be resolved later
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found.
|
// Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found.
|
||||||
@@ -4452,7 +4465,7 @@ void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_pri
|
|||||||
int operator()(const Preset &preset) const
|
int operator()(const Preset &preset) const
|
||||||
{
|
{
|
||||||
// Don't match any properties of the "-- default --" profile or the external profiles when switching printer profile.
|
// Don't match any properties of the "-- default --" profile or the external profiles when switching printer profile.
|
||||||
if (preset.is_default || preset.is_external)
|
if (preset.is_default || preset.is_external || !preset.is_visible)
|
||||||
return 0;
|
return 0;
|
||||||
if (! m_prefered_alias.empty() && m_prefered_alias == preset.alias)
|
if (! m_prefered_alias.empty() && m_prefered_alias == preset.alias)
|
||||||
// Matching an alias, always take this preset with priority.
|
// Matching an alias, always take this preset with priority.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
#include "libslic3r/Config.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "slic3r/GUI/wxExtensions.hpp"
|
#include "slic3r/GUI/wxExtensions.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
@@ -438,6 +439,50 @@ void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
|||||||
wxString s2 = OneSelect["model"];
|
wxString s2 = OneSelect["model"];
|
||||||
if (s1.compare(s2) == 0) {
|
if (s1.compare(s2) == 0) {
|
||||||
m_ProfileJson["model"][m]["nozzle_selected"] = m_ProfileJson["model"][m]["nozzle_diameter"];
|
m_ProfileJson["model"][m]["nozzle_selected"] = m_ProfileJson["model"][m]["nozzle_diameter"];
|
||||||
|
|
||||||
|
// Automatically select default materials for this printer model
|
||||||
|
// This mirrors the behavior of the old ConfigWizard::select_default_materials_for_printer_model()
|
||||||
|
if (TmpModel.contains("materials") && !TmpModel["materials"].is_null()) {
|
||||||
|
std::string materials_str;
|
||||||
|
|
||||||
|
// Handle both string and JSON array formats for materials
|
||||||
|
if (TmpModel["materials"].is_string()) {
|
||||||
|
materials_str = TmpModel["materials"].get<std::string>();
|
||||||
|
} else if (TmpModel["materials"].is_array()) {
|
||||||
|
// Convert JSON array to semicolon-separated string for unescape_strings_cstyle
|
||||||
|
for (const auto& material : TmpModel["materials"]) {
|
||||||
|
if (!materials_str.empty()) materials_str += ";";
|
||||||
|
materials_str += material.get<std::string>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
materials_str = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::trim(materials_str);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Processing default_materials for printer: " << s1.ToStdString() << " - materials: " << materials_str;
|
||||||
|
|
||||||
|
// Use the same parsing logic as ConfigWizard::select_default_materials_for_printer_model()
|
||||||
|
// This calls unescape_strings_cstyle() just like Preset.cpp:298 does
|
||||||
|
std::vector<std::string> materials;
|
||||||
|
if (Slic3r::unescape_strings_cstyle(materials_str, materials)) {
|
||||||
|
for (const std::string& material : materials) {
|
||||||
|
if (!material.empty()) {
|
||||||
|
// Mark this filament as selected if it exists in our filament list
|
||||||
|
// This mirrors appconfig_new.set(section, material, "true") from ConfigWizard.cpp:2150
|
||||||
|
if (m_ProfileJson["filament"].contains(material)) {
|
||||||
|
m_ProfileJson["filament"][material]["selected"] = 1;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Automatically selected default filament: " << material;
|
||||||
|
} else {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Default filament '" << material << "' not found in available filaments for printer: " << s1.ToStdString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Malformed default_materials field: " << materials_str << " for printer: " << s1.ToStdString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " No default_materials defined for printer: " << s1.ToStdString();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -838,45 +883,8 @@ bool GuideFrame::apply_config(AppConfig *app_config, PresetBundle *preset_bundle
|
|||||||
// Not switch filament
|
// Not switch filament
|
||||||
//get_first_added_material_preset(AppConfig::SECTION_FILAMENTS, first_added_filament);
|
//get_first_added_material_preset(AppConfig::SECTION_FILAMENTS, first_added_filament);
|
||||||
|
|
||||||
// For each @System filament, check if a vendor-specific override exists
|
|
||||||
// in the loaded profiles. If so, replace the @System variant with the
|
|
||||||
// override (e.g. replace "Generic ABS @System" with BBL "Generic ABS").
|
|
||||||
// When printers from the default bundle are also selected, keep @System
|
|
||||||
// too since those printers need it.
|
|
||||||
static const std::string system_suffix = " @System";
|
|
||||||
auto it_default = enabled_vendors.find(PresetBundle::ORCA_DEFAULT_BUNDLE);
|
|
||||||
bool has_default_bundle_printer = it_default != enabled_vendors.end() && !it_default->second.empty();
|
|
||||||
bool has_filament_profiles = m_ProfileJson.contains("filament");
|
|
||||||
|
|
||||||
// Check if any non-default vendor has selected printers
|
|
||||||
bool has_vendor_printer = false;
|
|
||||||
for (const auto& [vendor, models] : enabled_vendors) {
|
|
||||||
if (vendor != PresetBundle::ORCA_DEFAULT_BUNDLE && !models.empty()) {
|
|
||||||
has_vendor_printer = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, std::string> supplemented_filaments;
|
|
||||||
for (const auto& [name, value] : enabled_filaments) {
|
|
||||||
if (name.size() > system_suffix.size() &&
|
|
||||||
name.compare(name.size() - system_suffix.size(), system_suffix.size(), system_suffix) == 0) {
|
|
||||||
std::string short_name = name.substr(0, name.size() - system_suffix.size());
|
|
||||||
if (has_vendor_printer && has_filament_profiles && m_ProfileJson["filament"].contains(short_name)) {
|
|
||||||
supplemented_filaments[short_name] = value;
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Replacing @System filament: '" << name << "' -> '" << short_name << "'";
|
|
||||||
if (has_default_bundle_printer) {
|
|
||||||
supplemented_filaments[name] = value;
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Also keeping '" << name << "' for default bundle printers";
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
supplemented_filaments[name] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//update the app_config
|
//update the app_config
|
||||||
app_config->set_section(AppConfig::SECTION_FILAMENTS, supplemented_filaments);
|
app_config->set_section(AppConfig::SECTION_FILAMENTS, enabled_filaments);
|
||||||
app_config->set_vendors(m_appconfig_new);
|
app_config->set_vendors(m_appconfig_new);
|
||||||
|
|
||||||
if (check_unsaved_preset_changes)
|
if (check_unsaved_preset_changes)
|
||||||
@@ -886,10 +894,10 @@ bool GuideFrame::apply_config(AppConfig *app_config, PresetBundle *preset_bundle
|
|||||||
// If the active filament is not in the wizard-selected filaments, switch to the first
|
// If the active filament is not in the wizard-selected filaments, switch to the first
|
||||||
// compatible wizard-selected filament. This handles the first-run case where load_presets
|
// compatible wizard-selected filament. This handles the first-run case where load_presets
|
||||||
// falls back to "Generic PLA" even though the user selected a different filament.
|
// falls back to "Generic PLA" even though the user selected a different filament.
|
||||||
bool active_filament_selected = supplemented_filaments.empty()
|
bool active_filament_selected = enabled_filaments.empty()
|
||||||
|| supplemented_filaments.count(preset_bundle->filament_presets.front()) > 0;
|
|| enabled_filaments.count(preset_bundle->filament_presets.front()) > 0;
|
||||||
if (!active_filament_selected) {
|
if (!active_filament_selected) {
|
||||||
for (const auto& [filament_name, _] : supplemented_filaments) {
|
for (const auto& [filament_name, _] : enabled_filaments) {
|
||||||
const Preset* preset = preset_bundle->filaments.find_preset(filament_name);
|
const Preset* preset = preset_bundle->filaments.find_preset(filament_name);
|
||||||
if (preset && preset->is_visible && preset->is_compatible) {
|
if (preset && preset->is_visible && preset->is_compatible) {
|
||||||
preset_bundle->filaments.select_preset_by_name(filament_name, true);
|
preset_bundle->filaments.select_preset_by_name(filament_name, true);
|
||||||
@@ -1124,21 +1132,23 @@ int GuideFrame::LoadProfileData()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sync to web
|
wxGetApp().CallAfter([this] {
|
||||||
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
if (!m_destroy) {
|
||||||
|
//sync to appconfig first to populate current selections
|
||||||
|
SaveProfileData();
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished, json contents: " << std::endl << strAll;
|
//sync to web after selections are populated
|
||||||
json m_Res = json::object();
|
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||||
m_Res["command"] = "userguide_profile_load_finish";
|
|
||||||
m_Res["sequence_id"] = "10001";
|
|
||||||
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', true));
|
|
||||||
if (!m_destroy)
|
|
||||||
wxGetApp().CallAfter([this, strJS] { RunScript(strJS); });
|
|
||||||
|
|
||||||
//sync to appconfig
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished, json contents: " << std::endl << strAll;
|
||||||
if (!m_destroy)
|
json m_Res = json::object();
|
||||||
wxGetApp().CallAfter([this] { SaveProfileData(); });
|
m_Res["command"] = "userguide_profile_load_finish";
|
||||||
|
m_Res["sequence_id"] = "10001";
|
||||||
|
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', true));
|
||||||
|
|
||||||
|
RunScript(strJS);
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
// wxLogMessage("GUIDE: load_profile_error %s ", e.what());
|
// wxLogMessage("GUIDE: load_profile_error %s ", e.what());
|
||||||
// wxMessageBox(e.what(), "", MB_OK);
|
// wxMessageBox(e.what(), "", MB_OK);
|
||||||
|
|||||||
@@ -420,7 +420,9 @@ int DropDown::hoverIndex()
|
|||||||
{
|
{
|
||||||
if (hover_item < 0)
|
if (hover_item < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (count == items.size())
|
// BUG FIX: Can't take the shortcut if subDropDown exists (which means there are groups)
|
||||||
|
// because we need to detect group headers which return negative indices
|
||||||
|
if (count == items.size() && subDropDown == nullptr)
|
||||||
return hover_item;
|
return hover_item;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
std::set<wxString> groups;
|
std::set<wxString> groups;
|
||||||
@@ -448,7 +450,9 @@ int DropDown::selectedItem()
|
|||||||
{
|
{
|
||||||
if (selection < 0)
|
if (selection < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (count == items.size())
|
// BUG FIX: Can't take the shortcut if subDropDown exists (which means there are groups)
|
||||||
|
// because the visual position differs from the actual item index when groups are shown
|
||||||
|
if (count == items.size() && subDropDown == nullptr)
|
||||||
return selection;
|
return selection;
|
||||||
auto & sel = items[selection];
|
auto & sel = items[selection];
|
||||||
if (group.IsEmpty() ? !sel.group.IsEmpty() : sel.group != group)
|
if (group.IsEmpty() ? !sel.group.IsEmpty() : sel.group != group)
|
||||||
|
|||||||
Reference in New Issue
Block a user