mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-21 19:33:26 +00:00
Fix + Support 'Default' filament option (index 0) (#13887)
* Support 'Default' filament option (index 0) Treat filament index 0 as the new "Default" (use active object/part filament) instead of using 1. Update config defaults and tooltips for wall/sparse/solid infill filament options (min/default -> 0, tooltip explains "Default"). Adjust normalization and propagation logic to respect explicit feature overrides and only apply base extruder when feature values are zero; only copy sparse->solid infill when sparse > 0. Introduce FeatureFilamentOverrideMask and clamp_feature_filament_to_valid to resolve and clamp feature filaments. Update UI lists and selection behavior to expose a "Default" entry and handle zero-based indices in PartPlate and Plater. * enable_filament_for_features option Co-Authored-By: LixNix <105106115+lixnix@users.noreply.github.com> * \n * Allow wipe_tower_filament to equal nozzle count Relax the assertion in Print::extruders to permit wipe_tower_filament == config().nozzle_diameter.size(). The configuration value is 1-based and the code subtracts 1 when pushing the extruder index, so equality should be valid and selecting the last nozzle should not trigger an assertion. * Revert "Allow wipe_tower_filament to equal nozzle count" This reverts commit 2c976574327a8bcdc74a1b296bf1aaff7752a94e. * Revert "enable_filament_for_features option" This reverts commit 01c13baeddb8e26793f752deab788ee4d086975b. * Migrate legacy feature filament defaults Add migration logic to convert legacy feature filament selections from 1 to 0 for older 3mf files. Introduces a local migrate_legacy_feature_filament_defaults lambda in src/OrcaSlicer.cpp and src/slic3r/GUI/Plater.cpp that scans keys (wall_filament, sparse_infill_filament, solid_infill_filament, support_filament, support_interface_filament) on configs/objects/volumes, updates values, counts conversions and logs the result. Also adds a Semver check for "2.4.0-dev" in OrcaSlicer to trigger the migration for files older than that version. This preserves expected default filament selections when loading older project files. * Update OrcaSlicer.cpp * Extract migration helper to ConfigMigrations Centralize legacy feature-filament default migration by moving the duplicated lambda into ConfigMigrations::migrate_legacy_feature_filament_defaults (src/libslic3r/Config.cpp) and declaring it in Config.hpp. Update OrcaSlicer.cpp and slic3r/GUI/Plater.cpp to call the new function instead of inline lambdas. The helper converts specific feature filament keys (wall_filament, sparse_infill_filament, solid_infill_filament, support_filament, support_interface_filament) from int 1 to 0 and returns the count of conversions to avoid duplicated migration logic. * Remove DynamicFilamentList1Based and consolidate lists Delete the specialized DynamicFilamentList1Based struct and its global instance. Update Choice registrations to use the single dynamic_filament_list for wall, sparse_infill and solid_infill filaments, and remove the extra update call for the removed instance. This consolidates filament choice handling and removes duplicated logic in Plater.cpp. * move it * fix objects * Update Config.hpp * Update profiles
This commit is contained in:
@@ -3511,6 +3511,12 @@ static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders
|
||||
opt.value = 1;
|
||||
}
|
||||
|
||||
static void clamp_feature_filament_to_valid(ConfigOptionInt &opt, size_t num_extruders)
|
||||
{
|
||||
if (opt.value <= 0 || opt.value > (int)num_extruders)
|
||||
opt.value = 1;
|
||||
}
|
||||
|
||||
PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders)
|
||||
{
|
||||
PrintObjectConfig config = default_object_config;
|
||||
@@ -3528,61 +3534,88 @@ PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObject
|
||||
const std::string key_extruder { "extruder" };
|
||||
static constexpr const std::initializer_list<const std::string_view> keys_extruders { "sparse_infill_filament"sv, "solid_infill_filament"sv, "wall_filament"sv };
|
||||
|
||||
static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in)
|
||||
struct FeatureFilamentOverrideMask
|
||||
{
|
||||
// 1) Map legacy "extruder" to feature filament keys as a fallback only.
|
||||
// If any feature-specific filament is explicitly set, keep those values.
|
||||
bool sparse_infill_filament = false;
|
||||
bool solid_infill_filament = false;
|
||||
bool wall_filament = false;
|
||||
};
|
||||
|
||||
static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in, FeatureFilamentOverrideMask &feature_overrides)
|
||||
{
|
||||
// 1) Explicit feature filament values take precedence over base extruder fallback.
|
||||
auto *opt_extruder = in.opt<ConfigOptionInt>(key_extruder);
|
||||
auto *opt_sparse_infill_filament = in.opt<ConfigOptionInt>("sparse_infill_filament");
|
||||
auto *opt_solid_infill_filament = in.opt<ConfigOptionInt>("solid_infill_filament");
|
||||
auto *opt_wall_filament = in.opt<ConfigOptionInt>("wall_filament");
|
||||
const bool has_feature_filament_override =
|
||||
(opt_sparse_infill_filament != nullptr && opt_sparse_infill_filament->value > 0) ||
|
||||
(opt_solid_infill_filament != nullptr && opt_solid_infill_filament->value > 0) ||
|
||||
(opt_wall_filament != nullptr && opt_wall_filament->value > 0);
|
||||
if (opt_extruder)
|
||||
if (int extruder = opt_extruder->value; extruder > 1 && ! has_feature_filament_override) {
|
||||
// Not a default extruder.
|
||||
out.sparse_infill_filament.value = extruder;
|
||||
out.solid_infill_filament.value = extruder;
|
||||
out.wall_filament.value = extruder;
|
||||
}
|
||||
int base_extruder = (opt_extruder != nullptr) ? opt_extruder->value : 0;
|
||||
|
||||
// 2) Copy the rest of the values.
|
||||
for (auto it = in.cbegin(); it != in.cend(); ++ it)
|
||||
if (it->first != key_extruder)
|
||||
if (ConfigOption* my_opt = out.option(it->first, false); my_opt != nullptr) {
|
||||
if (one_of(it->first, keys_extruders)) {
|
||||
// Ignore "default" extruders.
|
||||
// "Default" (0) clears explicit override for this scope and lets fallback apply.
|
||||
int extruder = static_cast<const ConfigOptionInt*>(it->second.get())->value;
|
||||
if (extruder > 0)
|
||||
if (extruder > 0) {
|
||||
my_opt->setInt(extruder);
|
||||
if (it->first == "sparse_infill_filament")
|
||||
feature_overrides.sparse_infill_filament = true;
|
||||
else if (it->first == "solid_infill_filament")
|
||||
feature_overrides.solid_infill_filament = true;
|
||||
else if (it->first == "wall_filament")
|
||||
feature_overrides.wall_filament = true;
|
||||
} else {
|
||||
if (it->first == "sparse_infill_filament")
|
||||
feature_overrides.sparse_infill_filament = false;
|
||||
else if (it->first == "solid_infill_filament")
|
||||
feature_overrides.solid_infill_filament = false;
|
||||
else if (it->first == "wall_filament")
|
||||
feature_overrides.wall_filament = false;
|
||||
}
|
||||
} else
|
||||
my_opt->set(it->second.get());
|
||||
}
|
||||
|
||||
// 3) Apply base extruder only to features that were not explicitly overridden.
|
||||
if (base_extruder > 0) {
|
||||
if (!feature_overrides.sparse_infill_filament)
|
||||
out.sparse_infill_filament.value = base_extruder;
|
||||
if (!feature_overrides.solid_infill_filament)
|
||||
out.solid_infill_filament.value = base_extruder;
|
||||
if (!feature_overrides.wall_filament)
|
||||
out.wall_filament.value = base_extruder;
|
||||
}
|
||||
}
|
||||
|
||||
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders)
|
||||
{
|
||||
PrintRegionConfig config = default_or_parent_region_config;
|
||||
FeatureFilamentOverrideMask feature_overrides;
|
||||
|
||||
// For model parts, non-zero values coming from the print defaults should stay explicit.
|
||||
if (volume.is_model_part()) {
|
||||
feature_overrides.sparse_infill_filament = (config.sparse_infill_filament.value > 0);
|
||||
feature_overrides.solid_infill_filament = (config.solid_infill_filament.value > 0);
|
||||
feature_overrides.wall_filament = (config.wall_filament.value > 0);
|
||||
}
|
||||
|
||||
if (volume.is_model_part()) {
|
||||
// default_or_parent_region_config contains the Print's PrintRegionConfig.
|
||||
// Override with ModelObject's PrintRegionConfig values.
|
||||
apply_to_print_region_config(config, volume.get_object()->config.get());
|
||||
apply_to_print_region_config(config, volume.get_object()->config.get(), feature_overrides);
|
||||
} else {
|
||||
// default_or_parent_region_config contains parent PrintRegion config, which already contains ModelVolume's config.
|
||||
}
|
||||
apply_to_print_region_config(config, volume.config.get());
|
||||
apply_to_print_region_config(config, volume.config.get(), feature_overrides);
|
||||
if (! volume.material_id().empty())
|
||||
apply_to_print_region_config(config, volume.material()->config.get());
|
||||
apply_to_print_region_config(config, volume.material()->config.get(), feature_overrides);
|
||||
if (layer_range_config != nullptr) {
|
||||
// Not applicable to modifiers.
|
||||
assert(volume.is_model_part());
|
||||
apply_to_print_region_config(config, *layer_range_config);
|
||||
apply_to_print_region_config(config, *layer_range_config, feature_overrides);
|
||||
}
|
||||
// Clamp invalid extruders to the default extruder (with index 1).
|
||||
clamp_exturder_to_default(config.sparse_infill_filament, num_extruders);
|
||||
clamp_exturder_to_default(config.wall_filament, num_extruders);
|
||||
clamp_exturder_to_default(config.solid_infill_filament, num_extruders);
|
||||
// Resolve feature defaults and clamp invalid extruders to index 1.
|
||||
clamp_feature_filament_to_valid(config.sparse_infill_filament, num_extruders);
|
||||
clamp_feature_filament_to_valid(config.wall_filament, num_extruders);
|
||||
clamp_feature_filament_to_valid(config.solid_infill_filament, num_extruders);
|
||||
if (config.sparse_infill_density.value < 0.00011f)
|
||||
// Switch of infill for very low infill rates, also avoid division by zero in infill generator for these very low rates.
|
||||
// See GH issue #5910.
|
||||
|
||||
Reference in New Issue
Block a user