Merge branch 'maintenance' into main/supportPasswordManagers
This commit is contained in:
commit
881d3bb212
14 changed files with 97 additions and 51 deletions
|
|
@ -12,6 +12,7 @@ or **[creating pull requests](#pull-requests)**.
|
|||
* [Where can I find which version and branch I'm on?](#where-can-i-find-which-version-and-branch-im-on)
|
||||
* [Where can I find those log files you keep talking about?](#where-can-i-find-those-log-files-you-keep-talking-about)
|
||||
* [Where can I find my browser's error console?](#where-can-i-find-my-browsers-error-console)
|
||||
* [Setting up a development environment](#setting-up-a-development-environment)
|
||||
* [Pull requests](#pull-requests)
|
||||
* [What do the branches mean?](#what-do-the-branches-mean)
|
||||
* [How OctoPrint is versioned](#how-octoprint-is-versioned)
|
||||
|
|
@ -235,6 +236,10 @@ find information on how to do just that in the
|
|||
|
||||
See [How to open the Javascript Console in different browsers](https://webmasters.stackexchange.com/questions/8525/how-to-open-the-javascript-console-in-different-browsers)
|
||||
|
||||
## Setting up a development environment
|
||||
|
||||
See [the corresponding chapter in the documentation](http://docs.octoprint.org/en/master/development/index.html#setting-up-a-development-environment).
|
||||
|
||||
## Pull requests
|
||||
|
||||
1. If you want to add a new feature to OctoPrint, **please always first
|
||||
|
|
|
|||
|
|
@ -86,27 +86,27 @@ following usage examples assume that said `octoprint` script is on your `PATH`.
|
|||
|
||||
You can start the server via
|
||||
|
||||
octoprint
|
||||
octoprint serve
|
||||
|
||||
By default it binds to all interfaces on port 5000 (so pointing your browser to `http://127.0.0.1:5000`
|
||||
will do the trick). If you want to change that, use the additional command line parameters `host` and `port`,
|
||||
which accept the host ip to bind to and the numeric port number respectively. If for example you want the server
|
||||
to only listen on the local interface on port 8080, the command line would be
|
||||
|
||||
octoprint --host=127.0.0.1 --port=8080
|
||||
octoprint serve --host=127.0.0.1 --port=8080
|
||||
|
||||
Alternatively, the host and port on which to bind can be defined via the configuration.
|
||||
|
||||
If you want to run OctoPrint as a daemon (only supported on Linux), use
|
||||
|
||||
octoprint --daemon {start|stop|restart} [--pid PIDFILE]
|
||||
octoprint daemon {start|stop|restart} [--pid PIDFILE]
|
||||
|
||||
If you do not supply a custom pidfile location via `--pid PIDFILE`, it will be created at `/tmp/octoprint.pid`.
|
||||
|
||||
You can also specify the configfile or the base directory (for basing off the `uploads`, `timelapse` and `logs` folders),
|
||||
e.g.:
|
||||
|
||||
octoprint --config /path/to/another/config.yaml --basedir /path/to/my/basedir
|
||||
octoprint serve --config /path/to/another/config.yaml --basedir /path/to/my/basedir
|
||||
|
||||
See `octoprint --help` for further information.
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ IDE Setup
|
|||
PyCharm
|
||||
.......
|
||||
|
||||
- "File" > "Open ...", select OctoPrint checkout folder (e.g. ``~/devel/OctoPrint/venv`` or ``C:\Devel\OctoPrint``)
|
||||
- "File" > "Open ...", select OctoPrint checkout folder (e.g. ``~/devel/OctoPrint`` or ``C:\Devel\OctoPrint``)
|
||||
- "File" > "Settings ..." > "Project: OctoPrint" > "Project Interpreter" > "Add local ...", select OctoPrint venv
|
||||
folder (e.g. ``~/devel/OctoPrint/venv`` or ``C:\Devel\OctoPrint\venv``)
|
||||
- Right click "src" in project tree, mark as source folder
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -15,6 +15,9 @@ import octoprint_setuptools
|
|||
# Requirements for our application
|
||||
INSTALL_REQUIRES = [
|
||||
"flask>=0.9,<0.11",
|
||||
"Jinja2>=2.8,<2.9", # Jinja 2.9 has breaking changes WRT template scope - we can't
|
||||
# guarantee backwards compatibility for plugins and such with that
|
||||
# version, hence we need to pin to a lower version for now. See #1697
|
||||
"werkzeug>=0.8.3,<0.9",
|
||||
"tornado==4.0.2", # pinned for now, we need to migrate to a newer tornado, but due
|
||||
# to some voodoo needed to get large streamed uploads and downloads
|
||||
|
|
|
|||
|
|
@ -511,7 +511,7 @@ class LocalFileStorage(StorageInterface):
|
|||
filepath = self.sanitize_path(filepath)
|
||||
path = self.sanitize_path(path)
|
||||
|
||||
return filepath == path or filepath.startswith(path + "/")
|
||||
return filepath == path or filepath.startswith(path + os.sep)
|
||||
|
||||
def file_exists(self, path):
|
||||
path, name = self.sanitize(path)
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ 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)
|
||||
|
||||
# Start building the argument list for the CuraEngine command execution
|
||||
|
|
@ -375,11 +376,11 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
|
|||
if not tool_key in analysis["filament"]:
|
||||
analysis["filament"][tool_key] = dict()
|
||||
|
||||
if profile.get_float("filament_diameter") != None:
|
||||
if profile.get("gcode_flavor") == GcodeFlavors.ULTIGCODE or profile.get("gcode_flavor") == GcodeFlavors.REPRAP_VOLUME:
|
||||
analysis["filament"][tool_key] = _get_usage_from_volume(filament, profile.get_float("filament_diameter"))
|
||||
if slicing_profile.get_float("filament_diameter") is not None:
|
||||
if slicing_profile.get("gcode_flavor") == GcodeFlavors.ULTIGCODE or slicing_profile.get("gcode_flavor") == GcodeFlavors.REPRAP_VOLUME:
|
||||
analysis["filament"][tool_key] = _get_usage_from_volume(filament, slicing_profile.get_float("filament_diameter"))
|
||||
else:
|
||||
analysis["filament"][tool_key] = _get_usage_from_length(filament, profile.get_float("filament_diameter"))
|
||||
analysis["filament"][tool_key] = _get_usage_from_length(filament, slicing_profile.get_float("filament_diameter"))
|
||||
|
||||
except:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -63,12 +63,14 @@ defaults = dict(
|
|||
solid_top=True,
|
||||
solid_bottom=True,
|
||||
fill_overlap=15,
|
||||
perimeter_before_infill=False,
|
||||
|
||||
# speeds
|
||||
print_speed=50.0,
|
||||
travel_speed=150.0,
|
||||
bottom_layer_speed=20.0,
|
||||
infill_speed=0.0,
|
||||
solidarea_speed=0.0,
|
||||
outer_shell_speed=0.0,
|
||||
inner_shell_speed=0.0,
|
||||
|
||||
|
|
@ -117,8 +119,11 @@ defaults = dict(
|
|||
raft_base_linewidth=1.0,
|
||||
raft_interface_thickness=0.27,
|
||||
raft_interface_linewidth=0.4,
|
||||
raft_airgap_all=0.0,
|
||||
raft_airgap=0.22,
|
||||
raft_surface_layers=2,
|
||||
raft_surface_thickness=0.27,
|
||||
raft_surface_linewidth=0.4,
|
||||
|
||||
# repairing
|
||||
fix_horrible_union_all_type_a=True,
|
||||
|
|
@ -754,9 +759,13 @@ class Profile(object):
|
|||
|
||||
prefix = ""
|
||||
|
||||
gcode_parameter_key = "S"
|
||||
if self.get("gcode_flavor") == GcodeFlavors.MACH3:
|
||||
gcode_parameter_key = "P"
|
||||
|
||||
e_steps = self.get_float("steps_per_e")
|
||||
if e_steps > 0:
|
||||
prefix += "M92 E{e_steps}\n" % (e_steps)
|
||||
prefix += "M92 E{e_steps}\n".format(e_steps=e_steps)
|
||||
temp = self.get_float("print_temperature")
|
||||
|
||||
bed_temp = 0
|
||||
|
|
@ -765,30 +774,30 @@ class Profile(object):
|
|||
include_bed_temp = bed_temp > 0 and not "{print_bed_temperature}" in Profile.regex_strip_comments.sub("", contents)
|
||||
|
||||
if include_bed_temp:
|
||||
prefix += "M140 S{bed_temp}\n".format(bed_temp=bed_temp)
|
||||
prefix += "M140 {param}{bed_temp}\n".format(param=gcode_parameter_key, bed_temp=bed_temp)
|
||||
|
||||
if temp > 0 and not "{print_temperature}" in Profile.regex_strip_comments.sub("", contents):
|
||||
if extruder_count > 0:
|
||||
def temp_line(temp, extruder, template):
|
||||
def temp_line(temp, extruder, param, template):
|
||||
t = temp
|
||||
if extruder > 0:
|
||||
print_temp = self.get_float("print_temperature%d" % (extruder + 1))
|
||||
if print_temp > 0:
|
||||
t = print_temp
|
||||
return template.format(extruder=extruder, temp=t)
|
||||
return template.format(extruder=extruder, temp=t, param=param)
|
||||
|
||||
prefix_preheat = ""
|
||||
prefix_waitheat = ""
|
||||
for n in range(0, extruder_count):
|
||||
if n > 0:
|
||||
prefix_preheat += temp_line(temp, n, "M104 T{extruder} S{temp}\n")
|
||||
prefix_waitheat += temp_line(temp, n, "M109 T{extruder} S{temp}\n")
|
||||
prefix_preheat += temp_line(temp, n, gcode_parameter_key, "M104 T{extruder} {param}{temp}\n")
|
||||
prefix_waitheat += temp_line(temp, n, gcode_parameter_key, "M109 T{extruder} {param}{temp}\n")
|
||||
prefix += prefix_preheat + prefix_waitheat + "T0\n"
|
||||
else:
|
||||
prefix += "M109 S{temp}\n".format(temp=temp)
|
||||
prefix += "M109 {param}{temp}\n".format(param=gcode_parameter_key, temp=temp)
|
||||
|
||||
if include_bed_temp:
|
||||
prefix += "M190 S{bed_temp}\n".format(bed_temp=bed_temp)
|
||||
prefix += "M190 {param}{bed_temp}\n".format(param=gcode_parameter_key, bed_temp=bed_temp)
|
||||
|
||||
return prefix
|
||||
|
||||
|
|
@ -822,7 +831,7 @@ class Profile(object):
|
|||
if layer_height == 0.0:
|
||||
return 1
|
||||
import math
|
||||
return int(math.ceil(solid_thickness / (layer_height - 0.0001)))
|
||||
return int(math.ceil((solid_thickness - 0.0001) / layer_height))
|
||||
|
||||
def calculate_minimal_extruder_count(self):
|
||||
extruder_count = self.get("extruder_amount")
|
||||
|
|
@ -871,12 +880,14 @@ class Profile(object):
|
|||
"downSkinCount": solid_layer_count if self.get_boolean("solid_bottom") else 0,
|
||||
"upSkinCount": solid_layer_count if self.get_boolean("solid_top") else 0,
|
||||
"infillOverlap": self.get_int("fill_overlap"),
|
||||
"perimeterBeforeInfill": 1 if self.get_boolean("perimeter_before_infill") else 0,
|
||||
"initialSpeedupLayers": int(4),
|
||||
"initialLayerSpeed": self.get_int("bottom_layer_speed"),
|
||||
"printSpeed": self.get_int("print_speed"),
|
||||
"infillSpeed": self.get_int("infill_speed") if self.get_int("infill_speed") > 0 else self.get_int("print_speed"),
|
||||
"inset0Speed": self.get_int("outer_shell_speed") if self.get_int("outer_shell_speed") > 0 else self.get_int("print_speed"),
|
||||
"insetXSpeed": self.get_int("inner_shell_speed") if self.get_int("inner_shell_speed") > 0 else self.get_int("print_speed"),
|
||||
"skinSpeed": self.get_int("solidarea_speed") if self.get_int("solidarea_speed") > 0 > 0 else self.get_int("print_speed"),
|
||||
"moveSpeed": self.get_int("travel_speed"),
|
||||
"fanSpeedMin": self.get_int("fan_speed") if self.get_boolean("fan_enabled") else 0,
|
||||
"fanSpeedMax": self.get_int("fan_speed_max") if self.get_boolean("fan_enabled") else 0,
|
||||
|
|
@ -892,13 +903,14 @@ class Profile(object):
|
|||
"retractionAmountExtruderSwitch": self.get_microns("retraction_dual_amount"),
|
||||
"retractionZHop": self.get_microns("retraction_hop"),
|
||||
"minimalExtrusionBeforeRetraction": self.get_microns("retraction_minimal_extrusion"),
|
||||
"enableCombing": 1 if self.get("retraction_combing") == RetractionCombingTypes.ALL else (2 if self.get("retraction_combing") == RetractionCombingTypes.NO_SKIN else 0),
|
||||
"multiVolumeOverlap": self.get_microns("overlap_dual"),
|
||||
"objectSink": max(0, self.get_microns("object_sink")),
|
||||
"minimalLayerTime": self.get_int("cool_min_layer_time"),
|
||||
"minimalFeedrate": self.get_int("cool_min_feedrate"),
|
||||
"coolHeadLift": 1 if self.get_boolean("cool_head_lift") else 0,
|
||||
|
||||
"enableCombing": 1 if self.get("retraction_combing") == RetractionCombingTypes.ALL else (2 if self.get("retraction_combing") == RetractionCombingTypes.NO_SKIN else 0),
|
||||
|
||||
# model positioning
|
||||
"posx": self.get_pos_x() * 1000, # in microns
|
||||
"posy": self.get_pos_y() * 1000, # in microns
|
||||
|
|
@ -952,12 +964,13 @@ class Profile(object):
|
|||
settings["raftInterfaceThickness"] = self.get_microns("raft_interface_thickness")
|
||||
settings["raftInterfaceLinewidth"] = self.get_microns("raft_interface_linewidth")
|
||||
settings["raftInterfaceLineSpacing"] = self.get_microns("raft_interface_linewidth") * 2
|
||||
settings["raftAirGapLayer0"] = self.get_microns("raft_airgap")
|
||||
settings["raftAirGapLayer0"] = self.get_microns("raft_airgap") + self.get_microns("raft_airgap_all")
|
||||
settings["raftAirGap"] = self.get_microns("raft_airgap_all")
|
||||
settings["raftBaseSpeed"] = self.get_int("bottom_layer_speed")
|
||||
settings["raftFanSpeed"] = 100
|
||||
settings["raftSurfaceThickness"] = settings["raftInterfaceThickness"]
|
||||
settings["raftSurfaceLinewidth"] = int(edge_width * 1000)
|
||||
settings["raftSurfaceLineSpacing"] = int(edge_width * 1000 * 0.9)
|
||||
settings["raftFanSpeed"] = 0
|
||||
settings["raftSurfaceThickness"] = self.get_microns("raft_surface_thickness")
|
||||
settings["raftSurfaceLinewidth"] = self.get_microns("raft_surface_linewidth")
|
||||
settings["raftSurfaceLineSpacing"] = self.get_microns("raft_surface_linewidth")
|
||||
settings["raftSurfaceLayers"] = self.get_int("raft_surface_layers")
|
||||
settings["raftSurfaceSpeed"] = self.get_int("bottom_layer_speed")
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
|
|||
#~~ progress plugin reporting
|
||||
|
||||
def _reportPrintProgressToPlugins(self, progress):
|
||||
if not progress or not self._selectedFile or not "sd" in self._selectedFile or not "filename" in self._selectedFile:
|
||||
if progress is None or not self._selectedFile or not "sd" in self._selectedFile or not "filename" in self._selectedFile:
|
||||
return
|
||||
|
||||
storage = "sdcard" if self._selectedFile["sd"] else "local"
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ def _verifyFolderExists(origin, foldername):
|
|||
|
||||
|
||||
def _isBusy(target, path):
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and currentOrigin == target and fileManager.file_in_path(FileDestinations.LOCAL, path, currentFilename) and (printer.is_printing() or printer.is_paused()):
|
||||
currentOrigin, currentPath = _getCurrentFile()
|
||||
if currentPath is not None and currentOrigin == target and fileManager.file_in_path(FileDestinations.LOCAL, path, currentPath) and (printer.is_printing() or printer.is_paused()):
|
||||
return True
|
||||
|
||||
return any(target == x[0] and fileManager.file_in_path(FileDestinations.LOCAL, path, x[1]) for x in fileManager.get_busy_files())
|
||||
|
|
@ -705,8 +705,8 @@ def deleteGcodeFile(filename, target):
|
|||
return make_response("Trying to delete a file that is currently in use: %s" % filename, 409)
|
||||
|
||||
# deselect the file if it's currently selected
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and currentOrigin == target and filename == currentFilename:
|
||||
currentOrigin, currentPath = _getCurrentFile()
|
||||
if currentPath is not None and currentOrigin == target and filename == currentPath:
|
||||
printer.unselect_file()
|
||||
|
||||
# delete it
|
||||
|
|
@ -723,8 +723,8 @@ def deleteGcodeFile(filename, target):
|
|||
return make_response("Trying to delete a folder that contains a file that is currently in use: %s" % filename, 409)
|
||||
|
||||
# deselect the file if it's currently selected
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and currentOrigin == target and fileManager.file_in_path(target, filename, currentFilename):
|
||||
currentOrigin, currentPath = _getCurrentFile()
|
||||
if currentPath is not None and currentOrigin == target and fileManager.file_in_path(target, filename, currentPath):
|
||||
printer.unselect_file()
|
||||
|
||||
# delete it
|
||||
|
|
@ -734,8 +734,8 @@ def deleteGcodeFile(filename, target):
|
|||
|
||||
def _getCurrentFile():
|
||||
currentJob = printer.get_current_job()
|
||||
if currentJob is not None and "file" in currentJob.keys() and "name" in currentJob["file"] and "origin" in currentJob["file"]:
|
||||
return currentJob["file"]["origin"], currentJob["file"]["name"]
|
||||
if currentJob is not None and "file" in currentJob.keys() and "path" in currentJob["file"] and "origin" in currentJob["file"]:
|
||||
return currentJob["file"]["origin"], currentJob["file"]["path"]
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ def setTimelapseConfig():
|
|||
except ValueError:
|
||||
return make_response("Invalid value for retraction Z-Hop: %r" % data["retractionZHop"])
|
||||
else:
|
||||
if retractionZHop > 0:
|
||||
if retractionZHop >= 0:
|
||||
config["options"]["retractionZHop"] = retractionZHop
|
||||
else:
|
||||
return make_response("Invalid value for retraction Z-Hop: %d" % retractionZHop)
|
||||
|
|
|
|||
|
|
@ -154,12 +154,12 @@ class PrinterStateConnection(sockjs.tornado.SockJSConnection, octoprint.printer.
|
|||
messages = self._messageBacklog
|
||||
self._messageBacklog = []
|
||||
|
||||
busy_files = [dict(origin=v[0], name=v[1]) for v in self._fileManager.get_busy_files()]
|
||||
busy_files = [dict(origin=v[0], path=v[1]) for v in self._fileManager.get_busy_files()]
|
||||
if "job" in data and data["job"] is not None \
|
||||
and "file" in data["job"] and "name" in data["job"]["file"] and "origin" in data["job"]["file"] \
|
||||
and data["job"]["file"]["name"] is not None and data["job"]["file"]["origin"] is not None \
|
||||
and "file" in data["job"] and "path" in data["job"]["file"] and "origin" in data["job"]["file"] \
|
||||
and data["job"]["file"]["path"] is not None and data["job"]["file"]["origin"] is not None \
|
||||
and (self._printer.is_printing() or self._printer.is_paused()):
|
||||
busy_files.append(dict(origin=data["job"]["file"]["origin"], name=data["job"]["file"]["name"]))
|
||||
busy_files.append(dict(origin=data["job"]["file"]["origin"], path=data["job"]["file"]["path"]))
|
||||
|
||||
data.update({
|
||||
"serverTime": time.time(),
|
||||
|
|
|
|||
|
|
@ -708,11 +708,12 @@ $(function() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (entry["type"] == "folder" && entry["children"]) {
|
||||
var success = entry["name"].toLocaleLowerCase().indexOf(query) > -1;
|
||||
if (!success && entry["type"] == "folder" && entry["children"]) {
|
||||
return _.any(entry["children"], recursiveSearch);
|
||||
} else {
|
||||
return entry["name"].toLocaleLowerCase().indexOf(query) > -1;
|
||||
}
|
||||
|
||||
return success;
|
||||
};
|
||||
|
||||
self.listHelper.changeSearchFunction(recursiveSearch);
|
||||
|
|
|
|||
|
|
@ -256,8 +256,8 @@ $(function() {
|
|||
self._processBusyFiles = function(data) {
|
||||
var busyFiles = [];
|
||||
_.each(data, function(entry) {
|
||||
if (entry.hasOwnProperty("name") && entry.hasOwnProperty("origin")) {
|
||||
busyFiles.push(entry.origin + ":" + entry.name);
|
||||
if (entry.hasOwnProperty("path") && entry.hasOwnProperty("origin")) {
|
||||
busyFiles.push(entry.origin + ":" + entry.path);
|
||||
}
|
||||
});
|
||||
self.busyFiles(busyFiles);
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ class gcode(object):
|
|||
if ';' in line:
|
||||
comment = line[line.find(';')+1:].strip()
|
||||
if comment.startswith("filament_diameter"):
|
||||
# Slic3r
|
||||
filamentValue = comment.split("=", 1)[1].strip()
|
||||
try:
|
||||
self._filamentDiameter = float(filamentValue)
|
||||
|
|
@ -269,6 +270,7 @@ class gcode(object):
|
|||
except ValueError:
|
||||
self._filamentDiameter = 0.0
|
||||
elif comment.startswith("CURA_PROFILE_STRING") or comment.startswith("CURA_OCTO_PROFILE_STRING"):
|
||||
# Cura 15.04.* & OctoPrint Cura plugin
|
||||
if comment.startswith("CURA_PROFILE_STRING"):
|
||||
prefix = "CURA_PROFILE_STRING:"
|
||||
else:
|
||||
|
|
@ -280,6 +282,13 @@ class gcode(object):
|
|||
self._filamentDiameter = float(curaOptions["filament_diameter"])
|
||||
except:
|
||||
self._filamentDiameter = 0.0
|
||||
elif comment.startswith("filamentDiameter,"):
|
||||
# Simplify3D
|
||||
filamentValue = comment.split(",", 1)[1].strip()
|
||||
try:
|
||||
self._filamentDiameter = float(filamentValue)
|
||||
except ValueError:
|
||||
self._filamentDiameter = 0.0
|
||||
line = line[0:line.find(';')]
|
||||
|
||||
G = getCodeInt(line, 'G')
|
||||
|
|
@ -294,15 +303,28 @@ class gcode(object):
|
|||
e = getCodeFloat(line, 'E')
|
||||
f = getCodeFloat(line, 'F')
|
||||
|
||||
if x is not None or y is not None or z is not None:
|
||||
# this is a move
|
||||
move = True
|
||||
else:
|
||||
# print head stays on position
|
||||
move = False
|
||||
|
||||
oldPos = pos
|
||||
newPos = Vector3D(x if x is not None else pos.x,
|
||||
y if y is not None else pos.y,
|
||||
z if z is not None else pos.z)
|
||||
|
||||
# Use new coordinates if provided. If not provided, use prior coordinates in absolute
|
||||
# and 0.0 in relative mode.
|
||||
newPos = Vector3D(x if x is not None else (pos.x if posAbs else 0.0),
|
||||
y if y is not None else (pos.y if posAbs else 0.0),
|
||||
z if z is not None else (pos.z if posAbs else 0.0))
|
||||
|
||||
if posAbs:
|
||||
# Absolute mode: scale coordinates and apply offsets
|
||||
pos = newPos * scale + posOffset
|
||||
else:
|
||||
# Relative mode: scale and add to current position
|
||||
pos += newPos * scale
|
||||
|
||||
if f is not None and f != 0:
|
||||
feedrate = f
|
||||
|
||||
|
|
@ -310,10 +332,12 @@ class gcode(object):
|
|||
if absoluteE:
|
||||
# make sure e is relative
|
||||
e -= currentE[currentExtruder]
|
||||
# If move includes extrusion, calculate new min/max coordinates of model
|
||||
if e > 0.0:
|
||||
# extrusion -> relevant for print area & dimensions
|
||||
|
||||
# If move with extrusion, calculate new min/max coordinates of model
|
||||
if e > 0.0 and move:
|
||||
# extrusion and move -> relevant for print area & dimensions
|
||||
self._minMax.record(pos)
|
||||
|
||||
totalExtrusion[currentExtruder] += e
|
||||
currentE[currentExtruder] += e
|
||||
maxExtrusion[currentExtruder] = max(maxExtrusion[currentExtruder],
|
||||
|
|
@ -417,7 +441,6 @@ class gcode(object):
|
|||
|
||||
if throttle is not None:
|
||||
throttle()
|
||||
|
||||
if self.progressCallback is not None:
|
||||
self.progressCallback(100.0)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue