diff --git a/src/octoprint/plugins/svgtogcode/__init__.py b/src/octoprint/plugins/svgtogcode/__init__.py index 4875f81c..adbaab48 100644 --- a/src/octoprint/plugins/svgtogcode/__init__.py +++ b/src/octoprint/plugins/svgtogcode/__init__.py @@ -246,6 +246,7 @@ class SvgToGcodePlugin(octoprint.plugin.SlicerPlugin, on_progress_kwargs = dict() self._svgtogcode_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) + print("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) engine_settings = self._convert_to_engine(profile_path) @@ -253,6 +254,7 @@ class SvgToGcodePlugin(octoprint.plugin.SlicerPlugin, homedir = expanduser("~") executable = homedir + "/mrbeam-inkscape-ext/mrbeam.py" log_path = homedir + "/.octoprint/logs/svgtogcode.log" + log_enabled = "true" # debugging stuff. TODO remove hostname = socket.gethostname() @@ -269,7 +271,7 @@ class SvgToGcodePlugin(octoprint.plugin.SlicerPlugin, args = ['python "%s"' % executable, '-f "%s"' % dest_file, '-d "%s"' % dest_dir] for k, v in engine_settings.items(): args += ['"%s=%s"' % (k, str(v))] - args += ['--create-log=false', '"--log-filename=%s"' % log_path,'"%s"' % model_path] + args += ['--create-log=%s' % log_enabled, '"--log-filename=%s"' % log_path,'"%s"' % model_path] #python ~/mrbeam-inkscape-ext/standalone.py -f output.gcode -d output/path --engraving-laser-speed=300 # --laser-intensity=1000 --create-log=false path/to/input.svg diff --git a/src/octoprint/plugins/svgtogcode/static/js/convert.js b/src/octoprint/plugins/svgtogcode/static/js/convert.js index 29092523..aefe1cdd 100644 --- a/src/octoprint/plugins/svgtogcode/static/js/convert.js +++ b/src/octoprint/plugins/svgtogcode/static/js/convert.js @@ -2,6 +2,7 @@ function VectorConversionViewModel(loginStateViewModel, settingsViewModel) { var self = this; self.loginState = loginStateViewModel; + self.settings = settingsViewModel; self.target = undefined; self.file = undefined; @@ -27,19 +28,34 @@ function VectorConversionViewModel(loginStateViewModel, settingsViewModel) { self.gcodeFilename(self.file.substr(0, self.file.lastIndexOf("."))); $("#dialog_vector_graphics_conversion").modal("show"); }; + + self.show2 = function() { + var tmpsvg = snap.select("#scaleGroup"); // get working area + var dim = self.settings.printer_bedDimensions(); + var w = dim.x * 90/25.4; // convert mm to pix with 90dpi (inkscape default - TODO use 72 for illustrator svg) + var h = dim.y * 90/25.4; + var s = Snap(w, h); // create new empty svg with working area dimensions + s.append(tmpsvg); // .. and fill it + self.svg = s.outerSVG(); + // TODO: js svg conversion + self.title(gettext("Converting")); + var gcodeFile = "tmp"+Date.now()+".gco"; // TODO: user should not deal with gcode anymore. go and laser it. + self.gcodeFilename(gcodeFile); + $("#dialog_vector_graphics_conversion").modal("show"); + }; self.slicer.subscribe(function(newValue) { self.profilesForSlicer(newValue); }); self.enableConvertButton = ko.computed(function() { - if (self.laserIntensity() == undefined || self.laserSpeed() == undefined || self.gcodeFilename() == undefined) { + if (self.laserIntensity() === undefined || self.laserSpeed() === undefined || self.gcodeFilename() === undefined) { return false; } else { var tmpIntensity = parseInt(self.laserIntensity().trim()); var tmpSpeed = parseInt(self.laserSpeed().trim()); var tmpGcodeFilename = self.gcodeFilename().trim(); - return tmpGcodeFilename != "" + return tmpGcodeFilename !== "" && tmpIntensity > 0 && tmpIntensity <= 1000 && tmpSpeed >= 30 && tmpSpeed <= 2000; } @@ -51,18 +67,17 @@ function VectorConversionViewModel(loginStateViewModel, settingsViewModel) { type: "GET", dataType: "json", success: self.fromResponse - }) + }); }; self.fromResponse = function(data) { - console.log("convert.js", data); self.data = data; var selectedSlicer = undefined; self.slicers.removeAll(); _.each(_.values(data), function(slicer) { var name = slicer.displayName; - if (name == undefined) { + if (name === undefined) { name = slicer.key; } @@ -126,15 +141,19 @@ function VectorConversionViewModel(loginStateViewModel, settingsViewModel) { } var data = { - command: "slice", + command: "convert", "profile.speed": self.laserSpeed(), "profile.intensity": self.laserIntensity(), slicer: "svgtogcode", gcode: gcodeFilename }; + if(self.svg !== undefined){ + data.svg = self.svg; + } + $.ajax({ - url: API_BASEURL + "files/" + self.target + "/" + self.file, + url: API_BASEURL + "files/convert", type: "POST", dataType: "json", contentType: "application/json; charset=UTF-8", diff --git a/src/octoprint/plugins/svgtogcode/static/js/working_area.js b/src/octoprint/plugins/svgtogcode/static/js/working_area.js index 02b7d5d0..ac3baa2f 100644 --- a/src/octoprint/plugins/svgtogcode/static/js/working_area.js +++ b/src/octoprint/plugins/svgtogcode/static/js/working_area.js @@ -109,11 +109,19 @@ function WorkingAreaViewModel(loginStateViewModel, settingsViewModel, printerSta //self.getDivDimensions(); // init self.placeSVG = function(url){ - console.log("workingarea", url); Snap.load(url, function (f) { + var namespaces = {}; + var root = f.select('svg').node.attributes; + for(var i = 0; i < root.length; i++){ + var attr = root[i]; + if(attr.name.indexOf("xmlns") === 0){ + namespaces[attr.name] = attr.value; + } + } + var newSvg = f.select("g"); + newSvg.attr(namespaces); var id = self.generateId(url); - newSvg.attr("id", id); snap.select("#scaleGroup").append(newSvg); newSvg.drag();// Making croc draggable. Go ahead drag it around! diff --git a/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 b/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 index 65b19ceb..469cd433 100644 --- a/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 +++ b/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 @@ -212,12 +212,19 @@ var UI_API_KEY = "{{ uiApiKey }}";
- @@ -360,8 +367,8 @@ var UI_API_KEY = "{{ uiApiKey }}"; diff --git a/src/octoprint/server/api/files.py b/src/octoprint/server/api/files.py index cc01dba7..c1d50161 100644 --- a/src/octoprint/server/api/files.py +++ b/src/octoprint/server/api/files.py @@ -359,6 +359,106 @@ def gcodeFileCommand(filename, target): return NO_CONTENT +@api.route("/files/convert", methods=["POST"]) +@restricted_access +def gcodeConvertCommand(): + target = FileDestinations.LOCAL; + + #if not _verifyFileExists(target, filename): + # return make_response("File not found on '%s': %s" % (target, filename), 404) + + # valid file commands, dict mapping command name to mandatory parameters + valid_commands = { + "convert": [] + } + command, data, response = util.getJsonCommandFromRequest(request, valid_commands) + if response is not None: + return response + + import re + svg = data['svg'] + #svg = re.sub(r"inkscape:[a-zA-Z_-]+=\".*?\" ", "", svg) + #svg = re.sub(r"sodipodi:[a-zA-Z_-]+=\".*?\" ", "", svg) + del data['svg'] + + + if command == "convert": + print("files.py convert", data) + + import os + name, _ = os.path.splitext(data['gcode']) + + filename = target + "/" + name + ".svg" + class Wrapper(object): + def __init__(self, filename, content): + self.filename = filename + self.content = content + + def save(self, absolute_dest_path): + with open(absolute_dest_path, "w") as d: + d.write(self.content) + d.close() + + fileObj = Wrapper(filename, svg) + fileManager.add_file(target, filename, fileObj, links=None, allow_overwrite=True) + #fh = open(filename, 'w') + #fh.write(svg) + #fh.close() + + slicer = "svgtogcode"; + if "slicer" in data.keys() and data["slicer"]: + slicer = data["slicer"] + del data["slicer"] + slicer_instance = slicingManager.get_slicer(slicer) + if slicer_instance.get_slicer_properties()["same_device"] and (printer.isPrinting() or printer.isPaused()): + # slicer runs on same device as OctoPrint, slicing while printing is hence disabled + return make_response("Cannot convert while lasering due to performance reasons".format(**locals()), 409) + + if "gcode" in data.keys() and data["gcode"]: + gcode_name = data["gcode"] + del data["gcode"] + else: + import os + name, _ = os.path.splitext(filename) + gcode_name = name + ".gco" + + # prohibit overwriting the file that is currently being printed + currentOrigin, currentFilename = _getCurrentFile() + if currentFilename == gcode_name and currentOrigin == target and (printer.isPrinting() or printer.isPaused()): + make_response("Trying to slice into file that is currently being printed: %s" % gcode_name, 409) + + if "profile" in data.keys() and data["profile"]: + profile = data["profile"] + del data["profile"] + else: + profile = None + + override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None] + overrides = dict() + for key in override_keys: + overrides[key[len("profile."):]] = data[key] + + ok, result = fileManager.slice(slicer, target, filename, target, gcode_name, profile=profile, overrides=overrides) + if ok: + files = {} + location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True) + result = { + "name": gcode_name, + "origin": FileDestinations.LOCAL, + "refs": { + "resource": location, + "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + gcode_name + } + } + + r = make_response(jsonify(result), 202) + r.headers["Location"] = location + return r + else: + return make_response("Could not slice: {result}".format(result=result), 500) + + return NO_CONTENT + @api.route("/files/