diff --git a/src/octoprint/plugins/cura/profile.py b/src/octoprint/plugins/cura/profile.py index 6587c527..a63ff9cb 100644 --- a/src/octoprint/plugins/cura/profile.py +++ b/src/octoprint/plugins/cura/profile.py @@ -531,7 +531,7 @@ class Profile(object): elif key == "machine_height": return self._printer_profile["volume"]["height"] elif key == "machine_center_is_zero": - return self._printer_profile["volume"]["formFactor"] == "circular" + return self._printer_profile["volume"]["formFactor"] == "circular" or self._printer_profile["volume"]["origin"] == "center" else: return None diff --git a/src/octoprint/printer/profile.py b/src/octoprint/printer/profile.py index 547e81df..0b3f6834 100644 --- a/src/octoprint/printer/profile.py +++ b/src/octoprint/printer/profile.py @@ -31,6 +31,14 @@ class BedTypes(object): def values(cls): return [getattr(cls, name) for name in cls.__dict__ if not name.startswith("__")] +class BedOrigin(object): + LOWERLEFT = "lowerleft" + CENTER = "center" + + @classmethod + def values(cls): + return [getattr(cls, name) for name in cls.__dict__ if not name.startswith("__")] + class PrinterProfileManager(object): """ Manager for printer profiles. Offers methods to select the globally used printer profile and to list, add, remove, @@ -72,6 +80,10 @@ class PrinterProfileManager(object): * - ``volume.formFactor`` - ``string`` - Form factor of the print bed, either ``rectangular`` or ``circular`` + - ``volume.origin`` + - ``string`` + - Location of gcode origin in the print volume, either ``lowerleft`` + - or ``center`` * - ``heatedBed`` - ``bool`` - Whether the printer has a heated bed (``True``) or not (``False``) @@ -138,6 +150,7 @@ class PrinterProfileManager(object): depth = 200, height = 200, formFactor = BedTypes.RECTANGULAR, + origin = BedOrigin.LOWERLEFT ), heatedBed = False, extruder=dict( diff --git a/src/octoprint/static/gcodeviewer/js/renderer.js b/src/octoprint/static/gcodeviewer/js/renderer.js index 79abfff8..15b44eca 100644 --- a/src/octoprint/static/gcodeviewer/js/renderer.js +++ b/src/octoprint/static/gcodeviewer/js/renderer.js @@ -266,6 +266,11 @@ GCODE.renderer = (function(){ y: -1 * renderOptions["bed"]["y"] * zoomFactor }; + if (renderOptions["bed"]["centeredOrigin"]) { + origin.x -= width / 2; + origin.y += height / 2; + } + ctx.beginPath(); ctx.strokeStyle = renderOptions["colorGrid"]; ctx.fillStyle = "#ffffff"; @@ -281,15 +286,15 @@ GCODE.renderer = (function(){ ctx.beginPath(); for (i = 0; i <= renderOptions["bed"]["x"]; i += gridStep) { - ctx.moveTo(i * zoomFactor, 0); - ctx.lineTo(i * zoomFactor, -1 * renderOptions["bed"]["y"] * zoomFactor); + ctx.moveTo(origin.x + i * zoomFactor, origin.y); + ctx.lineTo(origin.x + i * zoomFactor, origin.y + height); } ctx.stroke(); ctx.beginPath(); for (i = 0; i <= renderOptions["bed"]["y"]; i += gridStep) { - ctx.moveTo(0, -1 * i * zoomFactor); - ctx.lineTo(renderOptions["bed"]["x"] * zoomFactor, -1 * i * zoomFactor); + ctx.moveTo(origin.x, origin.y + i * zoomFactor); + ctx.lineTo(origin.x + width, origin.y + i * zoomFactor); } ctx.stroke(); }; @@ -496,7 +501,7 @@ GCODE.renderer = (function(){ offsetModelY = -1 * (renderOptions["bed"]["y"] / 2 - (mdlInfo.min.y + mdlInfo.modelSize.y / 2)) * zoomFactor; offsetBedX = -1 * (renderOptions["bed"]["x"] / 2 - (mdlInfo.min.x + mdlInfo.modelSize.x / 2)) * zoomFactor; offsetBedY = (renderOptions["bed"]["y"] / 2 - (mdlInfo.min.y + mdlInfo.modelSize.y / 2)) * zoomFactor; - } else if (renderOptions["bed"]["circular"]) { + } else if (renderOptions["bed"]["circular"] || renderOptions["bed"]["centeredOrigin"]) { canvasCenter = ctx.transformedPoint(canvas.width / 2, canvas.height / 2); offsetModelX = canvasCenter.x; offsetModelY = canvasCenter.y; diff --git a/src/octoprint/static/js/app/viewmodels/gcode.js b/src/octoprint/static/js/app/viewmodels/gcode.js index e44096c7..aa3af46b 100644 --- a/src/octoprint/static/js/app/viewmodels/gcode.js +++ b/src/octoprint/static/js/app/viewmodels/gcode.js @@ -137,22 +137,27 @@ $(function() { } if (currentProfileData && currentProfileData.volume && currentProfileData.volume.formFactor() && currentProfileData.volume.width() && currentProfileData.volume.depth()) { - var x = undefined, y = undefined, r = undefined, circular = false; + var x = undefined, y = undefined, r = undefined, circular = false, centeredOrigin = false; var formFactor = currentProfileData.volume.formFactor(); if (formFactor == "circular") { r = currentProfileData.volume.width() / 2; circular = true; + centeredOrigin = true; } else { x = currentProfileData.volume.width(); y = currentProfileData.volume.depth(); + if (currentProfileData.volume.origin) { + centeredOrigin = currentProfileData.volume.origin() == "center"; + } } return { x: x, y: y, r: r, - circular: circular + circular: circular, + centeredOrigin: centeredOrigin }; } else { return undefined; @@ -507,4 +512,4 @@ $(function() { ["loginStateViewModel", "settingsViewModel"], "#gcode" ]); -}); \ No newline at end of file +}); diff --git a/src/octoprint/static/js/app/viewmodels/printerprofiles.js b/src/octoprint/static/js/app/viewmodels/printerprofiles.js index 516c207b..109c0791 100644 --- a/src/octoprint/static/js/app/viewmodels/printerprofiles.js +++ b/src/octoprint/static/js/app/viewmodels/printerprofiles.js @@ -12,7 +12,8 @@ $(function() { formFactor: "rectangular", width: 200, depth: 200, - height: 200 + height: 200, + origin: "lowerleft" }, heatedBed: false, axes: { @@ -66,6 +67,7 @@ $(function() { self.editorVolumeDepth = ko.observable(); self.editorVolumeHeight = ko.observable(); self.editorVolumeFormFactor = ko.observable(); + self.editorVolumeOrigin = ko.observable(); self.editorHeatedBed = ko.observable(); @@ -93,6 +95,11 @@ $(function() { {key: "black", name: gettext("black")} ]); + self.availableOrigins = ko.observable([ + {key: "lowerleft", name: gettext("Lower Left")}, + {key: "center", name: gettext("Centered")} + ]); + self.koEditorExtruderOffsets = ko.computed(function() { var extruderOffsets = self.editorExtruderOffsets(); var numExtruders = self.editorExtruders(); @@ -282,6 +289,7 @@ $(function() { self.editorVolumeDepth(data.volume.depth); self.editorVolumeHeight(data.volume.height); self.editorVolumeFormFactor(data.volume.formFactor); + self.editorVolumeOrigin(data.volume.origin); self.editorHeatedBed(data.heatedBed); @@ -346,7 +354,8 @@ $(function() { width: parseFloat(self.editorVolumeWidth()), depth: parseFloat(self.editorVolumeDepth()), height: parseFloat(self.editorVolumeHeight()), - formFactor: self.editorVolumeFormFactor() + formFactor: self.editorVolumeFormFactor(), + origin: self.editorVolumeOrigin() }, heatedBed: self.editorHeatedBed(), extruder: { diff --git a/src/octoprint/templates/dialogs/settings/printerprofiles.jinja2 b/src/octoprint/templates/dialogs/settings/printerprofiles.jinja2 index 821be236..d49ce3e2 100644 --- a/src/octoprint/templates/dialogs/settings/printerprofiles.jinja2 +++ b/src/octoprint/templates/dialogs/settings/printerprofiles.jinja2 @@ -76,6 +76,15 @@ +
+
+ +
+ +
+
+