diff --git a/src/libslic3r/Format/OBJ.hpp b/src/libslic3r/Format/OBJ.hpp index 7338fe0813..c103326af6 100644 --- a/src/libslic3r/Format/OBJ.hpp +++ b/src/libslic3r/Format/OBJ.hpp @@ -38,8 +38,8 @@ extern bool load_obj(const char *path, TriangleMesh *mesh, ObjInfo &vertex_color extern bool load_obj(const char *path, Model *model, ObjInfo &vertex_colors, std::string &message, const char *object_name = nullptr, ObjParser::MtlData *out_mtl = nullptr); struct TexturedMesh; -// Build a TexturedMesh (vertices + per-face UVs + decoded texture images) from a parsed OBJ -// plus its material table, so the texture-to-color importer can sample face colours. +// Build a TexturedMesh (vertices + per-face UVs + the texture files named by map_Kd) from a +// parsed OBJ plus its material table, so the texture-to-color importer can sample face colours. extern bool obj_to_textured_mesh( const ObjInfo& obj_info, const indexed_triangle_set& its, diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a98a991f03..f28918f05d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6106,8 +6106,7 @@ LayerResult GCode::process_layer( // A mixed-color slot is absent from layer_tools.extruders by design: resolve_mixed_filaments() // replaced it with its physical components. Its geometry is still keyed under the slot in // by_extruder though, and the sublayer emitter looks the plan up by slot id, so append the - // slots here. Appended (not merged) so the existing order is untouched, and empty for every - // configuration without sublayer splitting. + // slots here. Appending rather than merging leaves the flush-optimized order untouched. std::vector plan_filaments = layer_tools.extruders; for (const auto &grp : layer_tools.mixed_sub_layer_groups) if (std::find(plan_filaments.begin(), plan_filaments.end(), grp.mixed_slot_0based) == plan_filaments.end()) @@ -6593,8 +6592,8 @@ LayerResult GCode::process_layer( // Mixed-color sublayer extrusion: if this extruder is a component of a mixed sublayer // group, extrude the mixed slot's geometry at the appropriate sub-Z with scaled flow. - // Ported from BambuStudio's 混色耗材 feature; adapted to Orca's InstanceVisit-based - // instance loop and its finer-grained per-role region filament options. + // Ported from BambuStudio and adapted to Orca's instance loop and its finer-grained + // per-role region filament options. for (const auto &grp : layer_tools.mixed_sub_layer_groups) { int sub_idx = -1; for (size_t k = 0; k < grp.components_0based.size(); ++k) { diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index e59a607d7d..0a97e7ac41 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -91,11 +91,9 @@ bool check_filament_printable_after_group(const std::vector &used_ } // Return a zero based extruder from the region, or extruder_override if overriden. -// The region accessors below resolve mixed-color slots to the physical filament chosen for -// this layer. Without sub-layer splitting a mixed slot is realized by alternating whole layers -// (deficit round-robin, see resolve_mixed_filaments), so a region asking "which filament?" must -// get the resolved physical one, not the virtual slot id. resolve_mixed() is identity when the -// slot is not mixed, so this is a no-op for every non-mixed setup. +// The region accessors below resolve mixed-color slots to the physical filament chosen for this +// layer by resolve_mixed_filaments(), because a virtual slot id is never a real tool. resolve_mixed() +// returns its argument unchanged for every filament that is not a mixed slot. unsigned int LayerTools::wall_extruder_id(const PrintRegion ®ion) const { assert(region.config().outer_wall_filament_id.value > 0); @@ -2522,8 +2520,7 @@ void ToolOrdering::resolve_mixed_filaments(const PrintConfig &config) // - untagged region (modifier / painted / etc.) -> per_object_gradient[obj] // Populating both keeps the per-object run state correct even when per-volume // takes over for the same (slot, obj), and lets untagged geometry (which is - // explicitly NOT split per-volume in v1 per the design doc) keep its legacy - // per-object gradient ratios. + // never split per-volume) keep its per-object gradient ratios. if (grp.is_gradient) { auto vol_runs_slot_it = per_vol_runs.find(ext); if (vol_runs_slot_it != per_vol_runs.end()) { diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 71c042f4e0..600c46e7f5 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -309,9 +309,8 @@ Model Model::read_from_file(const std::string& ObjParser::MtlData mtl_data; result = load_obj(input_file.c_str(), &model, obj_info, message, nullptr, &mtl_data); if (result && obj_info.has_uv_png && !obj_info.uvs.empty() && !model.objects.empty()) { - // Textured OBJ: hand the mesh + materials to the texture-to-color importer instead - // of the flat per-face colour dialog. Replaces Orca's previous "not implemented" - // placeholder for this branch. + // Textured OBJ: hand the mesh + materials to the texture-to-color importer + // instead of the flat per-face colour dialog. auto tex_mesh = std::make_shared(); std::string obj_dir = boost::filesystem::path(input_file).parent_path().string(); if (obj_to_textured_mesh(obj_info, @@ -322,7 +321,7 @@ Model Model::read_from_file(const std::string& } else if (result && !model.objects.empty() && !model.objects.back()->volumes.empty()) { // Vertex-colour and MTL face-colour OBJs also go through the texture-to-color - // importer (as precomputed per-face colors) instead of the legacy flat + // importer (as precomputed per-face colors) instead of the flat // per-face colour dialog, matching the uv_png branch above. auto build_tex_mesh_geometry = [&]() { auto tex_mesh = std::make_shared(); @@ -374,7 +373,7 @@ Model Model::read_from_file(const std::string& else if (boost::algorithm::iends_with(input_file, ".glb") || boost::algorithm::iends_with(input_file, ".gltf") || boost::algorithm::iends_with(input_file, ".fbx")) { - // These formats always carry material/texture data, so they go through the textured + // These formats can carry material/texture data, so they go through the textured // import path: the geometry becomes a normal object and the texture is handed to the // texture-to-color dialog via Model::texture_mesh. auto tex_mesh = std::make_shared(); diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 74d48118e6..f92bb354ee 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -2715,19 +2715,13 @@ void PresetBundle::load_installed_sla_materials(AppConfig &config) preset.set_visible_from_appconfig(config); } -// Mixed-color filament metadata is project state, carried in the 3mf's project_settings.config. -// BambuStudio also snapshots it in the app config so the last session's mixes are back before any -// project is opened; there the filament list itself is a single global snapshot, so the mixed -// arrays live next to it in the global "presets" section. Orca's per-printer preset memory instead -// rebuilds the filament list from the selected printer's snapshot (filament_%02u/filament_colors) -// on startup AND on every printer selection — so the mixed arrays, whose component ids are 1-based -// indices into exactly that list, must live in the same per-printer snapshot or they end up -// describing a list they were never saved against (and previously got reset on every printer -// select, losing the mixes over a restart). -// Missing keys clear the arrays: a printer with no stored mixes must not inherit another's. -// fallback_to_global additionally reads the legacy shared "presets" keys (the old format) so a -// config saved by an earlier build still restores at startup; export_selections clears that -// section on the next save. +// Mixed-color filament metadata is project state saved in the 3mf, also mirrored into the app +// config so the last session's mixes are back before any project is opened. It is kept in the +// per-printer snapshot next to the filament list it indexes (filament_%02u/filament_colors), +// because that list is rebuilt on every printer selection and the component ids are 1-based +// indices into exactly that list. Missing keys clear the arrays, so one printer never inherits +// another's mixes; fallback_to_global also reads the shared "presets" keys an older config +// layout used, which export_selections drops on the next save. static void load_mixed_filament_settings(DynamicPrintConfig &project_config, AppConfig &config, const std::string &printer_name, size_t n_filaments, bool fallback_to_global) @@ -3162,12 +3156,9 @@ void PresetBundle::export_selections(AppConfig &config) "|"); config.set_printer_setting(printer_name, "flush_multiplier", flush_multiplier_str); - // Mixed-color filament metadata: stored in the per-printer snapshot next to the filament - // list it indexes (filament_%02u / filament_colors), so each printer's remembered config - // round-trips its own mixes and re-applying a snapshot never leaves the arrays describing a - // different list (see load_mixed_filament_settings). Bools are ','-joined; the - // component/ratio/range strings are '|'-joined; the gradient curve is escaped instead, - // because its values contain '|'. + // Mixed-color filament metadata goes into the per-printer snapshot next to the filament list + // it indexes (see load_mixed_filament_settings). Bools are ','-joined and the component, ratio + // and range strings '|'-joined; the gradient curve is escaped instead, as it contains '|'. auto join_bools = [](const std::vector &vals) { std::string s; for (size_t i = 0; i < vals.size(); ++i) { @@ -3227,8 +3218,7 @@ void PresetBundle::set_num_filaments(unsigned int n, std::vector ne ams_multi_color_filment.resize(n); // Mixed-color metadata is a parallel per-filament array set, so it has to grow and shrink - // with the filament count exactly like filament_colour above. Missing this leaves the - // arrays short and every lookup of a newly created slot reads past the end. + // with the filament count exactly like filament_colour above. if (auto* opt = project_config.option("filament_is_mixed")) opt->values.resize(n, false); if (auto* opt = project_config.option("filament_mixed_components")) @@ -3285,8 +3275,7 @@ void PresetBundle::set_num_filaments(unsigned int n, std::string new_color) ams_multi_color_filment.resize(n); // Mixed-color metadata is a parallel per-filament array set, so it has to grow and shrink - // with the filament count exactly like filament_colour above. Missing this leaves the - // arrays short and every lookup of a newly created slot reads past the end. + // with the filament count exactly like filament_colour above. if (auto* opt = project_config.option("filament_is_mixed")) opt->values.resize(n, false); if (auto* opt = project_config.option("filament_mixed_components")) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index e474818dfe..8be66da2a4 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2615,12 +2615,9 @@ void Print::process(long long *time_cost_with_cache, bool use_cache) print_object_instances_ordering = sort_object_instances_by_model_order(*this); // A mixed slot is virtual; only its components reach a nozzle. These per-object orderings // are unsorted (no resolve_mixed_filaments), so expand the slots here for the grouping, the - // unprintable sets and the slice-used lists. No-op without mixed filaments. - // Orca: the slice-used lists stay sourced from these expanded lists rather than from the - // sorted orderings (which may add the wipe-tower filament or seed dontcare layers - // differently), so prints without mixed filaments keep their used-filament set; the - // first-layer set therefore lists every component of a mixed slot, not just the one layer 0 - // resolves to. + // unprintable sets and the slice-used lists. Because the expansion happens here rather than + // on the sorted orderings, the first-layer used set lists every component of a mixed slot, + // not just the one layer 0 resolves to. No-op without mixed filaments. const auto &is_mixed = m_config.filament_is_mixed.values; const auto &comp_strs = m_config.filament_mixed_components.values; const bool has_mixed = has_any_mixed_filament(is_mixed); diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 7eb40946a4..f03271bf73 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -1931,8 +1931,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (const ModelVolume *volume : volumes) { const std::vector &volume_used_facet_states = volume->mmu_segmentation_facets.get_data().used_states; - // Sizes may legitimately differ: paint data stored before the state range was - // extended carries a shorter used_states vector. Merge over the common prefix. + // Paint data saved before the painted state range was extended deserializes a + // shorter used_states vector, so merge over the common prefix. for (size_t state_idx = 0; state_idx < std::min(volume_used_facet_states.size(), used_facet_states.size()); ++state_idx) used_facet_states[state_idx] |= volume_used_facet_states[state_idx]; } diff --git a/src/libslic3r/TextureToColor/TextureToColor.cpp b/src/libslic3r/TextureToColor/TextureToColor.cpp index bcdc985fc9..e5dde36714 100644 --- a/src/libslic3r/TextureToColor/TextureToColor.cpp +++ b/src/libslic3r/TextureToColor/TextureToColor.cpp @@ -639,9 +639,8 @@ static bool repair_cluster_smooth( { TriangleMesh stats_mesh(static_cast(mesh)); const auto& stats = stats_mesh.stats(); - // Orca's TriangleMeshStats defines manifold() as open_edges == 0 and does not track - // non-manifold edges/vertices separately, so BBS's "!manifold() || has_open_edges()" - // collapses to this single test and the extra counters drop out of the log. + // Orca's TriangleMeshStats only counts open edges: manifold() is open_edges == 0, and + // there are no separate non-manifold edge/vertex counters to test or log here. if (!stats.manifold()) { BOOST_LOG_TRIVIAL(info) << log_prefix << ": mesh has non-manifold geometry or open boundaries, open_edges=" << stats.open_edges; diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index dee0a93087..6584566f40 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -64,10 +64,9 @@ static constexpr double LARGE_BED_THRESHOLD = 2147; // Orca: maximum number of extruders is 64. For SEMM printers, it defines maximum filament number. static constexpr size_t MAXIMUM_EXTRUDER_NUMBER = 64; -// Orca: how many filament slots syncing an AMS setup may create. This used to follow -// EnforcerBlockerType::ExtruderMax, which capped it at the number of paintable filaments; that -// limit has since been raised to 32, so the value is pinned here to keep AMS sync behaving as -// before for projects that use no mixed-colour filaments. +// Orca: how many filament slots syncing an AMS setup may create. This was derived from +// EnforcerBlockerType::ExtruderMax, but that cap now covers 32 paintable filaments, so the AMS +// limit is pinned here to keep sync behaving as it does for projects without mixed-color filaments. static constexpr size_t MAXIMUM_AMS_SYNC_FILAMENT_NUMBER = 16; // Orca: maximum line width is 5 times the nozzle diameter diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 55a41a5720..d15164ef63 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -577,13 +577,9 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con } // BBS - // A filament override naming a slot that no longer exists is stale and falls back to the - // plater's value. Support and the wipe tower are additionally restricted to physical filaments: - // the engine consumes those keys directly, with no per-layer mixed resolution, so a virtual - // slot there would reach the G-code unresolved. The per-feature keys have no such restriction — - // LayerTools::extruder() and its siblings resolve a mixed slot to the physical filament chosen - // for each layer. The sidebar dropdowns already hide mixed slots for the restricted keys - // (Plater.cpp DynamicFilamentList); this reset covers values loaded from projects. + // Reset filament overrides pointing at a slot that no longer exists. Support and the wipe + // tower additionally reject mixed slots: the engine consumes those keys directly, so a virtual + // slot would reach the G-code unresolved, while the per-feature keys are resolved per layer. static const char* physical_only_keys[] = { "support_filament", "support_interface_filament", "wipe_tower_filament" }; static const char* feature_keys[] = { "outer_wall_filament_id", "inner_wall_filament_id", "sparse_infill_filament_id", "internal_solid_filament_id", diff --git a/src/slic3r/GUI/FilamentBitmapUtils.cpp b/src/slic3r/GUI/FilamentBitmapUtils.cpp index 45368e0537..1f51fc79b3 100644 --- a/src/slic3r/GUI/FilamentBitmapUtils.cpp +++ b/src/slic3r/GUI/FilamentBitmapUtils.cpp @@ -131,8 +131,7 @@ void fill_gradient_ramp_rect(wxDC& dc, const wxRect& rect, const std::vector 1) ? (double) (rect.height - 1 - y) / (rect.height - 1) : 0.5; dc.SetBrush(wxBrush(ramp[static_cast(t * (ramp.size() - 1) + 0.5)])); dc.DrawRectangle(rect.x, rect.y + y, rect.width, 1); diff --git a/src/slic3r/GUI/FilamentBitmapUtils.hpp b/src/slic3r/GUI/FilamentBitmapUtils.hpp index 9cb8d64249..11696f3401 100644 --- a/src/slic3r/GUI/FilamentBitmapUtils.hpp +++ b/src/slic3r/GUI/FilamentBitmapUtils.hpp @@ -38,19 +38,17 @@ wxColour blend_n_colors(const std::vector& cols, const std::vector sample_gradient_ramp(const wxColour& first, const wxColour& second, const Slic3r::GradientCurve& curve, int steps); // Same ramp for a project config slot, resolving components, colours and curve (or the -// linear gradient_range fallback) from cfg. Empty unless the slot is a two-component -// gradient mixed filament, which is what gates every caller to mixed slots only. -// steps is the ramp's resolution; pass the destination's height in pixels. +// linear gradient_range fallback) from cfg. Returns empty for any slot that is not a +// two-component gradient mixed filament. steps is the ramp's resolution; pass the +// destination's height in pixels. std::vector mixed_gradient_ramp(const Slic3r::DynamicPrintConfig& cfg, size_t slot, int steps); // Fill rect with a ramp, ramp.front() along the bottom edge. diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 94b0923885..6d03f992cd 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -9681,10 +9681,9 @@ void GLCanvas3D::_render_paint_toolbar() const } } } - // ORCA: the loop above only produces a label for a slot whose preset is found in the preset - // collection, while the render loop below iterates extruder_num (= colour count). Pad the - // label arrays so a slot without a matching preset cannot index past them — reading a garbage - // std::string here crashes in ImGui::CalcTextSize (strlen). + // ORCA: the loop above only labels a slot whose preset was found in the preset collection, + // while the render loop below iterates extruder_num. Pad the label arrays so a slot without a + // matching preset cannot index past them; a garbage std::string crashes ImGui::CalcTextSize. while (int(filament_text_first_line.size()) < extruder_num) { filament_text_first_line.emplace_back(); filament_text_second_line.emplace_back(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index d14943c94a..738af5e24c 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -8906,9 +8906,9 @@ void GUI_App::load_current_presets(bool active_preset_combox/*= false*/, bool ch auto* nozzle_diameter = edited_printer_preset.config.option("nozzle_diameter"); if (nozzle_diameter) { // Mixed-color slots are virtual filaments kept at the tail of the list, so they have no - // nozzle of their own. Sizing to the nozzle count alone truncates them away — and this - // runs right after a project is loaded, so it would silently drop the project's mixes - // and then let update_extruder_count() strip every painted facet above the new count. + // nozzle of their own. Sizing to the nozzle count alone would silently drop the mixes of + // a just-loaded project, and update_extruder_count() would then strip the facets painted + // with them. preset_bundle->set_num_filaments(nozzle_diameter->values.size() + preset_bundle->num_mixed_filaments()); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 48182da77b..b33cc82abc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -3234,8 +3234,8 @@ void ObjectList::merge(bool to_multipart_object) void ObjectList::layers_editing() { // Height ranges give each range its own layer height, varying the mixed sub-layer heights just - // like an adaptive profile; sibling of the on_action_layersediting/ConfigManipulation warnings, - // sharing the same do-not-show-again flag. + // like an adaptive profile, so this raises the same warning as variable layer height and shares + // its do-not-show-again flag. const auto& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; if (print_config.opt_bool("enable_mixed_color_sublayer")) { if (wxGetApp().app_config->get("no_warn_mixed_sublayer_variable_layer") != "1") { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 3f05f9c22c..3d4af75cde 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -326,10 +326,9 @@ bool GLGizmoMmuSegmentation::draw_color_button(int idx, const char* id_str, cons bool dark_tone = gradient ? (*gradient)[gradient->size() / 2].GetLuminance() < 0.51 : (0.299f * color.r() + 0.587f * color.g() + 0.114f * color.b()) < 0.51f; // matching values used by wxWidgets with clr.GetLuminance() < 0.51 - // Paint a gradient mixed filament's fade before the button and keep the button transparent, so the - // slot number and the frame below stay on top of it. The bands cannot round their corners, so the - // fade is drawn at the frame's inset and the frame masks it into the same shape a plain color slot - // gets. + // Paint a gradient mixed filament's fade before the button and keep the button transparent, so + // the slot number and the frame below stay on top of it. The bands cannot round their corners, + // so the fade is inset to the frame, which masks it into the shape a plain color slot gets. if (gradient) { ImGuiWrapper::draw_gradient_ramp(draw_list, {pos.x + frame_inset * scale, pos.y + frame_inset * scale}, {pos.x + size.x - frame_inset * scale, pos.y + size.y - frame_inset * scale}, *gradient); @@ -778,7 +777,7 @@ void GLGizmoMmuSegmentation::update_triangle_selectors_colors() TriangleSelectorPatch* selector = dynamic_cast(m_triangle_selectors[i].get()); int extruder_idx = m_volumes_extruder_idxs[i]; int extruder_color_idx = std::max(0, extruder_idx - 1); - // As above: a mixed-color slot can index past the physical colour list. + // A mixed-color slot can index past the physical colour list; fall back to the first colour. if (extruder_color_idx >= (int)m_extruders_colors.size()) extruder_color_idx = 0; std::vector ebt_colors; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 7d83468ea5..70cfde5aed 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -142,7 +142,7 @@ private: // ORCA bool draw_color_button(int idx, const char* id_str, const ColorRGBA& color, ColorRGBA& map_color, bool active, float scale); // Gradient ramp of a filament slot, or nullptr when the slot is a plain single color - // filament, so callers can index into what they get back freely. + // filament. A non-null result is never empty. const std::vector* gradient_of(int idx) const { return idx >= 0 && idx < (int) m_gradient_ramps.size() && !m_gradient_ramps[idx].empty() ? &m_gradient_ramps[idx] : nullptr; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 92c691f696..7882cf2269 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -998,8 +998,8 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) keyCode = keyCode- WXK_NUMPAD0+'0'; } if (keyCode >= '0' && keyCode <= '9') { - // The paint palette now reaches EXTRUDERS_LIMIT (mixed-color filaments share - // the same slots), so any leading digit that can start a valid two-digit + // The paint palette reaches EXTRUDERS_LIMIT slots (mixed-color filaments take + // ordinary slots too), so any leading digit that can start a valid two-digit // number waits briefly for a second one. const int digit = keyCode - '0'; const int shortcut_max = int(GLGizmoMmuSegmentation::EXTRUDERS_LIMIT); diff --git a/src/slic3r/GUI/GradientCurveEditor.cpp b/src/slic3r/GUI/GradientCurveEditor.cpp index d34e71a132..678fee0efc 100644 --- a/src/slic3r/GUI/GradientCurveEditor.cpp +++ b/src/slic3r/GUI/GradientCurveEditor.cpp @@ -19,7 +19,7 @@ namespace GUI { wxDEFINE_EVENT(wxEVT_GRADIENT_CURVE_CHANGED, wxCommandEvent); namespace { -// Layout (Figma "Property 1=Default", 214.06 x 179.63 px reference). +// Layout ratios of the plot rect within the widget, taken from a 214 x 180 px reference drawing. // Plot rect occupies the upper-left region; right + bottom margins host axis arrows / labels. constexpr double kPlotLeftRatio = 0.0316; constexpr double kPlotRightRatio = 0.6766; @@ -37,7 +37,7 @@ constexpr int kStrokeAxis = 2; // axis line width (px, no DPI scaling - constexpr int kAxisArrowHalf = 5; // half-base of the axis arrow triangle (DIP) constexpr int kAxisArrowLen = 10; // length of the axis arrow triangle (DIP) -// Light-mode design tokens from Figma. Resolved through StateColor::darkModeColorFor() +// Light-mode design tokens. Resolved through StateColor::darkModeColorFor() // at paint time so the editor follows the app theme (#EEEEEE -> #4C4C55, #6B6B6B -> // #818183, #262E30 -> #EFEFF0, *wxWHITE -> #2D2D31). Don't read these directly in paint; // always go through the resolved locals declared at the top of on_paint(). @@ -46,11 +46,9 @@ const wxColour kAxisColor (107, 107, 107); // #6B6B6B grey 700 const wxColour kLabelMuted (107, 107, 107); // #6B6B6B grey 700 const wxColour kLabelStrong ( 38, 46, 48); // #262E30 grey 900 -// LAB (DeltaE76) threshold for "curve color is too close to the background". Below this -// we paint a subtle axis-color outline so the curve doesn't visually vanish; above this -// we draw the curve plain. ~15 is "perceptible but still close", looser than the strict -// 5.0 used by FlushPredict::is_similar_color but loose enough that a pastel pink on white -// or a charcoal on #2B2B2B still triggers an outline. +// LAB (DeltaE76) threshold for "curve color is too close to the background": below it the curve +// gets a subtle outline so it does not visually vanish, otherwise it is drawn plain. Looser than +// the 5.0 of FlushPredict::is_similar_color, so a pastel pink on white still gets an outline. constexpr float kBgSimilarThreshold = 15.0f; constexpr int kOutlineExtraDip = 2; } // namespace @@ -65,8 +63,6 @@ GradientCurveEditor::GradientCurveEditor(wxWindow* parent, SetBackgroundStyle(wxBG_STYLE_PAINT); SetBackgroundColour(wxGetApp().get_window_default_clr()); // Wide enough so the X-axis "Material Ratio" label fits past the arrow tip without overlap. - // 260 (was 240): adds room for the "Material Ratio" label that gets shifted right by the - // longer axis arrow; the hosting MixedFilamentDialog grows to 470 DIP to accommodate. SetMinSize(FromDIP(wxSize(260, 200))); reset_to_linear(0.10, 0.90); @@ -456,10 +452,9 @@ void GradientCurveEditor::on_paint(wxPaintEvent& /*evt*/) return poly; }; - // Only the geometry goes through the graphics context: dc.DrawLines() takes integer - // wxPoint and would quantize the curve back to whole pixels. The pen is still set on - // the dc, which forwards it to this same context while keeping the dc's own cached - // state in sync, so later dc drawing does not inherit the curve's pen. + // Only the geometry goes through the graphics context: dc.DrawLines() takes integer wxPoint + // and would quantize the curve back to whole pixels. The pen is still set on the dc, which + // forwards it here while keeping its own cached state in sync for later dc drawing. auto draw_polyline = [&](const std::vector& poly, const wxColour& col, int stroke_dip) { dc.SetPen(wxPen(col, FromDIP(stroke_dip))); gc->StrokeLines(poly.size(), poly.data()); @@ -552,12 +547,9 @@ void GradientCurveEditor::on_left_down(wxMouseEvent& evt) // 4) Selected curve line body hit -> insert a new anchor at cursor x (snapped // to the current smooth curve so the initial click is visually invisible) - // and immediately enter Anchor drag mode. PS Curves style: the drag-bend - // interaction has no separate "bend without anchor" mode; pressing and - // dragging on the line is equivalent to clicking to add then dragging the - // fresh anchor. Trades the previous (failed) "no anchor on drag" promise - // for genuine cursor tracking, since a single cubic between two existing - // anchors mathematically cannot put its peak under an off-center cursor. + // and immediately enter Anchor drag mode. Bending the segment without + // inserting an anchor is not an option: a single cubic between two existing + // anchors cannot put its peak under an off-center cursor. double nx = 0, dummy = 0; px_to_data(pos.x, pos.y, nx, dummy); if (nx <= 0.0 || nx >= 1.0 || seg < 0) { diff --git a/src/slic3r/GUI/MixedFilamentDialog.cpp b/src/slic3r/GUI/MixedFilamentDialog.cpp index 91453a3113..46563664cc 100644 --- a/src/slic3r/GUI/MixedFilamentDialog.cpp +++ b/src/slic3r/GUI/MixedFilamentDialog.cpp @@ -894,9 +894,9 @@ wxBoxSizer* MixedFilamentDialog::create_ratio_slider() on_ratio_changed(std::max(MIN_COMPONENT_RATIO, std::min(100 - MIN_COMPONENT_RATIO, new_ratio))); }); - // Release whenever the capture is held, not only when the drag flag is set: - // the flag can be cleared behind our back, and a capture that outlives the - // widget wedges mouse input for the whole application. + // Key the release off the capture itself, not off the drag flag: the two can fall out of + // sync (a lost capture clears the flag on its own), and a capture that outlives the widget + // wedges mouse input for the whole application. m_ratio_bar->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) { m_ratio_dragging = false; if (m_ratio_bar->HasCapture()) @@ -1492,11 +1492,9 @@ void MixedFilamentDialog::on_ratio_changed(int new_ratio_a) void MixedFilamentDialog::on_gradient_toggled() { - // Orca: the engine only produces a gradient when the print profile's - // "enable_mixed_color_sublayer" option is on (ToolOrdering::resolve_mixed_filaments - // falls back to whole-layer round-robin without it, and BBS leaves users to find the - // option themselves). Offer to switch it on so the gradient the user just enabled - // actually shows up in the sliced result. Keep this block on future BBS syncs. + // Orca: a gradient is only sliced when the print profile's "enable_mixed_color_sublayer" + // option is on; without it ToolOrdering picks a single component per whole layer. Offer to + // turn the option on instead of silently ignoring the gradient the user just enabled. bool checked = m_chk_gradient->GetValue(); if (checked) { diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 74f13d94df..73c8073e4f 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2048,13 +2048,8 @@ bool PartPlate::check_tpu_printable_status(const DynamicPrintConfig & config, co } // A mixed-color filament alternates between its components constantly. On a single-nozzle -// printer every one of those switches is a full filament change plus a purge, so warn the -// user before they commit to it. Printers with more than one nozzle can keep the components -// loaded simultaneously and are not affected. -// -// BBS additionally excludes its H2C/H2D/X2D models by name; those are multi-nozzle machines -// already ruled out by the nozzle_diameter test above, so the name check is dropped here -// rather than carried over as a Bambu-specific special case. +// printer every one of those switches is a full filament change plus a purge, so warn before +// slicing. Multi-nozzle printers keep the components loaded at once and are not affected. bool PartPlate::check_single_extruder_mixed_filament_risk(const DynamicPrintConfig &config, std::string &warning_text) const { warning_text.clear(); diff --git a/src/slic3r/GUI/PlateSettingsDialog.cpp b/src/slic3r/GUI/PlateSettingsDialog.cpp index e7f1d926d9..bc81335d61 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.cpp +++ b/src/slic3r/GUI/PlateSettingsDialog.cpp @@ -473,8 +473,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title m_sizer_main->Add(m_other_layers_seq_panel, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); // A mixed-color slot resolves to a different physical filament per layer, so a user-defined - // filament order cannot be honoured. Disable the choice and say why. BBS puts this warning - // inside its button sizer; Orca builds the buttons with DialogButtons, so it gets its own row. + // filament order cannot be honoured; grey out the choice and explain that in the dialog. { auto &proj_cfg = wxGetApp().preset_bundle->project_config; auto *is_mixed_opt = proj_cfg.option("filament_is_mixed"); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c730dd705e..8b0fcc3902 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3876,10 +3876,8 @@ void Sidebar::change_top_border_for_mode_sizer(bool increase_border) // ---- Mixed-color filament sidebar support ---- -// Ported from BambuStudio's 混色耗材 feature. BBS hosts these widgets in an -// m_filament_area_wrapper that Orca's sidebar has no counterpart for, so the mixed -// section is parented to p->scrolled and sized with Orca's own row-height preference -// (filaments_area_preferred_count) rather than BBS's fixed 3-row / 12-filament cap. +// The mixed rows get their own scroll area, capped by Orca's filaments_area_preferred_count +// row budget rather than BBS's fixed 3-row / 12-filament limit. void Sidebar::recalc_filament_scroll_sizes() { if (!p->m_mixed_scroll_area || !p->m_mixed_scroll_area->GetSizer()) @@ -4102,8 +4100,8 @@ void Sidebar::update_mixed_filament_list() unsigned int mix_num = (unsigned int)(cfg_idx + 1); // The swatch fades bottom to top over the model's height, sampled the same way - // the slicer builds the sublayers, so it matches the editor's Effect Preview. It - // comes back empty for every slot that is not a two component gradient mix. + // the slicer builds the sublayers, so it matches the editor's Effect Preview. The + // ramp comes back empty for every slot that is not a two component gradient mix. const int swatch_sz = FromDIP(20); const std::vector gradient_ramp = mixed_gradient_ramp(project_config, cfg_idx, swatch_sz); @@ -4642,9 +4640,8 @@ static bool create_mixed_filament_from_result( multi_colour_opt->values[new_idx] = mixed_color; } - // set_num_filaments() above is what grows these parallel arrays. Guard the writes anyway, - // matching the gradient writes below, so a sizing bug degrades into a no-op rather than a - // heap overwrite. + // set_num_filaments() above already grows these parallel arrays; the writes are still + // size-guarded so a sizing bug degrades into a no-op rather than a heap overwrite. { auto* is_mixed_opt = project_config.option("filament_is_mixed"); while (is_mixed_opt->values.size() <= new_idx) is_mixed_opt->values.push_back(false); @@ -14071,11 +14068,9 @@ bool Plater::priv::can_layers_editing() const void Plater::priv::on_action_layersediting(SimpleEvent&) { - // Sub-layer splitting divides each layer by the mix ratio, so an adaptive layer profile makes - // those sub-layer heights vary and degrades the blend. ConfigManipulation warns when the - // option is switched on with a variable profile already present; this is the other direction, - // warning when variable layer editing is switched on while the option is active. All three - // sites (with ObjectList::layers_editing for height ranges) honour the same do-not-show-again flag. + // Sub-layer splitting divides each layer by the mix ratio, so a variable layer height profile + // makes those sub-layer heights uneven and degrades the blend. ConfigManipulation warns for the + // opposite order, when the option is switched on while a variable profile already exists. if (!view3D->is_layers_editing_enabled()) { const auto& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; if (print_config.opt_bool("enable_mixed_color_sublayer")) { @@ -19988,14 +19983,11 @@ std::vector Plater::get_filament_color_render_type() const const std::vector>& Plater::get_filament_gradient_ramps() const { - // Sampling a ramp walks the measured-blend recipe table once per step, and the paint toolbar - // asks for the ramps on every rendered frame, so they are cached against the config values - // they are built from and resampled only when one of those actually changes. - // - // The cache cannot live on the Plater: the extruder icons ask for the ramps from inside - // MenuFactory::init(), which runs while this Plater is still being constructed, so `this` is - // not usable yet. Everything the ramps are built from is global anyway, and there is one - // Plater per process, which is the same reasoning behind the icons' own static BitmapCache. + // Sampling a ramp walks the measured-blend recipe table once per step and the paint toolbar + // asks for the ramps every rendered frame, so they are cached against the config values they + // are built from. The cache is static rather than a Plater member because the extruder icons + // ask for the ramps from MenuFactory::init(), which runs while this Plater is still inside its + // own constructor, so wxGetApp().plater_ is not assigned yet. static std::string s_ramps_key; static std::vector> s_ramps; diff --git a/src/slic3r/GUI/SyncAmsInfoDialog.cpp b/src/slic3r/GUI/SyncAmsInfoDialog.cpp index 5005b49303..9515ecc116 100644 --- a/src/slic3r/GUI/SyncAmsInfoDialog.cpp +++ b/src/slic3r/GUI/SyncAmsInfoDialog.cpp @@ -2577,7 +2577,7 @@ void SyncAmsInfoDialog::reset_and_sync_ams_list() m_filaments.clear(); // Mixed-color slots are virtual: they never occupy a tray, so they must not appear as - // AMS sync targets. Look the flags up once and skip those slots in the loop below. + // AMS sync targets. auto* is_mixed_opt = preset_bundle->project_config.option("filament_is_mixed"); bool use_double_extruder = get_is_double_extruder(); @@ -2801,7 +2801,7 @@ void SyncAmsInfoDialog::generate_override_fix_ams_list() m_fix_filaments.clear(); // Mixed-color slots are virtual: they never occupy a tray, so they must not appear as - // AMS sync targets. Look the flags up once and skip those slots in the loop below. + // AMS sync targets. auto* is_mixed_opt = preset_bundle->project_config.option("filament_is_mixed"); bool use_double_extruder = get_is_double_extruder(); diff --git a/src/slic3r/GUI/TextureImportDialog.cpp b/src/slic3r/GUI/TextureImportDialog.cpp index 688898ed0a..ef9beda4d0 100644 --- a/src/slic3r/GUI/TextureImportDialog.cpp +++ b/src/slic3r/GUI/TextureImportDialog.cpp @@ -1368,11 +1368,9 @@ void TexturePreviewCanvas::ensure_gl_ready() { if (m_gl_initialized) return; - // BBS loads GL entry points here with GLEW. Orca uses glad and centralises loading in - // OpenGLManager, which has already run by the time any canvas is realized, so just - // verify the loader is up and drain any stale error state. - // glad leaves unresolved entry points as null pointers, so this is a cheap guard against - // painting before OpenGLManager::init_gl() has run. + // BBS loads the GL entry points here with GLEW; Orca loads them centrally in + // OpenGLManager, so only check that this has already happened (glad leaves unresolved + // entry points null) and drain any stale error state. if (glGetString == nullptr) { BOOST_LOG_TRIVIAL(error) << "TexturePreviewCanvas: OpenGL functions are not loaded yet"; return; @@ -2436,10 +2434,9 @@ void TextureImportDialog::start_computation(bool auto_color, bool initial) settings.target_colors_num = auto_color ? 0 : (size_t)m_param_color_count; settings.smooth_weight = m_param_smooth / 10.0; settings.mesh_repair_decision = m_mesh_repair_decision; - // BBS repairs the mesh through the Windows 3D SDK, which only exists on Windows and only - // when the SDK is present at build time. Orca already ships a CGAL-based repair - // (MeshBoolean::cgal::repair) that works on all three platforms, so use that instead — - // this makes the repair path available on Linux and macOS too. + // BBS repairs the mesh through the Windows 3D SDK, which is only available on Windows + // builds that ship the SDK. Orca's CGAL-based repair (MeshBoolean::cgal::repair) works + // on all three platforms, so use that instead. settings.mesh_repair_callback = [](const indexed_triangle_set& mesh, indexed_triangle_set& repaired_mesh, std::function progress_callback, diff --git a/src/slic3r/GUI/Widgets/DropDown.cpp b/src/slic3r/GUI/Widgets/DropDown.cpp index a44303169a..aae8bccf9e 100644 --- a/src/slic3r/GUI/Widgets/DropDown.cpp +++ b/src/slic3r/GUI/Widgets/DropDown.cpp @@ -360,8 +360,7 @@ void DropDown::render(wxDC &dc) for (int i = 0; i < items.size(); ++i) { auto &item = items[i]; int states2 = states; - // Dimmed items stay selectable but render greyed out (used by the mixed-filament - // dialog to show components that are already consumed by another mix). + // Dimmed items render greyed out but stay selectable, so they cannot reuse the disabled state. bool is_dimmed = (item.style & DD_ITEM_STYLE_DIMMED) != 0; if ((item.style & DD_ITEM_STYLE_DISABLED) != 0) states2 &= ~StateColor::Enabled; diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp index 70aba0404e..d4fbcc6fe3 100644 --- a/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/src/slic3r/GUI/WipeTowerDialog.cpp @@ -261,10 +261,9 @@ static std::vector MatrixFlatten(const WipingDialog::VolumeMatrix& matrix return vec; } -// Mixed-color slots are virtual: they are never loaded into a tray and so have no flushing -// volumes of their own. The dialog therefore shows only the physical filaments, which means -// converting between the full config matrix (indexed by config slot) and a dense physical -// sub-matrix (indexed by row/column in the table). +// Mixed-color slots are virtual and have no flushing volumes, so the dialog shows only the +// physical filaments. That means converting between the full config matrix (indexed by config +// slot) and a dense physical sub-matrix (indexed by row/column in the table). static std::vector extract_physical_sub_matrix( const std::vector& full_matrix, size_t full_n, const std::vector& indices) diff --git a/tests/fff_print/test_mixed_filament.cpp b/tests/fff_print/test_mixed_filament.cpp index 143ecdcb6e..a8f1e2e84c 100644 --- a/tests/fff_print/test_mixed_filament.cpp +++ b/tests/fff_print/test_mixed_filament.cpp @@ -37,7 +37,7 @@ DynamicPrintConfig mixed_config(bool sublayer_on, const char *ratios = "0.6,0.4" return config; } -// Total sub-layer groups and per-layer DRR resolutions across the whole tool ordering. +// Total sub-layer groups and per-layer mixed-filament resolutions across the whole tool ordering. void count_mixed(ToolOrdering &to, size_t &groups, size_t &resolutions) { groups = resolutions = 0; @@ -139,9 +139,8 @@ TEST_CASE("Whole-layer mixing emits only the nominal layer height", "[MixedFilam TEST_CASE("By-object prints without mixed filaments keep their used-filament set", "[MixedFilament]") { - // Regression guard for the mixed gate: with no mixed slot the by-object bookkeeping must - // be untouched by this change. Object 2 prints with filament 2, so both filaments are used - // and no mixed filament is reported. + // With no mixed slot the by-object bookkeeping stays plain: object 2 prints with filament 2, + // so both filaments are used and no mixed filament is reported. DynamicPrintConfig config = multifilament_config(2, {{"print_sequence", "by object"}}); const std::vector> overrides{ {}, { {"extruder", "2"} } }; diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index e09f664b7e..4c0a09cf3f 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -501,10 +501,8 @@ SCENARIO("Nozzle-group metadata .3mf round-trip", "[3mf][MultiNozzle]") { // A mixed-color filament occupies an ordinary filament slot, and painting with it stores an -// ordinary extruder state — a project saved by BambuStudio encodes filament 5 of a 5-slot setup -// as paint state 5, with the mix described by the parallel filament_mixed_* project arrays. This -// pins both halves of that contract at the .3mf layer: the project keys and the painted states -// must come back exactly as written. +// ordinary extruder state: a project saved by BambuStudio encodes filament 5 of a 5-slot setup +// as paint state 5, with the mix described by the parallel filament_mixed_* project arrays. SCENARIO("Mixed-color filament setup and painting round-trip through a .3mf", "[3mf][MixedFilament]") { GIVEN("a painted model whose project config describes a mixed filament in the last slot") { Model model; diff --git a/tests/libslic3r/test_filament_mixer.cpp b/tests/libslic3r/test_filament_mixer.cpp index fb11fa9481..ade0c910dc 100644 --- a/tests/libslic3r/test_filament_mixer.cpp +++ b/tests/libslic3r/test_filament_mixer.cpp @@ -101,10 +101,9 @@ TEST_CASE("check_mixed_filament_type_consistency flags mismatched component type TEST_CASE("a support-flagged component reads as its own filament type for the consistency check", "[FilamentMixer]") { - // Sidebar::update_mixed_filament_list and Sidebar::has_broken_mixed_filament derive each - // component's type through DynamicPrintConfig::get_filament_type, which folds the - // filament_is_support flag into the type — so toggling that flag alone changes the verdict - // and Plater::on_config_change has to refresh the mixed list on filament_is_support too. + // The sidebar derives each component's type through DynamicPrintConfig::get_filament_type, + // which folds filament_is_support into the type, so toggling that flag alone flips the + // verdict and the mixed filament list has to be refreshed on filament_is_support too. DynamicPrintConfig plain_pla; plain_pla.set_key_value("filament_type", new ConfigOptionStrings({"PLA"})); plain_pla.set_key_value("filament_is_support", new ConfigOptionBools({false})); @@ -193,8 +192,8 @@ TEST_CASE("blend_color_multi weights components", "[FilamentMixer]") } SECTION("Mixing a color with itself stays close to that color") { - // The mixer is a degree-4 polynomial fit of pigment behaviour, so a round trip through - // it is near-identity rather than exact (the model documents a mean Delta-E around 2). + // The mixer is a degree-4 polynomial fit of pigment behaviour, so mixing a color with + // itself lands near it rather than exactly on it; allow a small per-channel drift. std::string mixed = blend_color_multi({"#123456", "#123456"}, {1, 1}); REQUIRE(mixed.size() == 7); auto comp = [](const std::string &hex, int i) { diff --git a/tests/libslic3r/test_preset_bundle_loading.cpp b/tests/libslic3r/test_preset_bundle_loading.cpp index 0fb6f3e2f8..ea05ec0cf5 100644 --- a/tests/libslic3r/test_preset_bundle_loading.cpp +++ b/tests/libslic3r/test_preset_bundle_loading.cpp @@ -614,12 +614,10 @@ TEST_CASE("set_num_filaments keeps mixed-color arrays in step with the filament } } -// A mix is described by 1-based indices into the project's filament list. Orca's per-printer -// preset memory rebuilds that list from the selected printer's snapshot (filament_%02u / -// filament_colors) at startup and on every printer selection, so the mixed arrays must be stored -// in the SAME per-printer snapshot: kept globally (as BambuStudio does — its filament list is a -// single global snapshot too) they end up indexing a list they were never saved against, and used -// to be reset on every printer selection instead, losing the mixes over an app restart. +// A mix is described by 1-based indices into the project's filament list, which Orca rebuilds +// from the selected printer's snapshot (filament_%02u / filament_colors) at startup and on every +// printer selection. Held anywhere but that same per-printer snapshot, the mixed arrays end up +// indexing a filament list they were never saved against. TEST_CASE("Mixed-color filament metadata is snapshotted per printer, with its filament list", "[Preset][Bundle][FilamentMixer]") { PresetBundle bundle; @@ -674,10 +672,9 @@ TEST_CASE("A multi-point gradient curve survives the app-config snapshot", "[Pre } // A multi-tool printer sizes the filament list from its nozzle count. Mixed-color slots are extra -// virtual filaments at the tail of that list with no nozzle of their own, so the sync has to add -// them on top. Sizing to the nozzle count alone truncates them — and because that sync runs right -// after a project is loaded, it silently drops the project's mixes and then lets the filament-count -// change strip every painted facet above the new count. +// virtual filaments at the tail of that list with no nozzle of their own, so the count has to +// allow for them: sizing to the nozzle count alone drops the project's mixes and strips every +// painted facet above the new count. TEST_CASE("Sizing the filament list to a multi-tool nozzle count keeps mixed slots", "[Preset][Bundle][FilamentMixer]") { // The 5-slot layout of a 4-tool project carrying one mix of filaments 2 and 3. diff --git a/tests/libslic3r/test_triangle_selector.cpp b/tests/libslic3r/test_triangle_selector.cpp index dfeae477b9..0bdc639626 100644 --- a/tests/libslic3r/test_triangle_selector.cpp +++ b/tests/libslic3r/test_triangle_selector.cpp @@ -99,7 +99,7 @@ TEST_CASE("Extruder states above 17 are encoded in a second nibble", "[TriangleS } // Model.cpp writes these hex strings into the 3MF for colored mesh imports; the selector must -// decode exactly the states that table assigns to them. +// decode exactly the states CONST_FILAMENTS assigns to them. TEST_CASE("Extruder states match the CONST_FILAMENTS hex encoding", "[TriangleSelector]") { struct Case { const char *hex; int state; }; diff --git a/tests/slic3rutils/test_filament_bitmap_utils.cpp b/tests/slic3rutils/test_filament_bitmap_utils.cpp index 35c32570f4..997a119521 100644 --- a/tests/slic3rutils/test_filament_bitmap_utils.cpp +++ b/tests/slic3rutils/test_filament_bitmap_utils.cpp @@ -140,8 +140,8 @@ TEST_CASE("recompute_mixed_slot_colors honours the configured ratios and is idem // --- mixed_gradient_ramp / sample_gradient_ramp ----------------------------------------- // // The ramp is what every mixed filament swatch is drawn from, so these pin the three things -// a plain two-endpoint fade got wrong: the reserved ratio band, the component order, and the -// custom curve. +// a plain fade between two endpoint colours cannot express: the reserved ratio band, the +// component order, and the custom curve. namespace { @@ -169,7 +169,7 @@ TEST_CASE("mixed_gradient_ramp runs bottom to top and never reaches a pure compo REQUIRE(ramp.size() == 16); // Neither end is the pure component colour - the slicer clamps the blend to - // [kGradientMinRatio, kGradientMaxRatio], which is exactly what a two-endpoint fade missed. + // [kGradientMinRatio, kGradientMaxRatio], which a fade between the pure colours would ignore. REQUIRE(ramp.front() != wxColour(255, 0, 0)); REQUIRE(ramp.back() != wxColour(0, 0, 255)); @@ -188,7 +188,7 @@ TEST_CASE("mixed_gradient_ramp follows the range's direction rather than the com REQUIRE(falling.size() == 16); // "0.1,0.9" starts blue-heavy at the bottom; "0.9,0.1" starts red-heavy. Reversing the - // range must reverse the ramp, which HSV-sorted endpoint colours could not express. + // range must reverse the ramp, which endpoint colours ordered by HSV cannot express. REQUIRE(int(rising.front().Blue()) > int(rising.front().Red())); REQUIRE(int(falling.front().Red()) > int(falling.front().Blue())); require_same_rgb(rising.front(), falling.back());