mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 19:31:22 +00:00
Merge branch 'main' into belt/baseChanges
This commit is contained in:
@@ -1654,7 +1654,7 @@ msgid "Based on PrusaSlicer and BambuStudio"
|
|||||||
msgstr "Basierend auf PrusaSlicer und BambuStudio"
|
msgstr "Basierend auf PrusaSlicer und BambuStudio"
|
||||||
|
|
||||||
msgid "STEP files"
|
msgid "STEP files"
|
||||||
msgstr "SETP Dateien"
|
msgstr "STEP Dateien"
|
||||||
|
|
||||||
msgid "STL files"
|
msgid "STL files"
|
||||||
msgstr "STL Dateien"
|
msgstr "STL Dateien"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Creality",
|
"name": "Creality",
|
||||||
"version": "02.03.02.60",
|
"version": "02.03.02.61",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Creality configurations",
|
"description": "Creality configurations",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -5,9 +5,9 @@
|
|||||||
"nozzle_diameter": "0.2;0.4;0.6;0.8",
|
"nozzle_diameter": "0.2;0.4;0.6;0.8",
|
||||||
"machine_tech": "FFF",
|
"machine_tech": "FFF",
|
||||||
"family": "Creality",
|
"family": "Creality",
|
||||||
"bed_model": "creality_k1_buildplate_model.stl",
|
"bed_model": "creality_k2_buildplate_model.stl",
|
||||||
"default_bed_type": "Textured PEI Plate",
|
"default_bed_type": "Textured PEI Plate",
|
||||||
"bed_texture": "creality_k1_buildplate_texture.png",
|
"bed_texture": "creality_k2_buildplate_texture.png",
|
||||||
"hotend_model": "",
|
"hotend_model": "",
|
||||||
"default_materials": "Creality Generic ABS @K2-all;Creality Generic ASA @K2-all;Creality Generic PETG @K2-all;Creality Generic PLA @K2-all;Creality Generic PLA High Speed @K2-all;Creality Generic PLA Matte @K2-all;Creality Generic PLA Silk @K2-all"
|
"default_materials": "Creality Generic ABS @K2-all;Creality Generic ASA @K2-all;Creality Generic PETG @K2-all;Creality Generic PLA @K2-all;Creality Generic PLA High Speed @K2-all;Creality Generic PLA Matte @K2-all;Creality Generic PLA Silk @K2-all"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# these are the CachyOS Linux specific build functions
|
||||||
|
|
||||||
|
# Additional Dev packages for OrcaSlicer
|
||||||
|
export REQUIRED_DEV_PACKAGES=(
|
||||||
|
cmake
|
||||||
|
curl
|
||||||
|
dbus
|
||||||
|
eglexternalplatform
|
||||||
|
extra-cmake-modules
|
||||||
|
file
|
||||||
|
gettext
|
||||||
|
git
|
||||||
|
glew
|
||||||
|
gstreamer
|
||||||
|
gtk3
|
||||||
|
libmspack
|
||||||
|
libsecret
|
||||||
|
libspnav
|
||||||
|
mesa
|
||||||
|
ninja
|
||||||
|
openssl
|
||||||
|
texinfo
|
||||||
|
wayland-protocols
|
||||||
|
webkit2gtk
|
||||||
|
wget
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
then
|
||||||
|
echo -n -e "Updating linux ...\n"
|
||||||
|
NEEDED_PKGS=()
|
||||||
|
for PKG in "${REQUIRED_DEV_PACKAGES[@]}"; do
|
||||||
|
pacman -Q "${PKG}" > /dev/null || NEEDED_PKGS+=("${PKG}")
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${#NEEDED_PKGS[*]}" -gt 0 ]]; then
|
||||||
|
sudo pacman -Syy --noconfirm "${NEEDED_PKGS[@]}"
|
||||||
|
fi
|
||||||
|
echo -e "done\n"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
export FOUND_GTK3_DEV
|
||||||
|
FOUND_GTK3_DEV=$(pacman -Q gtk3)
|
||||||
@@ -5,7 +5,7 @@ Icon=OrcaSlicer
|
|||||||
Exec=orca-slicer %U
|
Exec=orca-slicer %U
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
MimeType=model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;x-scheme-handler/orcaslicer;
|
MimeType=model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;x-scheme-handler/orcaslicer;model/step;
|
||||||
Categories=Graphics;3DGraphics;Engineering;
|
Categories=Graphics;3DGraphics;Engineering;
|
||||||
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
|
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
|
||||||
StartupNotify=false
|
StartupNotify=false
|
||||||
|
|||||||
+14
-10
@@ -587,26 +587,30 @@ public:
|
|||||||
auto rhs_opt = static_cast<const ConfigOptionVector<T>*>(rhs);
|
auto rhs_opt = static_cast<const ConfigOptionVector<T>*>(rhs);
|
||||||
auto inherits_opt = static_cast<const ConfigOptionVector<T>*>(inherits);
|
auto inherits_opt = static_cast<const ConfigOptionVector<T>*>(inherits);
|
||||||
|
|
||||||
if (inherits->size() != rhs->size())
|
if (stride <= 0)
|
||||||
throw ConfigurationError("ConfigOptionVector::set_with_nil(): rhs size different with inherits size");
|
throw ConfigurationError("ConfigOptionVector::set_with_nil(): invalid stride");
|
||||||
|
|
||||||
this->values.resize(inherits->size(), this->values.front());
|
// Tolerate legacy/transitional presets where vector sizes may diverge
|
||||||
|
// (for example after reducing extruder/variant count).
|
||||||
|
// Keep rhs as source of truth and nil-mark only on overlapping range.
|
||||||
|
this->values = rhs_opt->values;
|
||||||
|
|
||||||
for (size_t i = 0; i < inherits_opt->size(); i= i+stride) {
|
const size_t overlap_size = std::min(rhs_opt->size(), inherits_opt->size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < overlap_size; i += size_t(stride)) {
|
||||||
|
const size_t group_size = std::min(size_t(stride), overlap_size - i);
|
||||||
bool set_nil = true;
|
bool set_nil = true;
|
||||||
for (size_t j = 0; j < stride; j++) {
|
for (size_t j = 0; j < group_size; ++j) {
|
||||||
if (inherits_opt->values[i +j] != rhs_opt->values[i +j]) {
|
if (inherits_opt->values[i + j] != rhs_opt->values[i + j]) {
|
||||||
set_nil = false;
|
set_nil = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < stride; j++) {
|
for (size_t j = 0; j < group_size; ++j) {
|
||||||
if (set_nil) {
|
if (set_nil) {
|
||||||
this->set_at_to_nil(i +j);
|
this->set_at_to_nil(i + j);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
this->values[i +j] = rhs_opt->values[i +j];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ void group_region_by_fuzzify(PerimeterGenerator& g)
|
|||||||
surfaces.push_back(&surface);
|
surfaces.push_back(&surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.type != FuzzySkinType::None) {
|
if (cfg.type != FuzzySkinType::None && cfg.type != FuzzySkinType::Disabled_fuzzy) {
|
||||||
g.has_fuzzy_skin = true;
|
g.has_fuzzy_skin = true;
|
||||||
if (cfg.type != FuzzySkinType::External) {
|
if (cfg.type != FuzzySkinType::External) {
|
||||||
g.has_fuzzy_hole = true;
|
g.has_fuzzy_hole = true;
|
||||||
|
|||||||
@@ -5461,8 +5461,10 @@ void GCodeProcessor::process_M1020(const GCodeReader::GCodeLine &line)
|
|||||||
BOOST_LOG_TRIVIAL(error) << "Invalid M1020 command (" << line.raw() << ").";
|
BOOST_LOG_TRIVIAL(error) << "Invalid M1020 command (" << line.raw() << ").";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (eid >= m_result.filaments_count)
|
if (eid >= m_result.filaments_count) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Invalid M1020 command (" << line.raw() << ").";
|
BOOST_LOG_TRIVIAL(error) << "Invalid M1020 command (" << line.raw() << ").";
|
||||||
|
return;
|
||||||
|
}
|
||||||
process_filament_change(eid);
|
process_filament_change(eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5490,8 +5492,10 @@ void GCodeProcessor::process_T(const std::string_view command)
|
|||||||
BOOST_LOG_TRIVIAL(error) << "Invalid T command (" << command << ").";
|
BOOST_LOG_TRIVIAL(error) << "Invalid T command (" << command << ").";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (eid >= m_result.filaments_count)
|
if (eid >= m_result.filaments_count) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Invalid T command (" << command << ").";
|
BOOST_LOG_TRIVIAL(error) << "Invalid T command (" << command << ").";
|
||||||
|
return;
|
||||||
|
}
|
||||||
process_filament_change(eid);
|
process_filament_change(eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,9 +734,16 @@ 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()) {
|
||||||
|
// Check if preferred filament exists and is visible
|
||||||
|
const Preset* preferred_preset = this->filaments.find_preset(prefered_filament_profile, false);
|
||||||
|
if (preferred_preset && preferred_preset->is_visible) {
|
||||||
filament_presets[i] = prefered_filament_profile;
|
filament_presets[i] = prefered_filament_profile;
|
||||||
else
|
} else {
|
||||||
|
// Fall back to first visible filament
|
||||||
|
filament_presets[i] = this->filaments.first_visible().name;
|
||||||
|
}
|
||||||
|
} else
|
||||||
filament_presets[i] = this->filaments.first_visible().name;
|
filament_presets[i] = this->filaments.first_visible().name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1970,9 +1977,15 @@ 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)) {
|
||||||
|
// 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];
|
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.
|
||||||
prints.select_preset_by_name_strict(initial_print_profile_name);
|
prints.select_preset_by_name_strict(initial_print_profile_name);
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -9338,11 +9338,8 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig&
|
|||||||
//variant index
|
//variant index
|
||||||
variant_index[e_index] = get_index_for_extruder(e_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
variant_index[e_index] = get_index_for_extruder(e_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
||||||
if (variant_index[e_index] < 0) {
|
if (variant_index[e_index] < 0) {
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: could not found extruder_type %2%, nozzle_volume_type %3%, extruder_index %4%")
|
// Orca: This is expected during transient UI states (e.g. popup windows),
|
||||||
%__LINE__ %s_keys_names_ExtruderType[extruder_type] % s_keys_names_NozzleVolumeType[nozzle_volume_type] % (e_index+1);
|
// fall back to 0 silently.
|
||||||
assert(false);
|
|
||||||
//for some updates happens in a invalid state(caused by popup window)
|
|
||||||
//we need to avoid crash
|
|
||||||
variant_index[e_index] = 0;
|
variant_index[e_index] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Slic3r
|
|||||||
int m_nozzle_id = -1;
|
int m_nozzle_id = -1;
|
||||||
NozzleFlowType m_nozzle_flow = NozzleFlowType::S_FLOW;// 0-common 1-high flow
|
NozzleFlowType m_nozzle_flow = NozzleFlowType::S_FLOW;// 0-common 1-high flow
|
||||||
NozzleType m_nozzle_type = NozzleType::ntUndefine;// 0-stainless_steel 1-hardened_steel 5-tungsten_carbide
|
NozzleType m_nozzle_type = NozzleType::ntUndefine;// 0-stainless_steel 1-hardened_steel 5-tungsten_carbide
|
||||||
float m_diameter = 0.4f;// 0.2mm 0.4mm 0.6mm 0.8mm
|
float m_diameter = 0.0f;// unknown until reported by the printer
|
||||||
};
|
};
|
||||||
|
|
||||||
class DevNozzleSystem
|
class DevNozzleSystem
|
||||||
|
|||||||
@@ -4285,7 +4285,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
p = p->GetParent();
|
p = p->GetParent();
|
||||||
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
||||||
//Orca: Set focus so hotkeys like 'tab' work when a notification is shown.
|
//Orca: Set focus so hotkeys like 'tab' work when a notification is shown.
|
||||||
if (top_level_wnd != nullptr && top_level_wnd->IsActive())
|
//But don't steal focus from text input controls.
|
||||||
|
wxWindow* focused = wxWindow::FindFocus();
|
||||||
|
bool focus_in_text_ctrl = dynamic_cast<wxTextCtrl*>(focused) != nullptr;
|
||||||
|
if (top_level_wnd != nullptr && top_level_wnd->IsActive() && !focus_in_text_ctrl)
|
||||||
m_canvas->SetFocus();
|
m_canvas->SetFocus();
|
||||||
}
|
}
|
||||||
m_mouse.position = pos.cast<double>();
|
m_mouse.position = pos.cast<double>();
|
||||||
@@ -8485,11 +8488,27 @@ void GLCanvas3D::_render_return_toolbar() const
|
|||||||
ImVec2 margin = ImVec2(10.0f, 5.0f);
|
ImVec2 margin = ImVec2(10.0f, 5.0f);
|
||||||
|
|
||||||
if (ImGui::ImageTextButton(real_size,_utf8(L("Return")).c_str(), m_return_toolbar.get_return_texture_id(), button_icon_size, uv0, uv1, -1, bg_col, tint_col, margin)) {
|
if (ImGui::ImageTextButton(real_size,_utf8(L("Return")).c_str(), m_return_toolbar.get_return_texture_id(), button_icon_size, uv0, uv1, -1, bg_col, tint_col, margin)) {
|
||||||
if (m_canvas != nullptr)
|
|
||||||
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
|
|
||||||
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
|
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
|
||||||
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
|
if (m_canvas != nullptr && !wxGetApp().is_closing()) {
|
||||||
wxGetApp().plater()->get_view3D_canvas3D()->reload_scene(true);
|
m_canvas->CallAfter([]() {
|
||||||
|
auto& app = wxGetApp();
|
||||||
|
if (app.is_closing())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto* plater = app.plater();
|
||||||
|
if (plater == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plater->select_view_3D("3D");
|
||||||
|
|
||||||
|
auto* view3d_canvas = plater->get_view3D_canvas3D();
|
||||||
|
if (view3d_canvas == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
view3d_canvas->get_gizmos_manager().reset_all_states();
|
||||||
|
view3d_canvas->reload_scene(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(5);
|
ImGui::PopStyleColor(5);
|
||||||
ImGui::PopStyleVar(1);
|
ImGui::PopStyleVar(1);
|
||||||
|
|||||||
@@ -752,18 +752,51 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
|
|||||||
|
|
||||||
wxMenuItem* MenuFactory::append_menu_item_change_type(wxMenu* menu)
|
wxMenuItem* MenuFactory::append_menu_item_change_type(wxMenu* menu)
|
||||||
{
|
{
|
||||||
return append_menu_item(menu, wxID_ANY, _L("Change type"), "",
|
const wxString menu_name = _L("Change type");
|
||||||
[](wxCommandEvent&) { obj_list()->change_part_type(); }, "", menu,
|
|
||||||
[]() {
|
// Delete old menu item if exists
|
||||||
wxDataViewItemArray selections;
|
const int item_id = menu->FindItem(menu_name);
|
||||||
obj_list()->GetSelections(selections);
|
if (item_id != wxNOT_FOUND)
|
||||||
if (selections.empty()) return false;
|
menu->Destroy(item_id);
|
||||||
for (const auto& it : selections) {
|
|
||||||
if (!(obj_list()->GetModel()->GetItemType(it) & itVolume))
|
// Create submenu
|
||||||
return false; // non-volume present -> disable
|
wxMenu* type_menu = new wxMenu();
|
||||||
|
|
||||||
|
struct TypeInfo {
|
||||||
|
ModelVolumeType type;
|
||||||
|
wxString label;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<TypeInfo> types = {
|
||||||
|
{ ModelVolumeType::MODEL_PART, _L("Part") },
|
||||||
|
{ ModelVolumeType::NEGATIVE_VOLUME, _L("Negative Part") },
|
||||||
|
{ ModelVolumeType::PARAMETER_MODIFIER, _L("Modifier") },
|
||||||
|
{ ModelVolumeType::SUPPORT_BLOCKER, _L("Support Blocker") },
|
||||||
|
{ ModelVolumeType::SUPPORT_ENFORCER, _L("Support Enforcer") }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& info : types) {
|
||||||
|
wxMenuItem* item = append_menu_check_item(type_menu, wxID_ANY, info.label, "",
|
||||||
|
[type = info.type](wxCommandEvent&) { obj_list()->set_volume_type(type); }, type_menu);
|
||||||
|
|
||||||
|
// Update checkmark dynamically when menu is shown - check all selected volumes
|
||||||
|
m_parent->Bind(wxEVT_UPDATE_UI, [type = info.type](wxUpdateUIEvent& evt) {
|
||||||
|
bool has_type = false;
|
||||||
|
wxDataViewItemArray sels;
|
||||||
|
obj_list()->GetSelections(sels);
|
||||||
|
for (auto item : sels) {
|
||||||
|
ModelVolumeType vol_type = obj_list()->GetModel()->GetVolumeType(item);
|
||||||
|
if (vol_type == type) {
|
||||||
|
has_type = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
}, m_parent);
|
evt.Check(has_type);
|
||||||
|
}, item->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->Append(wxID_ANY, menu_name, type_menu, _L("Change part type"));
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu)
|
wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu)
|
||||||
|
|||||||
@@ -5538,6 +5538,136 @@ void ObjectList::change_part_type()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelVolumeType ObjectList::get_selected_volume_type()
|
||||||
|
{
|
||||||
|
ModelVolume* volume = get_selected_model_volume();
|
||||||
|
if (volume)
|
||||||
|
return volume->type();
|
||||||
|
return ModelVolumeType::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectList::set_volume_type(ModelVolumeType new_type)
|
||||||
|
{
|
||||||
|
struct VolumeSelection {
|
||||||
|
int object_idx;
|
||||||
|
ModelVolume* volume;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<VolumeSelection> volumes;
|
||||||
|
auto add_volume = [&volumes](int obj_idx, ModelVolume* volume) {
|
||||||
|
if (volume == nullptr)
|
||||||
|
return;
|
||||||
|
auto it = std::find_if(volumes.begin(), volumes.end(), [volume](const VolumeSelection& other) { return other.volume == volume; });
|
||||||
|
if (it == volumes.end())
|
||||||
|
volumes.push_back({ obj_idx, volume });
|
||||||
|
};
|
||||||
|
|
||||||
|
wxDataViewItemArray sels;
|
||||||
|
GetSelections(sels);
|
||||||
|
for (auto item : sels) {
|
||||||
|
wxDataViewItem volume_item = item;
|
||||||
|
ItemType type = m_objects_model->GetItemType(item);
|
||||||
|
if (!(type & itVolume)) {
|
||||||
|
if ((type & itSettings) && (m_objects_model->GetItemType(m_objects_model->GetParent(item)) & itVolume))
|
||||||
|
volume_item = m_objects_model->GetParent(item);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int obj_idx = m_objects_model->GetObjectIdByItem(volume_item);
|
||||||
|
const int vol_idx = m_objects_model->GetVolumeIdByItem(volume_item);
|
||||||
|
if (obj_idx < 0 || vol_idx < 0 || obj_idx >= m_objects->size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int real_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx, vol_idx);
|
||||||
|
if (real_idx < 0 || real_idx >= (*m_objects)[obj_idx]->volumes.size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
add_volume(obj_idx, (*m_objects)[obj_idx]->volumes[real_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto collect_from_canvas = [&add_volume](GLCanvas3D* canvas) {
|
||||||
|
if (canvas == nullptr)
|
||||||
|
return;
|
||||||
|
const Selection& selection = canvas->get_selection();
|
||||||
|
for (auto idx : selection.get_volume_idxs()) {
|
||||||
|
const GLVolume* gl_volume = selection.get_volume(idx);
|
||||||
|
if (gl_volume == nullptr || gl_volume->object_idx() < 0)
|
||||||
|
continue;
|
||||||
|
ModelVolume* volume = get_model_volume(*gl_volume, selection.get_model()->objects);
|
||||||
|
add_volume(gl_volume->object_idx(), volume);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (volumes.empty()) {
|
||||||
|
collect_from_canvas(wxGetApp().plater()->canvas3D());
|
||||||
|
if (volumes.empty()) {
|
||||||
|
auto canvas_type = wxGetApp().plater()->get_current_canvas3D()->get_canvas_type();
|
||||||
|
if (canvas_type == GLCanvas3D::ECanvasType::CanvasView3D && is_connectors_item_selected())
|
||||||
|
collect_from_canvas(wxGetApp().plater()->get_view3D_canvas3D());
|
||||||
|
}
|
||||||
|
if (volumes.empty())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool any_diff = std::any_of(volumes.begin(), volumes.end(),
|
||||||
|
[new_type](const VolumeSelection& sel) { return sel.volume->type() != new_type; });
|
||||||
|
|
||||||
|
if (!any_diff)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (new_type != ModelVolumeType::MODEL_PART) {
|
||||||
|
std::map<int, int> total_part_cnt;
|
||||||
|
std::map<int, int> selected_part_cnt;
|
||||||
|
|
||||||
|
for (const auto& sel : volumes) {
|
||||||
|
if (total_part_cnt.find(sel.object_idx) == total_part_cnt.end()) {
|
||||||
|
int count = 0;
|
||||||
|
for (auto vol : (*m_objects)[sel.object_idx]->volumes)
|
||||||
|
if (vol->type() == ModelVolumeType::MODEL_PART)
|
||||||
|
++count;
|
||||||
|
total_part_cnt.emplace(sel.object_idx, count);
|
||||||
|
}
|
||||||
|
if (sel.volume->type() == ModelVolumeType::MODEL_PART)
|
||||||
|
++selected_part_cnt[sel.object_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& sel : selected_part_cnt) {
|
||||||
|
auto it = total_part_cnt.find(sel.first);
|
||||||
|
if (it != total_part_cnt.end() && it->second > 0 && sel.second == it->second) {
|
||||||
|
Slic3r::GUI::show_error(nullptr, _(L("The type of the last solid object part is not to be changed.")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
take_snapshot("Change part type");
|
||||||
|
|
||||||
|
std::set<const ModelVolume*> changed_volumes;
|
||||||
|
std::set<int> touched_objects;
|
||||||
|
for (const auto& sel : volumes) {
|
||||||
|
sel.volume->set_type(new_type);
|
||||||
|
changed_volumes.insert(sel.volume);
|
||||||
|
touched_objects.insert(sel.object_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDataViewItemArray new_selection;
|
||||||
|
for (int obj_idx : touched_objects) {
|
||||||
|
wxDataViewItemArray sel_items = reorder_volumes_and_get_selection(obj_idx, [&changed_volumes](const ModelVolume* volume) {
|
||||||
|
return changed_volumes.find(volume) != changed_volumes.end();
|
||||||
|
});
|
||||||
|
for (const auto& item : sel_items)
|
||||||
|
new_selection.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_selection.IsEmpty()) {
|
||||||
|
m_prevent_list_events = true;
|
||||||
|
UnselectAll();
|
||||||
|
SetSelections(new_selection);
|
||||||
|
m_prevent_list_events = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectList::last_volume_is_deleted(const int obj_idx)
|
void ObjectList::last_volume_is_deleted(const int obj_idx)
|
||||||
{
|
{
|
||||||
// BBS: object (obj_idx calc in obj list) is already removed from m_objects in Plater::priv::remove().
|
// BBS: object (obj_idx calc in obj list) is already removed from m_objects in Plater::priv::remove().
|
||||||
|
|||||||
@@ -414,6 +414,8 @@ public:
|
|||||||
|
|
||||||
ModelVolume* get_selected_model_volume();
|
ModelVolume* get_selected_model_volume();
|
||||||
void change_part_type();
|
void change_part_type();
|
||||||
|
void set_volume_type(ModelVolumeType new_type);
|
||||||
|
ModelVolumeType get_selected_volume_type();
|
||||||
|
|
||||||
void last_volume_is_deleted(const int obj_idx);
|
void last_volume_is_deleted(const int obj_idx);
|
||||||
void update_and_show_object_settings_item();
|
void update_and_show_object_settings_item();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
@@ -32,6 +33,15 @@ wxDEFINE_EVENT(EVT_VOLUME_ATTACHED, VolumeAttachedEvent);
|
|||||||
wxDEFINE_EVENT(EVT_VOLUME_DETACHED, VolumeDetachedEvent);
|
wxDEFINE_EVENT(EVT_VOLUME_DETACHED, VolumeDetachedEvent);
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
|
wxString format_nozzle_diameter(float diameter)
|
||||||
|
{
|
||||||
|
if (diameter <= 0.0f) {
|
||||||
|
return _L("Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxString::Format("%smm", wxString::FromDouble(diameter));
|
||||||
|
}
|
||||||
|
|
||||||
CopyFileResult copy_file_gui(const std::string &from, const std::string &to, std::string& error_message, const bool with_check)
|
CopyFileResult copy_file_gui(const std::string &from, const std::string &to, std::string& error_message, const bool with_check)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ wxDECLARE_EVENT(EVT_VOLUME_DETACHED, VolumeDetachedEvent);
|
|||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
|
wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
|
||||||
|
wxString format_nozzle_diameter(float diameter);
|
||||||
|
|
||||||
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
|
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
|
||||||
|
|
||||||
|
|||||||
@@ -4050,8 +4050,8 @@ void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int
|
|||||||
|
|
||||||
const std::vector<int>& min_flush_volumes = get_min_flush_volumes(full_config, extruder_id);
|
const std::vector<int>& min_flush_volumes = get_min_flush_volumes(full_config, extruder_id);
|
||||||
|
|
||||||
ConfigOptionFloat* flush_multi_opt = project_config.option<ConfigOptionFloat>("flush_multiplier");
|
const auto* flush_multi_opt = project_config.option<ConfigOptionFloats>("flush_multiplier");
|
||||||
float flush_multiplier = flush_multi_opt ? flush_multi_opt->getFloat() : 1.f;
|
float flush_multiplier = flush_multi_opt ? (float)flush_multi_opt->get_at(extruder_id) : 1.f;
|
||||||
std::vector<double> matrix = init_matrix;
|
std::vector<double> matrix = init_matrix;
|
||||||
int m_max_flush_volume = Slic3r::g_max_flush_volume;
|
int m_max_flush_volume = Slic3r::g_max_flush_volume;
|
||||||
unsigned int m_number_of_extruders = (int)(sqrt(init_matrix.size()) + 0.001);
|
unsigned int m_number_of_extruders = (int)(sqrt(init_matrix.size()) + 0.001);
|
||||||
|
|||||||
@@ -1345,7 +1345,7 @@ bool PrinterPartsDialog::Show(bool show)
|
|||||||
auto type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID);
|
auto type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID);
|
||||||
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
||||||
nozzle_type_checkbox->SetValue(GetString(type));
|
nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
|
|
||||||
// nozzle flow type
|
// nozzle flow type
|
||||||
nozzle_flow_type_label->Show(obj->is_nozzle_flow_type_supported());
|
nozzle_flow_type_label->Show(obj->is_nozzle_flow_type_supported());
|
||||||
@@ -1369,7 +1369,7 @@ bool PrinterPartsDialog::Show(bool show)
|
|||||||
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(DEPUTY_EXTRUDER_ID);
|
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(DEPUTY_EXTRUDER_ID);
|
||||||
auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(DEPUTY_EXTRUDER_ID);
|
auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(DEPUTY_EXTRUDER_ID);
|
||||||
multiple_left_nozzle_type_checkbox->SetValue(GetString(type));
|
multiple_left_nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
multiple_left_nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
multiple_left_nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
multiple_left_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
multiple_left_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
||||||
|
|
||||||
//right
|
//right
|
||||||
@@ -1377,7 +1377,7 @@ bool PrinterPartsDialog::Show(bool show)
|
|||||||
diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
||||||
flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID);
|
flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID);
|
||||||
multiple_right_nozzle_type_checkbox->SetValue(GetString(type));
|
multiple_right_nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
multiple_right_nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
multiple_right_nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
multiple_right_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
multiple_right_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
||||||
|
|
||||||
if (obj->is_support_refresh_nozzle) {
|
if (obj->is_support_refresh_nozzle) {
|
||||||
@@ -1421,7 +1421,7 @@ wxString PrinterPartsDialog::GetString(NozzleType nozzle_type) const {
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxEmptyString;
|
return _L("Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString PrinterPartsDialog::GetString(NozzleFlowType nozzle_flow_type) const {
|
wxString PrinterPartsDialog::GetString(NozzleFlowType nozzle_flow_type) const {
|
||||||
@@ -1483,7 +1483,7 @@ void PrinterPartsDialog::UpdateNozzleInfo(){
|
|||||||
auto type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID);
|
auto type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID);
|
||||||
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
||||||
nozzle_type_checkbox->SetValue(GetString(type));
|
nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
|
|
||||||
// nozzle flow type
|
// nozzle flow type
|
||||||
nozzle_flow_type_label->Show(obj->is_nozzle_flow_type_supported());
|
nozzle_flow_type_label->Show(obj->is_nozzle_flow_type_supported());
|
||||||
@@ -1499,7 +1499,7 @@ void PrinterPartsDialog::UpdateNozzleInfo(){
|
|||||||
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(DEPUTY_EXTRUDER_ID);
|
auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(DEPUTY_EXTRUDER_ID);
|
||||||
auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(DEPUTY_EXTRUDER_ID);
|
auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(DEPUTY_EXTRUDER_ID);
|
||||||
multiple_left_nozzle_type_checkbox->SetValue(GetString(type));
|
multiple_left_nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
multiple_left_nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
multiple_left_nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
multiple_left_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
multiple_left_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
||||||
|
|
||||||
//right
|
//right
|
||||||
@@ -1507,7 +1507,7 @@ void PrinterPartsDialog::UpdateNozzleInfo(){
|
|||||||
diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID);
|
||||||
flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID);
|
flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID);
|
||||||
multiple_right_nozzle_type_checkbox->SetValue(GetString(type));
|
multiple_right_nozzle_type_checkbox->SetValue(GetString(type));
|
||||||
multiple_right_nozzle_diameter_checkbox->SetValue(GetString(diameter));
|
multiple_right_nozzle_diameter_checkbox->SetValue(format_nozzle_diameter(diameter));
|
||||||
multiple_right_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
multiple_right_nozzle_flow_checkbox->SetValue(GetString(flow_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,7 @@ private:
|
|||||||
|
|
||||||
wxString GetString(NozzleType nozzle_type) const;
|
wxString GetString(NozzleType nozzle_type) const;
|
||||||
wxString GetString(NozzleFlowType nozzle_flow_type) const;
|
wxString GetString(NozzleFlowType nozzle_flow_type) const;
|
||||||
wxString GetString(float diameter) const { return wxString::FromDouble(diameter); };
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class PrintOptionsDialog : public DPIDialog
|
class PrintOptionsDialog : public DPIDialog
|
||||||
|
|||||||
@@ -1823,7 +1823,15 @@ static bool _is_same_nozzle_diameters(MachineObject* obj, float &tag_nozzle_diam
|
|||||||
}
|
}
|
||||||
|
|
||||||
tag_nozzle_diameter = float(opt_nozzle_diameters->get_at(used_nozzle_idx));
|
tag_nozzle_diameter = float(opt_nozzle_diameters->get_at(used_nozzle_idx));
|
||||||
if (tag_nozzle_diameter != obj->GetExtderSystem()->GetNozzleDiameter(used_nozzle_idx))
|
auto machine_nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(used_nozzle_idx);
|
||||||
|
|
||||||
|
// Assume matching if diameter is unknown
|
||||||
|
if (machine_nozzle_diameter == 0.0f)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag_nozzle_diameter != machine_nozzle_diameter)
|
||||||
{
|
{
|
||||||
mismatch_nozzle_id = used_nozzle_idx;
|
mismatch_nozzle_id = used_nozzle_idx;
|
||||||
return false;
|
return false;
|
||||||
@@ -1840,7 +1848,16 @@ static bool _is_same_nozzle_diameters(MachineObject* obj, float &tag_nozzle_diam
|
|||||||
|
|
||||||
bool SelectMachineDialog::is_nozzle_hrc_matched(const DevExtder* extruder, std::string& filament_type) const
|
bool SelectMachineDialog::is_nozzle_hrc_matched(const DevExtder* extruder, std::string& filament_type) const
|
||||||
{
|
{
|
||||||
auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(extruder->GetNozzleType());
|
if (extruder == nullptr) return false;
|
||||||
|
|
||||||
|
auto printer_nozzle_type = extruder->GetNozzleType();
|
||||||
|
|
||||||
|
// Assume matching if nozzle type unknown
|
||||||
|
if (printer_nozzle_type == NozzleType::ntUndefine) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(printer_nozzle_type);
|
||||||
|
|
||||||
auto preset_bundle = wxGetApp().preset_bundle;
|
auto preset_bundle = wxGetApp().preset_bundle;
|
||||||
MaterialHash::const_iterator iter = m_materialList.begin();
|
MaterialHash::const_iterator iter = m_materialList.begin();
|
||||||
@@ -5154,13 +5171,11 @@ static wxString _get_tips(MachineObject* obj_)
|
|||||||
|
|
||||||
wxString ext_diameter;
|
wxString ext_diameter;
|
||||||
if (obj_->GetExtderSystem()->GetTotalExtderCount() == 1) {
|
if (obj_->GetExtderSystem()->GetTotalExtderCount() == 1) {
|
||||||
ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(0));
|
ext_diameter += format_nozzle_diameter(obj_->GetExtderSystem()->GetNozzleDiameter(0));
|
||||||
ext_diameter += "mm";
|
|
||||||
} else if (obj_->GetExtderSystem()->GetTotalExtderCount() == 2) {
|
} else if (obj_->GetExtderSystem()->GetTotalExtderCount() == 2) {
|
||||||
ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(1));//Left
|
ext_diameter += format_nozzle_diameter(obj_->GetExtderSystem()->GetNozzleDiameter(1));//Left
|
||||||
ext_diameter += "/";
|
ext_diameter += "/";
|
||||||
ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(0));
|
ext_diameter += format_nozzle_diameter(obj_->GetExtderSystem()->GetNozzleDiameter(0));
|
||||||
ext_diameter += "mm";
|
|
||||||
} else {
|
} else {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,7 +1132,12 @@ int GuideFrame::LoadProfileData()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sync to web
|
wxGetApp().CallAfter([this] {
|
||||||
|
if (!m_destroy) {
|
||||||
|
//sync to appconfig first to populate current selections
|
||||||
|
SaveProfileData();
|
||||||
|
|
||||||
|
//sync to web after selections are populated
|
||||||
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished, json contents: " << std::endl << strAll;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished, json contents: " << std::endl << strAll;
|
||||||
@@ -1132,13 +1145,10 @@ int GuideFrame::LoadProfileData()
|
|||||||
m_Res["command"] = "userguide_profile_load_finish";
|
m_Res["command"] = "userguide_profile_load_finish";
|
||||||
m_Res["sequence_id"] = "10001";
|
m_Res["sequence_id"] = "10001";
|
||||||
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', true));
|
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', true));
|
||||||
if (!m_destroy)
|
|
||||||
wxGetApp().CallAfter([this, strJS] { RunScript(strJS); });
|
|
||||||
|
|
||||||
//sync to appconfig
|
|
||||||
if (!m_destroy)
|
|
||||||
wxGetApp().CallAfter([this] { SaveProfileData(); });
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ bool QidiPrinterAgent::fetch_filament_info(std::string dev_id)
|
|||||||
series_id = infer_series_id(info.model_id, info.dev_name);
|
series_id = infer_series_id(info.model_id, info.dev_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (series_id.empty()) {
|
||||||
|
// Fall back to the configured Orca model if Moonraker doesn't expose a usable identifier.
|
||||||
|
series_id = infer_series_id(device_info.model_id, device_info.model_name);
|
||||||
|
}
|
||||||
|
|
||||||
// 2. Fetch filament dictionary
|
// 2. Fetch filament dictionary
|
||||||
QidiFilamentDict dict;
|
QidiFilamentDict dict;
|
||||||
|
|||||||
Reference in New Issue
Block a user