diff --git a/src/octoprint/plugins/cura/__init__.py b/src/octoprint/plugins/cura/__init__.py index 3633cf5e..058445d6 100644 --- a/src/octoprint/plugins/cura/__init__.py +++ b/src/octoprint/plugins/cura/__init__.py @@ -246,11 +246,11 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, machinecode_path = path + ".gco" if position and isinstance(position, dict) and "x" in position and "y" in position: - posX = position["x"] - posY = position["y"] + pos_x = position["x"] + pos_y = position["y"] else: - posX = None - posY = None + pos_x = None + pos_y = None if on_progress: if not on_progress_args: @@ -266,8 +266,24 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, working_dir = os.path.dirname(executable) - slicing_profile = Profile(self._load_profile(profile_path), printer_profile, posX, posY) - engine_settings = self._convert_to_engine(profile_path, printer_profile, posX, posY) + slicing_profile = Profile(self._load_profile(profile_path), printer_profile, pos_x, pos_y) + + # NOTE: We can assume an extruder count of 1 here since the only way we currently + # support dual extrusion in this implementation is by using the second extruder for support (which + # the engine conversion will automatically detect and adapt accordingly). + # + # We currently do only support STL files as sliceables, which by default can only contain one mesh, + # so no risk of having to slice multi-objects at the moment, which would necessitate a full analysis + # of the objects to slice to determine amount of needed extruders to use here. If we ever decide to + # also support dual extrusion slicing (including composition from multiple STLs or support for OBJ or + # AMF files and the like), this code needs to be adapted! + # + # The extruder count is needed to decide which start/end gcode will be used from the Cura profile. + # Stock Cura implementation counts the number of objects in the scene for this (and also takes a look + # at the support usage, like the engine conversion here does). We only ever have one object. + engine_settings = self._convert_to_engine(profile_path, printer_profile, + pos_x=pos_x, pos_y=pos_y, + used_extruders=1) # Start building the argument list for the CuraEngine command execution args = [executable, '-v', '-p'] @@ -443,9 +459,9 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, with octoprint.util.atomic_write(path, "wb", max_permissions=0o666) as f: yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True) - def _convert_to_engine(self, profile_path, printer_profile, posX, posY): - profile = Profile(self._load_profile(profile_path), printer_profile, posX, posY) - return profile.convert_to_engine() + def _convert_to_engine(self, profile_path, printer_profile, pos_x=None, pos_y=None, used_extruders=1): + profile = Profile(self._load_profile(profile_path), printer_profile, pos_x, pos_y) + return profile.convert_to_engine(used_extruders=used_extruders) def _sanitize_name(name): if name is None: diff --git a/src/octoprint/plugins/cura/profile.py b/src/octoprint/plugins/cura/profile.py index 5f8538bd..2f8792d0 100644 --- a/src/octoprint/plugins/cura/profile.py +++ b/src/octoprint/plugins/cura/profile.py @@ -674,9 +674,7 @@ class Profile(object): return default return int(value * 1000) - def get_gcode_template(self, key): - extruder_count = self.get_int("extruder_amount") - + def get_gcode_template(self, key, extruder_count=1): if key in self._profile: gcode = self._profile[key] else: @@ -736,7 +734,7 @@ class Profile(object): return pre + str(f) - def get_gcode(self, key): + def get_gcode(self, key, extruder_count=1): prefix = "" postfix = "" @@ -746,11 +744,11 @@ class Profile(object): return "" if key == "start_gcode": - contents = self.get_gcode_template("start_gcode") + contents = self.get_gcode_template("start_gcode", extruder_count=extruder_count) prefix += self.get_start_gcode_prefix(contents) else: - contents = self.get_gcode_template(key) + contents = self.get_gcode_template(key, extruder_count=extruder_count) return unicode(prefix + re.sub("(.)\{([^\}]*)\}", self.replaceTagMatch, contents).rstrip() + '\n' + postfix).strip().encode('utf-8') + '\n' @@ -861,13 +859,14 @@ class Profile(object): return int(self.get_float("machine_depth") / 2.0) if not self.get_boolean("machine_center_is_zero") else 0.0 - def convert_to_engine(self): + def convert_to_engine(self, used_extruders=1): edge_width, line_count = self.calculate_edge_width_and_line_count() solid_layer_count = self.calculate_solid_layer_count() extruder_count = self.get_int("extruder_amount") minimal_extruder_count = self.calculate_minimal_extruder_count() + actual_extruder_count = max(minimal_extruder_count, used_extruders) settings = { "layerThickness": self.get_microns("layer_height"), @@ -916,10 +915,10 @@ class Profile(object): "posy": self.get_pos_y() * 1000, # in microns # gcodes - "startCode": self.get_gcode("start_gcode"), - "endCode": self.get_gcode("end_gcode"), - "preSwitchExtruderCode": self.get_gcode("preSwitchExtruder_gcode"), - "postSwitchExtruderCode": self.get_gcode("postSwitchExtruder_gcode"), + "startCode": self.get_gcode("start_gcode", extruder_count=actual_extruder_count), + "endCode": self.get_gcode("end_gcode", extruder_count=actual_extruder_count), + "preSwitchExtruderCode": self.get_gcode("preSwitchExtruder_gcode", extruder_count=actual_extruder_count), + "postSwitchExtruderCode": self.get_gcode("postSwitchExtruder_gcode", extruder_count=actual_extruder_count), # fixing "fixHorrible": 0,