diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 776d92a1f63..1536d541c76 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -810,11 +810,6 @@ def _updateDisallowedAreas(self) -> None: break if prime_tower_collision: # Already found a collision. break - if self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft": - brim_size = self._calculateBedAdhesionSize(used_extruders, "brim") - # Use 2x the brim size, since we need 1x brim size distance due to the object brim and another - # times the brim due to the brim of the prime tower - prime_tower_areas[extruder_id][area_index] = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(2 * brim_size, num_segments = 24)) if not prime_tower_collision: result_areas[extruder_id].extend(prime_tower_areas[extruder_id]) result_areas_no_brim[extruder_id].extend(prime_tower_areas[extruder_id]) @@ -840,9 +835,13 @@ def _computeDisallowedAreasPrinted(self, used_extruders): result = {} skirt_brim_extruder: ExtruderStack = None + skirt_brim_extruder_nr = self._global_container_stack.getProperty("skirt_brim_extruder_nr", "value") + for extruder in used_extruders: - if int(extruder.getProperty("extruder_nr", "value")) == int(self._global_container_stack.getProperty("skirt_brim_extruder_nr", "value")): - skirt_brim_extruder = extruder + if skirt_brim_extruder_nr == -1: + skirt_brim_extruder = used_extruders[0] # The prime tower brim is always printed with the first extruder + elif int(extruder.getProperty("extruder_nr", "value")) == int(skirt_brim_extruder_nr): + skirt_brim_extruder = extruder result[extruder.getId()] = [] # Currently, the only normally printed object is the prime tower. @@ -856,15 +855,6 @@ def _computeDisallowedAreasPrinted(self, used_extruders): prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left. prime_tower_y = prime_tower_y + machine_depth / 2 - if skirt_brim_extruder is not None and self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft": - brim_size = ( - skirt_brim_extruder.getProperty("brim_line_count", "value") * - skirt_brim_extruder.getProperty("skirt_brim_line_width", "value") / 100.0 * - skirt_brim_extruder.getProperty("initial_layer_line_width_factor", "value") - ) - prime_tower_x -= brim_size - prime_tower_y += brim_size - radius = prime_tower_size / 2 prime_tower_area = Polygon.approximatedCircle(radius, num_segments = 24) prime_tower_area = prime_tower_area.translate(prime_tower_x - radius, prime_tower_y - radius) @@ -1076,7 +1066,7 @@ def _getSettingFromAllExtruders(self, setting_key: str) -> List[Any]: all_values[i] = 0 return all_values - def _calculateBedAdhesionSize(self, used_extruders, adhesion_override = None): + def _calculateBedAdhesionSize(self, used_extruders): """Get the bed adhesion size for the global container stack and used extruders :param adhesion_override: override adhesion type. @@ -1086,52 +1076,12 @@ def _calculateBedAdhesionSize(self, used_extruders, adhesion_override = None): return None container_stack = self._global_container_stack - adhesion_type = adhesion_override - if adhesion_type is None: - adhesion_type = container_stack.getProperty("adhesion_type", "value") - - # Skirt_brim_line_width is a bit of an odd one out. The primary bit of the skirt/brim is printed - # with the adhesion extruder, but it also prints one extra line by all other extruders. As such, the - # setting does *not* have a limit_to_extruder setting (which means that we can't ask the global extruder what - # the value is. - skirt_brim_extruder_nr = self._global_container_stack.getProperty("skirt_brim_extruder_nr", "value") - try: - skirt_brim_stack = self._global_container_stack.extruderList[int(skirt_brim_extruder_nr)] - except IndexError: - Logger.warning(f"Couldn't find extruder with index '{skirt_brim_extruder_nr}', defaulting to 0 instead.") - skirt_brim_stack = self._global_container_stack.extruderList[0] - skirt_brim_line_width = skirt_brim_stack.getProperty("skirt_brim_line_width", "value") - - initial_layer_line_width_factor = skirt_brim_stack.getProperty("initial_layer_line_width_factor", "value") - # Use brim width if brim is enabled OR the prime tower has a brim. - if adhesion_type == "brim": - brim_line_count = skirt_brim_stack.getProperty("brim_line_count", "value") - brim_gap = skirt_brim_stack.getProperty("brim_gap", "value") - bed_adhesion_size = brim_gap + skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0 - - for extruder_stack in used_extruders: - bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 - - # We don't create an additional line for the extruder we're printing the brim with. - bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0 - elif adhesion_type == "skirt": - skirt_distance = skirt_brim_stack.getProperty("skirt_gap", "value") - skirt_line_count = skirt_brim_stack.getProperty("skirt_line_count", "value") - - bed_adhesion_size = skirt_distance + ( - skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0 - - for extruder_stack in used_extruders: - bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 - - # We don't create an additional line for the extruder we're printing the skirt with. - bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0 - elif adhesion_type == "raft": + adhesion_type = container_stack.getProperty("adhesion_type", "value") + + if adhesion_type == "raft": bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value") # Should refer to the raft extruder if set. - elif adhesion_type == "none": + else: # raft, brim or skirt. Those last two are handled by CuraEngine. bed_adhesion_size = 0 - else: - raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?") max_length_available = 0.5 * min( self._global_container_stack.getProperty("machine_width", "value"), diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 52d63b611ba..f429a0de197 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -275,7 +275,7 @@ def getUsedExtruderStacks(self) -> List["ExtruderStack"]: for extruder_setting in used_adhesion_extruders: extruder_str_nr = str(global_stack.getProperty(extruder_setting, "value")) if extruder_str_nr == "-1": - extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition + continue # An optional extruder doesn't force any extruder to be used if it isn't used already if extruder_str_nr in self.extruderIds: used_extruder_stack_ids.add(self.extruderIds[extruder_str_nr]) @@ -298,7 +298,7 @@ def getInitialExtruderNr(self) -> int: # Starts with the adhesion extruder. adhesion_type = global_stack.getProperty("adhesion_type", "value") if adhesion_type in {"skirt", "brim"}: - return global_stack.getProperty("skirt_brim_extruder_nr", "value") + return max(0, int(global_stack.getProperty("skirt_brim_extruder_nr", "value"))) # optional skirt/brim extruder defaults to zero if adhesion_type == "raft": return global_stack.getProperty("raft_base_extruder_nr", "value") diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index e93193818c6..eba41569b79 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -142,8 +142,6 @@ def getProperty(self, key: str, property_name: str, context: Optional[PropertyEv limit_to_extruder = super().getProperty(key, "limit_to_extruder", context) if limit_to_extruder is not None: - if limit_to_extruder == -1: - limit_to_extruder = int(cura.CuraApplication.CuraApplication.getInstance().getMachineManager().defaultExtruderPosition) limit_to_extruder = str(limit_to_extruder) if (limit_to_extruder is not None and limit_to_extruder != "-1") and self.getMetaDataEntry("position") != str(limit_to_extruder): diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 041bd19d3a4..25fc74b28f1 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -226,8 +226,6 @@ def getProperty(self, key: str, property_name: str, context: Optional[PropertyEv # Handle the "limit_to_extruder" property. limit_to_extruder = super().getProperty(key, "limit_to_extruder", context) if limit_to_extruder is not None: - if limit_to_extruder == -1: - limit_to_extruder = int(cura.CuraApplication.CuraApplication.getInstance().getMachineManager().defaultExtruderPosition) limit_to_extruder = str(limit_to_extruder) if limit_to_extruder is not None and limit_to_extruder != "-1" and limit_to_extruder in self._extruders: if super().getProperty(key, "settable_per_extruder", context): diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 64216f373fe..d06136a2b4b 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -487,6 +487,10 @@ def _buildGlobalSettingsMessage(self, stack: ContainerStack) -> None: settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], initial_extruder_nr) settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], initial_extruder_nr) + # Manually add 'nozzle offsetting', since that is a metadata-entry instead for some reason. + # NOTE: This probably needs to be an actual setting at some point. + settings["nozzle_offsetting_for_disallowed_areas"] = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("nozzle_offsetting_for_disallowed_areas", True) + # Add all sub-messages for each individual setting. for key, value in settings.items(): setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings") diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 15bd6914b5e..08a895c9fa5 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4785,7 +4785,6 @@ "default_value": 8.0, "minimum_value": "0.0", "maximum_value_warning": "50.0", - "maximum_value": "0.5 * min(machine_width, machine_depth)", "enabled": "(support_enable or support_meshes_present) and support_brim_enable", "settable_per_mesh": false, "settable_per_extruder": true, @@ -4800,7 +4799,6 @@ "default_value": 20, "minimum_value": "0", "maximum_value_warning": "50 / skirt_brim_line_width", - "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", "value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))", "enabled": "(support_enable or support_meshes_present) and support_brim_enable", "settable_per_mesh": false, @@ -5559,10 +5557,11 @@ { "label": "Skirt/Brim Extruder", "description": "The extruder train to use for printing the skirt or brim. This is used in multi-extrusion.", - "type": "extruder", + "type": "optional_extruder", "default_value": "0", "value": "adhesion_extruder_nr", "enabled": "extruders_enabled_count > 1 and (resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable'))", + "resolve": "'-1' if '-1' in extruderValues('skirt_brim_extruder_nr') else adhesion_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -5614,9 +5613,9 @@ "maximum_value_warning": "10", "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", "enabled": "resolveOrValue('adhesion_type') == 'skirt'", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr" + "settable_per_extruder": true }, "skirt_gap": { @@ -5628,9 +5627,9 @@ "minimum_value_warning": "max(extruderValues('machine_nozzle_size'))", "maximum_value_warning": "10", "enabled": "resolveOrValue('adhesion_type') == 'skirt'", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr" + "settable_per_extruder": true }, "skirt_brim_minimal_length": { @@ -5643,6 +5642,7 @@ "minimum_value_warning": "25", "maximum_value_warning": "2500", "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -5655,11 +5655,10 @@ "default_value": 8.0, "minimum_value": "0.0", "maximum_value_warning": "50.0", - "maximum_value": "0.5 * min(machine_width, machine_depth)", "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr", "children": { "brim_line_count": @@ -5670,12 +5669,11 @@ "default_value": 20, "minimum_value": "0", "maximum_value_warning": "50 / skirt_brim_line_width", - "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", "value": "math.ceil(brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))", "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr" + "settable_per_extruder": true } } }, @@ -5689,9 +5687,9 @@ "minimum_value": "0", "maximum_value_warning": "skirt_brim_line_width", "enabled": "resolveOrValue('adhesion_type') == 'brim'", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": true, - "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr" + "settable_per_extruder": true }, "brim_replaces_support": { @@ -5700,9 +5698,9 @@ "type": "bool", "default_value": true, "enabled": "resolveOrValue('adhesion_type') == 'brim' and (support_enable or support_meshes_present)", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "support_infill_extruder_nr" + "settable_per_extruder": true }, "brim_outside_only": { @@ -5711,9 +5709,22 @@ "type": "bool", "default_value": true, "enabled": "resolveOrValue('adhesion_type') == 'brim'", + "limit_to_extruder": "skirt_brim_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "skirt_brim_extruder_nr" + "settable_per_extruder": true + }, + "brim_inside_margin": + { + "label": "Brim Inside Avoid Margin", + "description": "If brim is only on outside then parts fully enclosed inside another part will get a brim which might overlap with the internal holes of the outer part. This setting controls how far to stay away from those internal holes. Set to a high value to prevent any brim from being generated for parts enclosed within the holes of other parts.", + "unit": "mm", + "type": "float", + "default_value": 5, + "minimum_value": "0", + "enabled": "resolveOrValue('adhesion_type') == 'brim' and any(extruderValues('brim_outside_only'))", + "limit_to_extruder": "skirt_brim_extruder_nr", + "settable_per_mesh": false, + "settable_per_extruder": true }, "raft_margin": { diff --git a/tests/TestBuildVolume.py b/tests/TestBuildVolume.py index 458b7afad37..5012784bdf0 100644 --- a/tests/TestBuildVolume.py +++ b/tests/TestBuildVolume.py @@ -86,12 +86,12 @@ def test_noGlobalStack(self, build_volume: BuildVolume): ({"adhesion_type": {"value": "skirt"}}, 0), ({"adhesion_type": {"value": "raft"}}, 0), ({"adhesion_type": {"value": "none"}}, 0), - ({"adhesion_type": {"value": "skirt"}, "skirt_line_count": {"value": 2}, "initial_layer_line_width_factor": {"value": 1}, "skirt_brim_line_width": {"value": 2}}, 0.02), + ({"adhesion_type": {"value": "skirt"}, "skirt_line_count": {"value": 2}, "initial_layer_line_width_factor": {"value": 1}, "skirt_brim_line_width": {"value": 2}}, 0), # Even though it's marked as skirt, it should behave as a brim as the prime tower has a brim (skirt line count is still at 0!) - ({"adhesion_type": {"value": "skirt"}, "prime_tower_brim_enable": {"value": True}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, -0.06), + ({"adhesion_type": {"value": "skirt"}, "prime_tower_brim_enable": {"value": True}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0), ({"brim_line_count": {"value": 1}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0), - ({"brim_line_count": {"value": 2}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0.06), - ({"brim_line_count": {"value": 9000000}, "skirt_brim_line_width": {"value": 90000}, "initial_layer_line_width_factor": {"value": 9000}}, 100), # Clamped at half the max size of buildplate + ({"brim_line_count": {"value": 2}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0), + ({"brim_line_count": {"value": 9000000}, "skirt_brim_line_width": {"value": 90000}, "initial_layer_line_width_factor": {"value": 9000}}, 0), # Clamped at half the max size of buildplate ]) def test_singleExtruder(self, build_volume: BuildVolume, setting_dict, result): self.createAndSetGlobalStack(build_volume) @@ -106,14 +106,6 @@ def test_singleExtruder(self, build_volume: BuildVolume, setting_dict, result): with patch.dict(self.setting_property_dict, patched_dictionary): assert build_volume._calculateBedAdhesionSize([]) == result - def test_unknownBedAdhesion(self, build_volume: BuildVolume): - self.createAndSetGlobalStack(build_volume) - patched_dictionary = self.setting_property_dict.copy() - patched_dictionary.update({"adhesion_type": {"value": "OMGZOMGBBQ"}}) - with patch.dict(self.setting_property_dict, patched_dictionary): - with pytest.raises(Exception): - build_volume._calculateBedAdhesionSize([]) - class TestComputeDisallowedAreasStatic: setting_property_dict = {"machine_disallowed_areas": {"value": [[[-200, 112.5], [ -82, 112.5], [ -84, 102.5], [-115, 102.5]]]}, "machine_width": {"value": 200},