diff --git a/src/octoprint/plugins/cura/__init__.py b/src/octoprint/plugins/cura/__init__.py deleted file mode 100644 index 9cebe18e..00000000 --- a/src/octoprint/plugins/cura/__init__.py +++ /dev/null @@ -1,407 +0,0 @@ -# coding=utf-8 -from __future__ import absolute_import - -__author__ = "Gina Häußge " -__license__ = "GNU Affero General Public License http://www.gnu.org/licenses/agpl.html" -__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License" - -import logging -import logging.handlers -import os -import flask - -import octoprint.plugin -import octoprint.util -import octoprint.slicing -import octoprint.settings - -default_settings = { - "cura_engine": None, - "default_profile": None, - "debug_logging": False -} -s = octoprint.plugin.plugin_settings("cura", defaults=default_settings) - -from .profile import Profile - -blueprint = flask.Blueprint("plugin.cura", __name__) - -@blueprint.route("/import", methods=["POST"]) -def importCuraProfile(): - import datetime - import tempfile - - from octoprint.server import slicingManager - - input_name = "file" - input_upload_name = input_name + "." + s.globalGet(["server", "uploads", "nameSuffix"]) - input_upload_path = input_name + "." + s.globalGet(["server", "uploads", "pathSuffix"]) - - if input_upload_name in flask.request.values and input_upload_path in flask.request.values: - filename = flask.request.values[input_upload_name] - try: - profile_dict = Profile.from_cura_ini(flask.request.values[input_upload_path]) - except Exception as e: - return flask.make_response("Something went wrong while converting imported profile: {message}".format(e.message), 500) - - elif input_name in flask.request.files: - temp_file = tempfile.NamedTemporaryFile("wb", delete=False) - try: - temp_file.close() - upload = flask.request.files[input_name] - upload.save(temp_file.name) - profile_dict = Profile.from_cura_ini(temp_file.name) - except Exception as e: - return flask.make_response("Something went wrong while converting imported profile: {message}".format(e.message), 500) - finally: - os.remove(temp_file) - - filename = upload.filename - - else: - return flask.make_response("No file included", 400) - - if profile_dict is None: - return flask.make_response("Could not convert Cura profile", 400) - - name, _ = os.path.splitext(filename) - - # default values for name, display name and description - profile_name = _sanitize_name(name) - profile_display_name = name - profile_description = "Imported from {filename} on {date}".format(filename=filename, date=octoprint.util.getFormattedDateTime(datetime.datetime.now())) - profile_allow_overwrite = False - - # overrides - if "name" in flask.request.values: - profile_name = flask.request.values["name"] - if "displayName" in flask.request.values: - profile_display_name = flask.request.values["displayName"] - if "description" in flask.request.values: - profile_description = flask.request.values["description"] - if "allowOverwrite" in flask.request.values: - from octoprint.server.api import valid_boolean_trues - profile_allow_overwrite = flask.request.values["allowOverwrite"] in valid_boolean_trues - - slicingManager.save_profile("cura", - profile_name, - profile_dict, - allow_overwrite=profile_allow_overwrite, - display_name=profile_display_name, - description=profile_description) - - result = dict( - resource=flask.url_for("api.slicingGetSlicerProfile", slicer="cura", name=profile_name, _external=True), - displayName=profile_display_name, - description=profile_description - ) - r = flask.make_response(flask.jsonify(result), 201) - r.headers["Location"] = result["resource"] - return r - - -class CuraPlugin(octoprint.plugin.SlicerPlugin, - octoprint.plugin.SettingsPlugin, - octoprint.plugin.TemplatePlugin, - octoprint.plugin.AssetPlugin, - octoprint.plugin.BlueprintPlugin, - octoprint.plugin.StartupPlugin): - - def __init__(self): - self._logger = logging.getLogger("octoprint.plugins.cura") - self._cura_logger = logging.getLogger("octoprint.plugins.cura.engine") - - # setup job tracking across threads - import threading - self._slicing_commands = dict() - self._slicing_commands_mutex = threading.Lock() - self._cancelled_jobs = [] - self._cancelled_jobs_mutex = threading.Lock() - - ##~~ StartupPlugin API - - def on_startup(self, host, port): - # setup our custom logger - cura_logging_handler = logging.handlers.RotatingFileHandler(s.getPluginLogfilePath(postfix="engine"), maxBytes=2*1024*1024) - cura_logging_handler.setFormatter(logging.Formatter("%(asctime)s %(message)s")) - cura_logging_handler.setLevel(logging.DEBUG) - - self._cura_logger.addHandler(cura_logging_handler) - self._cura_logger.setLevel(logging.DEBUG if s.getBoolean(["debug_logging"]) else logging.CRITICAL) - self._cura_logger.propagate = False - - ##~~ BlueprintPlugin API - - def get_blueprint(self): - global blueprint - return blueprint - - ##~~ AssetPlugin API - - def get_asset_folder(self): - import os - return os.path.join(os.path.dirname(os.path.realpath(__file__)), "static") - - def get_assets(self): - return { - "js": ["js/cura.js"], - "less": ["less/cura.less"], - "css": ["css/cura.css"] - } - - ##~~ SettingsPlugin API - - def on_settings_load(self): - return dict( - cura_engine=s.get(["cura_engine"]), - default_profile=s.get(["default_profile"]), - debug_logging=s.getBoolean(["debug_logging"]) - ) - - def on_settings_save(self, data): - if "cura_engine" in data and data["cura_engine"]: - s.set(["cura_engine"], data["cura_engine"]) - if "default_profile" in data and data["default_profile"]: - s.set(["default_profile"], data["default_profile"]) - if "debug_logging" in data: - old_debug_logging = s.getBoolean(["debug_logging"]) - new_debug_logging = data["debug_logging"] in octoprint.settings.valid_boolean_trues - if old_debug_logging != new_debug_logging: - if new_debug_logging: - self._cura_logger.setLevel(logging.DEBUG) - else: - self._cura_logger.setLevel(logging.CRITICAL) - s.setBoolean(["debug_logging"], new_debug_logging) - - ##~~ TemplatePlugin API - - def get_template_vars(self): - return dict( - _settings_menu_entry="Cura" - ) - - def get_template_folder(self): - import os - return os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates") - - ##~~ SlicerPlugin API - - def is_slicer_configured(self): - cura_engine = s.get(["cura_engine"]) - return cura_engine is not None and os.path.exists(cura_engine) - - def get_slicer_properties(self): - return dict( - type="cura", - name="CuraEngine", - same_device=True, - progress_report=True - ) - - def get_slicer_default_profile(self): - path = s.get(["default_profile"]) - if not path: - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "profiles", "default.profile.yaml") - return self.get_slicer_profile(path) - - def get_slicer_profile(self, path): - profile_dict = self._load_profile(path) - - display_name = None - description = None - if "_display_name" in profile_dict: - display_name = profile_dict["_display_name"] - del profile_dict["_display_name"] - if "_description" in profile_dict: - description = profile_dict["_description"] - del profile_dict["_description"] - - properties = self.get_slicer_properties() - return octoprint.slicing.SlicingProfile(properties["type"], "unknown", profile_dict, display_name=display_name, description=description) - - def save_slicer_profile(self, path, profile, allow_overwrite=True, overrides=None): - new_profile = Profile.merge_profile(profile.data, overrides=overrides) - - if profile.display_name is not None: - new_profile["_display_name"] = profile.display_name - if profile.description is not None: - new_profile["_description"] = profile.description - - self._save_profile(path, new_profile, allow_overwrite=allow_overwrite) - - def do_slice(self, model_path, machinecode_path=None, profile_path=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None): - if not profile_path: - profile_path = s.get(["default_profile"]) - if not machinecode_path: - path, _ = os.path.splitext(model_path) - machinecode_path = path + ".gco" - - if on_progress: - if not on_progress_args: - on_progress_args = () - if not on_progress_kwargs: - on_progress_kwargs = dict() - - self._cura_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) - - engine_settings = self._convert_to_engine(profile_path) - - executable = s.get(["cura_engine"]) - if not executable: - return False, "Path to CuraEngine is not configured " - - working_dir, _ = os.path.split(executable) - args = ['"%s"' % executable, '-v', '-p'] - for k, v in engine_settings.items(): - args += ["-s", '"%s=%s"' % (k, str(v))] - args += ['-o', '"%s"' % machinecode_path, '"%s"' % model_path] - - import sarge - command = " ".join(args) - self._logger.info("Running %r in %s" % (command, working_dir)) - try: - p = sarge.run(command, cwd=working_dir, async=True, stdout=sarge.Capture(), stderr=sarge.Capture()) - try: - with self._slicing_commands_mutex: - self._slicing_commands[machinecode_path] = p.commands[0] - - line_seen = False - layer_count = None - step_factor = dict( - inset=0, - skin=1, - export=2 - ) - while p.returncode is None: - line = p.stderr.readline(timeout=0.5) - if not line: - if line_seen: - break - else: - continue - - line_seen = True - self._cura_logger.debug(line.strip()) - - if on_progress is not None: - # The Cura slicing process has three individual steps, each consisting of substeps: - # - # - inset - # - skin - # - export - # - # So each layer will be processed three times, once for each step, resulting in a total amount of - # substeps of 3 * . - # - # The CuraEngine reports the calculated layer count and the continuous progress on stderr. - # The layer count gets reported right at the beginning in a line of the format: - # - # Layer count: - # - # The individual progress per each of the three steps gets reported on stderr in a line of - # the format: - # - # Progress::: - # - # Thus, for determining the overall progress the following formula applies: - # - # progress = * + / * 3 - # - # with being 0 for "inset", 1 for "skin" and 2 for "export". - - if line.startswith("Layer count:") and layer_count is None: - try: - layer_count = float(line[len("Layer count:"):].strip()) - except: - pass - - elif line.startswith("Progress:"): - split_line = line[len("Progress:"):].strip().split(":") - if len(split_line) == 3: - step, current_layer, _ = split_line - try: - current_layer = float(current_layer) - except: - pass - else: - if not step in step_factor: - continue - on_progress_kwargs["_progress"] = (step_factor[step] * layer_count + current_layer) / (layer_count * 3) - on_progress(*on_progress_args, **on_progress_kwargs) - finally: - p.close() - - with self._cancelled_jobs_mutex: - if machinecode_path in self._cancelled_jobs: - self._cura_logger.info("### Cancelled") - raise octoprint.slicing.SlicingCancelled() - - self._cura_logger.info("### Finished, returncode %d" % p.returncode) - if p.returncode == 0: - return True, None - else: - self._logger.warn("Could not slice via Cura, got return code %r" % p.returncode) - return False, "Got returncode %r" % p.returncode - - except octoprint.slicing.SlicingCancelled as e: - raise e - except: - self._logger.exception("Could not slice via Cura, got an unknown error") - return False, "Unknown error, please consult the log file" - - finally: - with self._cancelled_jobs_mutex: - if machinecode_path in self._cancelled_jobs: - self._cancelled_jobs.remove(machinecode_path) - with self._slicing_commands_mutex: - if machinecode_path in self._slicing_commands: - del self._slicing_commands[machinecode_path] - - self._cura_logger.info("-" * 40) - - def cancel_slicing(self, machinecode_path): - with self._slicing_commands_mutex: - if machinecode_path in self._slicing_commands: - with self._cancelled_jobs_mutex: - self._cancelled_jobs.append(machinecode_path) - self._slicing_commands[machinecode_path].terminate() - self._logger.info("Cancelled slicing of %s" % machinecode_path) - - def _load_profile(self, path): - import yaml - profile_dict = dict() - with open(path, "r") as f: - try: - profile_dict = yaml.safe_load(f) - except: - raise IOError("Couldn't read profile from {path}".format(path=path)) - return profile_dict - - def _save_profile(self, path, profile, allow_overwrite=True): - if not allow_overwrite and os.path.exists(path): - raise IOError("Cannot overwrite {path}".format(path=path)) - - import yaml - with open(path, "wb") as f: - yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True) - - def _convert_to_engine(self, profile_path): - profile = Profile(self._load_profile(profile_path)) - return profile.convert_to_engine() - -def _sanitize_name(name): - if name is None: - return None - - if "/" in name or "\\" in name: - raise ValueError("name must not contain / or \\") - - import string - valid_chars = "-_.() {ascii}{digits}".format(ascii=string.ascii_letters, digits=string.digits) - sanitized_name = ''.join(c for c in name if c in valid_chars) - sanitized_name = sanitized_name.replace(" ", "_") - return sanitized_name.lower() - -__plugin_name__ = "cura" -__plugin_version__ = "0.1" -__plugin_implementations__ = [CuraPlugin()] \ No newline at end of file diff --git a/src/octoprint/plugins/cura/profile.py b/src/octoprint/plugins/cura/profile.py deleted file mode 100644 index 04b42c53..00000000 --- a/src/octoprint/plugins/cura/profile.py +++ /dev/null @@ -1,956 +0,0 @@ -# coding=utf-8 -from __future__ import absolute_import - -__author__ = "Gina Häußge " -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' -__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License" - - -from . import s - -import re - -class SupportLocationTypes(object): - NONE = "none" - TOUCHING_BUILDPLATE = "buildplate" - EVERYWHERE = "everywhere" - -class SupportDualTypes(object): - BOTH = "both" - FIRST = "first" - SECOND = "second" - -class SupportTypes(object): - GRID = "grid" - LINES = "lines" - -class PlatformAdhesionTypes(object): - NONE = "none" - BRIM = "brim" - RAFT = "raft" - -class MachineShapeTypes(object): - SQUARE = "square" - CIRCULAR = "circular" - -class GcodeFlavors(object): - REPRAP = "reprap" - REPRAP_VOLUME = "reprap_volume" - ULTIGCODE = "ultigcode" - MAKERBOT = "makerbot" - BFB = "bfb" - MACH3 = "mach3" - - -defaults = dict( - layer_height=0.1, - wall_thickness=0.8, - solid_layer_thickness=0.6, - nozzle_size=0.4, - print_temperature=[220, 0, 0, 0], - print_bed_temperature=70, - platform_adhesion=PlatformAdhesionTypes.NONE, - filament_diameter=[2.85, 0, 0, 0], - filament_flow=100.0, - bottom_thickness=0.3, - first_layer_width_factor=100.0, - object_sink=0.0, - - fill_density=20, - solid_top=True, - solid_bottom=True, - fill_overlap=15, - - # speeds - print_speed=50.0, - travel_speed=150.0, - bottom_layer_speed=20.0, - infill_speed=0.0, - outer_shell_speed=0.0, - inner_shell_speed=0.0, - - # dual extrusion - overlap_dual=0.15, - wipe_tower=False, - wipe_tower_volume=15, - ooze_shield=False, - - # retraction - retraction_enable=True, - retraction_speed=40.0, - retraction_amount=4.5, - retraction_dual_amount=16.5, - retraction_min_travel=1.5, - retraction_combing=True, - retraction_minimal_extrusion=0.02, - retraction_hop=0.0, - - # cooling - cool_min_layer_time=5, - fan_enabled=True, - fan_full_height=0.5, - fan_speed=100, - fan_speed_max=100, - cool_min_feedrate=10, - cool_head_lift=False, - - # support - support=SupportLocationTypes.NONE, - support_type=SupportTypes.GRID, - support_angle=60.0, - support_fill_rate=15, - support_xy_distance=0.7, - support_z_distance=0.15, - support_dual_extrusion=SupportDualTypes.BOTH, - - # platform adhesion - skirt_line_count=1, - skirt_gap=3.0, - skirt_minimal_length=150.0, - brim_line_count=20, - raft_margin=5.0, - raft_line_spacing=3.0, - raft_base_thickness=0.3, - raft_base_linewidth=1.0, - raft_interface_thickness=0.27, - raft_interface_linewidth=0.4, - raft_airgap=0.22, - raft_surface_layers=2, - - # repairing - fix_horrible_union_all_type_a=True, - fix_horrible_union_all_type_b=False, - fix_horrible_use_open_bits=False, - fix_horrible_extensive_stitching=False, - - # extras - spiralize=False, - follow_surface=False, - - machine_width=205, - machine_depth=205, - machine_center_is_zero=False, - has_heated_bed=False, - gcode_flavor=GcodeFlavors.REPRAP, - extruder_amount=1, - steps_per_e=0, - start_gcode=[ - # 1 extruder - """;Sliced at: {day} {date} {time} -;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} -;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line -;M109 S{print_temperature} ;Uncomment to add your own temperature line -G21 ;metric values -G90 ;absolute positioning -M82 ;set extruder to absolute mode -M107 ;start with the fan off - -G28 X0 Y0 ;move X/Y to min endstops -G28 Z0 ;move Z to min endstops - -G1 Z15.0 F{travel_speed} ;move the platform down 15mm - -G92 E0 ;zero the extruded length -G1 F200 E3 ;extrude 3mm of feed stock -G92 E0 ;zero the extruded length again -G1 F{travel_speed} -;Put printing message on LCD screen -M117 Printing... -""", - # 2 extruders - """;Sliced at: {day} {date} {time} -;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} -;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line -;M104 S{print_temperature} ;Uncomment to add your own temperature line -;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line -;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line -G21 ;metric values -G90 ;absolute positioning -M107 ;start with the fan off - -G28 X0 Y0 ;move X/Y to min endstops -G28 Z0 ;move Z to min endstops - -G1 Z15.0 F{travel_speed} ;move the platform down 15mm - -T1 ;Switch to the 2nd extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T0 ;Switch to the first extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F{travel_speed} -;Put printing message on LCD screen -M117 Printing... -""", - # 3 extruders - """;Sliced at: {day} {date} {time} -;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} -;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line -;M104 S{print_temperature} ;Uncomment to add your own temperature line -;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line -;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line -G21 ;metric values -G90 ;absolute positioning -M107 ;start with the fan off - -G28 X0 Y0 ;move X/Y to min endstops -G28 Z0 ;move Z to min endstops - -G1 Z15.0 F{travel_speed} ;move the platform down 15mm - -T2 ;Switch to the 2nd extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T1 ;Switch to the 2nd extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T0 ;Switch to the first extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F{travel_speed} -;Put printing message on LCD screen -M117 Printing... -""", - # 4 extruders - """;Sliced at: {day} {date} {time} -;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} -;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line -;M104 S{print_temperature} ;Uncomment to add your own temperature line -;M109 T2 S{print_temperature2} ;Uncomment to add your own temperature line -;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line -;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line -G21 ;metric values -G90 ;absolute positioning -M107 ;start with the fan off - -G28 X0 Y0 ;move X/Y to min endstops -G28 Z0 ;move Z to min endstops - -G1 Z15.0 F{travel_speed} ;move the platform down 15mm - -T3 ;Switch to the 4th extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T2 ;Switch to the 3th extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T1 ;Switch to the 2nd extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F200 E-{retraction_dual_amount} - -T0 ;Switch to the first extruder -G92 E0 ;zero the extruded length -G1 F200 E10 ;extrude 10mm of feed stock -G92 E0 ;zero the extruded length again -G1 F{travel_speed} -;Put printing message on LCD screen -M117 Printing... -""" - ], - end_gcode=[ - # 1 extruder - """;End GCode -M104 S0 ;extruder heater off -M140 S0 ;heated bed heater off (if you have it) - -G91 ;relative positioning -G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure -G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more -G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way - -M84 ;steppers off -G90 ;absolute positioning -;{profile_string} -""", - # 2 extruders - """;End GCode -M104 T0 S0 ;extruder heater off -M104 T1 S0 ;extruder heater off -M140 S0 ;heated bed heater off (if you have it) - -G91 ;relative positioning -G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure -G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more -G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way - -M84 ;steppers off -G90 ;absolute positioning -;{profile_string} -""", - # 3 extruders - """;End GCode -M104 T0 S0 ;extruder heater off -M104 T1 S0 ;extruder heater off -M104 T2 S0 ;extruder heater off -M140 S0 ;heated bed heater off (if you have it) - -G91 ;relative positioning -G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure -G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more -G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way - -M84 ;steppers off -G90 ;absolute positioning -;{profile_string} -""", - # 4 extruders - """;End GCode -M104 T0 S0 ;extruder heater off -M104 T1 S0 ;extruder heater off -M104 T2 S0 ;extruder heater off -M104 T3 S0 ;extruder heater off -M140 S0 ;heated bed heater off (if you have it) - -G91 ;relative positioning -G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure -G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more -G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way - -M84 ;steppers off -G90 ;absolute positioning -;{profile_string} -""" - ], - preSwitchExtruder_gcode=""";Switch between the current extruder and the next extruder, when printing with multiple extruders. -;This code is added before the T(n) -""", - postSwitchExtruder_gcode=""";Switch between the current extruder and the next extruder, when printing with multiple extruders. -;This code is added after the T(n) -""" -) - - -class Profile(object): - - regex_extruder_offset = re.compile("extruder_offset_([xy])(\d)") - regex_filament_diameter = re.compile("filament_diameter(\d?)") - regex_print_temperature = re.compile("print_temperature(\d?)") - regex_strip_comments = re.compile(";.*$", flags=re.MULTILINE) - - @classmethod - def from_cura_ini(cls, path): - import os - if not os.path.exists(path) or not os.path.isfile(path): - return None - - import ConfigParser - config = ConfigParser.ConfigParser() - try: - config.read(path) - except: - return None - - arrayified_options = ["print_temperature", "filament_diameter", "start.gcode", "end.gcode"] - translated_options = dict( - inset0_speed="outer_shell_speed", - insetx_speed="inner_shell_speed", - layer0_width_factor="first_layer_width_factor", - simple_mode="follow_surface", - ) - translated_options["start.gcode"] = "start_gcode" - translated_options["end.gcode"] = "end_gcode" - value_conversions = dict( - platform_adhesion={ - "None": PlatformAdhesionTypes.NONE, - "Brim": PlatformAdhesionTypes.BRIM, - "Raft": PlatformAdhesionTypes.RAFT - }, - support={ - "None": SupportLocationTypes.NONE, - "Touching buildplate": SupportLocationTypes.TOUCHING_BUILDPLATE, - "Everywhere": SupportLocationTypes.EVERYWHERE - }, - support_type={ - "Lines": SupportTypes.LINES, - "Grid": SupportTypes.GRID - }, - support_dual_extrusion={ - "Both": SupportDualTypes.BOTH, - "First extruder": SupportDualTypes.FIRST, - "Second extruder": SupportDualTypes.SECOND - } - ) - - result = dict() - for section in config.sections(): - if not section in ("profile", "alterations"): - continue - - for option in config.options(section): - ignored = False - key = option - - # try to fetch the value in the correct type - try: - value = config.getboolean(section, option) - except: - # no boolean, try int - try: - value = config.getint(section, option) - except: - # no int, try float - try: - value = config.getfloat(section, option) - except: - # no float, use str - value = config.get(section, option) - index = None - - for opt in arrayified_options: - if key.startswith(opt): - if key == opt: - index = 0 - else: - try: - # try to convert the target index, e.g. print_temperature2 => print_temperature[1] - index = int(key[len(opt):]) - 1 - except ValueError: - # ignore entries for which that fails - ignored = True - key = opt - break - if ignored: - continue - - if key in translated_options: - # if the key has to be translated to a new value, do that now - key = translated_options[key] - - if key in value_conversions and value in value_conversions[key]: - value = value_conversions[key][value] - - if index is not None: - # if we have an array to fill, make sure the target array exists and has the right size - if not key in result: - result[key] = [] - if len(result[key]) <= index: - for n in xrange(index - len(result[key]) + 1): - result[key].append(None) - result[key][index] = value - else: - # just set the value if there's no array to fill - result[key] = value - - # merge it with our default settings, the imported profile settings taking precedence - return cls.merge_profile(result) - - - @classmethod - def merge_profile(cls, profile, overrides=None): - result = dict() - for key in defaults.keys(): - r = cls.merge_profile_key(key, profile, overrides=overrides) - if r is not None: - result[key] = r - return result - - @classmethod - def merge_profile_key(cls, key, profile, overrides=None): - profile_value = None - override_value = None - - if not key in defaults: - return None - import copy - result = copy.deepcopy(defaults[key]) - - if key in profile: - profile_value = profile[key] - if overrides and key in overrides: - override_value = overrides[key] - - if profile_value is None and override_value is None: - # neither override nor profile, no need to handle this key further - return None - - if key in ("filament_diameter", "print_temperature", "start_gcode", "end_gcode"): - # the array fields need some special treatment. Basically something like this: - # - # override_value: [None, "b"] - # profile_value : ["a" , None, "c"] - # default_value : ["d" , "e" , "f", "g"] - # - # should merge to something like this: - # - # ["a" , "b" , "c", "g"] - # - # So override > profile > default, if neither override nor profile value are available - # the default value should just be left as is - - for x in xrange(len(result)): - if override_value is not None and x < len(override_value) and override_value[x] is not None: - # we have an override value for this location, so we use it - result[x] = override_value[x] - elif profile_value is not None and x < len(profile_value) and profile_value[x] is not None: - # we have a profile value for this location, so we use it - result[x] = profile_value[x] - - else: - # just change the result value to the override_value if available, otherwise to the profile_value if - # that is given, else just leave as is - if override_value is not None: - result = override_value - elif profile_value is not None: - result = profile_value - - return result - - def __init__(self, profile, overrides=None): - self._profile = self.__class__.merge_profile(profile, overrides=overrides) - - def profile(self): - import copy - return copy.deepcopy(self._profile) - - def get(self, key): - if key in ("machine_width", "machine_depth", "machine_center_is_zero"): - bedDimensions = s.globalGet(["printerParameters", "bedDimensions"]) - circular = bedDimensions["circular"] if "circular" in bedDimensions else False - radius = bedDimensions["radius"] if "radius" in bedDimensions and bedDimensions["radius"] is not None else 0 - if key == "machine_width": - return radius * 2 if circular else bedDimensions["x"] - elif key == "machine_depth": - return radius * 2 if circular else bedDimensions["y"] - elif key == "machine_center_is_zero": - return circular - else: - return None - - elif key == "extruder_amount": - return s.globalGetInt(["printerParameters", "numExtruders"]) - - elif key.startswith("extruder_offset_"): - extruder_offsets = s.globalGet(["printerParameters", "extruderOffsets"]) - match = Profile.regex_extruder_offset.match(key) - if not match: - return 0.0 - - axis, number = match.groups() - axis = axis.lower() - number = int(number) - - if not axis in ("x", "y"): - return 0.0 - if number >= len(extruder_offsets): - return 0.0 - if not axis in extruder_offsets[number]: - return 0.0 - return extruder_offsets[number][axis] - - elif key.startswith("filament_diameter"): - match = Profile.regex_filament_diameter.match(key) - if not match: - return 0.0 - - diameters = self._get("filament_diameter") - if not match.group(1): - return diameters[0] - index = int(match.group(1)) - if index >= len(diameters): - return 0.0 - return diameters[index] - - elif key.startswith("print_temperature"): - match = Profile.regex_print_temperature.match(key) - if not match: - return 0.0 - - temperatures = self._get("print_temperature") - if not match.group(1): - return temperatures[0] - index = int(match.group(1)) - if index >= len(temperatures): - return 0.0 - return temperatures[index] - - else: - return self._get(key) - - def _get(self, key): - if key in self._profile: - return self._profile[key] - elif key in defaults: - return defaults[key] - else: - return None - - def get_int(self, key, default=None): - value = self.get(key) - if value is None: - return default - - try: - return int(value) - except ValueError: - return default - - def get_float(self, key, default=None): - value = self.get(key) - if value is None: - return default - - if isinstance(value, (str, unicode, basestring)): - value = value.replace(",", ".").strip() - - try: - return float(value) - except ValueError: - return default - - def get_boolean(self, key, default=None): - value = self.get(key) - if value is None: - return default - - if isinstance(value, bool): - return value - elif isinstance(value, (str, unicode, basestring)): - return value.lower() == "true" or value.lower() == "yes" or value.lower() == "on" or value == "1" - elif isinstance(value, (int, float)): - return value > 0 - else: - return value == True - - def get_microns(self, key, default=None): - value = self.get_float(key, default=None) - if value is None: - return default - return int(value * 1000) - - def get_gcode_template(self, key): - extruder_count = s.globalGetInt(["printerParameters", "numExtruders"]) - - if key in self._profile: - gcode = self._profile[key] - else: - gcode = defaults[key] - - if key in ("start_gcode", "end_gcode"): - return gcode[extruder_count-1] - else: - return gcode - - def get_machine_extruder_offset(self, extruder, axis): - extruder_offsets = s.globalGet(["printerParameters", "extruderOffsets"]) - if extruder >= len(extruder_offsets): - return 0.0 - if axis.lower() not in ("x", "y"): - return 0.0 - return extruder_offsets[extruder][axis.lower()] - - def get_profile_string(self): - import base64 - import zlib - - import copy - profile = copy.deepcopy(defaults) - profile.update(self._profile) - for key in ("print_temperature", "print_temperature2", "print_temperature3", "print_temperature4", - "filament_diameter", "filament_diameter2", "filament_diameter3", "filament_diameter4"): - profile[key] = self.get(key) - - result = [] - for k, v in profile.items(): - if isinstance(v, (str, unicode)): - result.append("{k}={v}".format(k=k, v=v.encode("utf-8"))) - else: - result.append("{k}={v}".format(k=k, v=v)) - - return base64.b64encode(zlib.compress("\b".join(result), 9)) - - def replaceTagMatch(self, m): - import time - - pre = m.group(1) - tag = m.group(2) - - if tag == 'time': - return pre + time.strftime('%H:%M:%S') - if tag == 'date': - return pre + time.strftime('%d-%m-%Y') - if tag == 'day': - return pre + ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][int(time.strftime('%w'))] - if tag == 'profile_string': - return pre + 'CURA_OCTO_PROFILE_STRING:%s' % (self.get_profile_string()) - - if pre == 'F' and tag == 'max_z_speed': - f = self.get_float("travel_speed") * 60 - elif pre == 'F' and tag in ['print_speed', 'retraction_speed', 'travel_speed', 'bottom_layer_speed', 'cool_min_feedrate']: - f = self.get_float(tag) * 60 - elif self.get(tag): - f = self.get(tag) - else: - return '%s?%s?' % (pre, tag) - - if (f % 1) == 0: - return pre + str(int(f)) - - return pre + str(f) - - def get_gcode(self, key): - extruder_count = s.globalGetInt(["printerParameters", "numExtruders"]) - - prefix = "" - postfix = "" - - if self.get("gcode_flavor") == GcodeFlavors.ULTIGCODE: - if key == "end_gcode": - return "M25 ;Stop reading from this point on.\n;CURA_PROFILE_STRING:%s\n" % (self.get_profile_string()) - return "" - - if key == "start_gcode": - contents = self.get_gcode_template("start_gcode") - - e_steps = self.get_float("steps_per_e") - if e_steps > 0: - prefix += "M92 E{e_steps}\n" % (e_steps) - temp = self.get_float("print_temperature") - - bedTemp = 0 - if self.get_boolean("has_heated_bed"): - bedTemp = self.get_float("print_bed_temperature") - include_bed_temps = bedTemp > 0 and not "{print_bed_temperature}" in Profile.regex_strip_comments.sub("", contents) - - if include_bed_temps: - prefix += "M140 S{print_bed_temperature}\n" - - if temp > 0 and not "{print_temperature}" in Profile.regex_strip_comments.sub("", contents): - if extruder_count > 0: - def temp_line(temp, extruder, 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) - for n in xrange(1, extruder_count): - prefix += temp_line(temp, n, "M104 T{extruder} S{temp}\n") - for n in xrange(0, extruder_count): - prefix += temp_line(temp, n, "M109 T{extruder} S{temp}\n") - prefix += "T0\n" - else: - prefix += "M109 S{temp}\n".format(temp=temp) - - if include_bed_temps: - prefix += "M190 S{print_bed_temperature}\n".format(bedTemp=bedTemp) - - else: - contents = self.get_gcode_template(key) - - return unicode(prefix + re.sub("(.)\{([^\}]*)\}", self.replaceTagMatch, contents).rstrip() + '\n' + postfix).strip().encode('utf-8') + '\n' - - def calculate_edge_width_and_line_count(self): - wall_thickness = self.get_float("wall_thickness") - nozzle_size = self.get_float("nozzle_size") - - if self.get_boolean("spiralize") or self.get_boolean("follow_surface"): - return wall_thickness, 1 - if wall_thickness < 0.01: - return nozzle_size, 0 - if wall_thickness < nozzle_size: - return wall_thickness, 1 - - edge_width = None - line_count = int(wall_thickness / (nozzle_size - 0.0001)) - if line_count < 1: - edge_width = nozzle_size - line_count = 1 - line_width = wall_thickness / line_count - line_width_alt = wall_thickness / (line_count + 1) - if line_width > nozzle_size * 1.5: - return line_width_alt, line_count + 1 - if not edge_width: - edge_width = line_width - return edge_width, line_count - - def calculate_solid_layer_count(self): - layer_height = self.get_float("layer_height") - solid_thickness = self.get_float("solid_layer_thickness") - if layer_height == 0.0: - return 1 - import math - return int(math.ceil(solid_thickness / (layer_height - 0.0001))) - - def calculate_minimal_extruder_count(self): - extruder_count = s.globalGetInt(["printerParameters", "numExtruders"]) - if extruder_count < 2: - return 1 - if self.get("support") == SupportLocationTypes.NONE: - return 1 - if self.get("support_dual_extrusion") == SupportDualTypes.SECOND: - return 2 - return 1 - - def convert_to_engine(self): - - edge_width, line_count = self.calculate_edge_width_and_line_count() - solid_layer_count = self.calculate_solid_layer_count() - - extruder_count = s.globalGetInt(["printerParameters", "numExtruders"]) - minimal_extruder_count = self.calculate_minimal_extruder_count() - - settings = { - "layerThickness": self.get_microns("layer_height"), - "initialLayerThickness": self.get_microns("bottom_thickness") if self.get_float("bottom_thickness") > 0.0 else self.get_microns("layer_height"), - "filamentDiameter": self.get_microns("filament_diameter"), - "filamentFlow": self.get_int("filament_flow"), - "extrusionWidth": edge_width * 1000, - "layer0extrusionWidth": int(edge_width * self.get_float("first_layer_width_factor") / 100 * 1000), - "insetCount": line_count, - "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"), - "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"), - "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, - "supportAngle": int(-1) if self.get("support") == SupportLocationTypes.NONE else self.get_int("support_angle"), - "supportEverywhere": int(1) if self.get("support") == SupportLocationTypes.EVERYWHERE else int(0), - "supportLineDistance": int(100 * edge_width * 1000 / self.get_float("support_fill_rate")) if self.get_float("support_fill_rate") > 0 else -1, - "supportXYDistance": int(1000 * self.get_float("support_xy_distance")), - "supportZDistance": int(1000 * self.get_float("support_z_distance")), - "supportExtruder": 0 if self.get("support_dual_extrusion") == SupportDualTypes.FIRST else (1 if self.get("support_dual_extrusion") == SupportDualTypes.SECOND and minimal_extruder_count > 1 else -1), - "retractionAmount": self.get_microns("retraction_amount") if self.get_boolean("retraction_enable") else 0, - "retractionSpeed": self.get_int("retraction_speed"), - "retractionMinimalDistance": self.get_microns("retraction_min_travel"), - "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_boolean("retraction_combing") 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, - - # model positioning - "posx": int(self.get_float("machine_width") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0, - "posy": int(self.get_float("machine_depth") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0, - - # 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"), - - # fixing - "fixHorrible": 0, - } - - for extruder in range(1, extruder_count): - for axis in ("x", "y"): - settings["extruderOffset[{extruder}].{axis}".format(extruder=extruder, axis=axis.upper())] = self.get_machine_extruder_offset(extruder, axis) - - fanFullHeight = self.get_microns("fan_full_height") - settings["fanFullOnLayerNr"] = (fanFullHeight - settings["initialLayerThickness"] - 1) / settings["layerThickness"] + 1 - if settings["fanFullOnLayerNr"] < 0: - settings["fanFullOnLayerNr"] = 0 - - if self.get("support_type") == SupportTypes.LINES: - settings["supportType"] = 1 - - # infill - if self.get_float("fill_density") == 0: - settings["sparseInfillLineDistance"] = -1 - - elif self.get_float("fill_density") == 100: - settings["sparseInfillLineDistance"] = settings["extrusionWidth"] - settings["downSkinCount"] = 10000 - settings["upSkinCount"] = 10000 - - else: - settings["sparseInfillLineDistance"] = int(100 * edge_width * 1000 / self.get_float("fill_density")) - - # brim/raft/skirt - if self.get("platform_adhesion") == PlatformAdhesionTypes.BRIM: - settings["skirtDistance"] = 0 - settings["skirtLineCount"] = self.get_int("brim_line_count") - - elif self.get("platform_adhesion") == PlatformAdhesionTypes.RAFT: - settings["skirtDistance"] = 0 - settings["skirtLineCount"] = 0 - settings["raftMargin"] = self.get_microns("raft_margin") - settings["raftLineSpacing"] = self.get_microns("raft_line_spacing") - settings["raftBaseThickness"] = self.get_microns("raft_base_thickness") - settings["raftBaseLinewidth"] = self.get_microns("raft_base_linewidth") - 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["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["raftSurfaceLayers"] = self.get_int("raft_surface_layers") - settings["raftSurfaceSpeed"] = self.get_int("bottom_layer_speed") - - else: - settings["skirtDistance"] = self.get_microns("skirt_gap") - settings["skirtLineCount"] = self.get_int("skirt_line_count") - settings["skirtMinLength"] = self.get_microns("skirt_minimal_length") - - # fixing - if self.get_boolean("fix_horrible_union_all_type_a"): - settings["fixHorrible"] |= 0x01 - if self.get_boolean("fix_horrible_union_all_type_b"): - settings["fixHorrible"] |= 0x02 - if self.get_boolean("fix_horrible_use_open_bits"): - settings["fixHorrible"] |= 0x10 - if self.get_boolean("fix_horrible_extensive_stitching"): - settings["fixHorrible"] |= 0x04 - - if settings["layerThickness"] <= 0: - settings["layerThickness"] = 1000 - - # gcode flavor - if self.get("gcode_flavor") == GcodeFlavors.ULTIGCODE: - settings["gcodeFlavor"] = 1 - elif self.get("gcode_flavor") == GcodeFlavors.MAKERBOT: - settings["gcodeFlavor"] = 2 - elif self.get("gcode_flavor") == GcodeFlavors.BFB: - settings["gcodeFlavor"] = 3 - elif self.get("gcode_flavor") == GcodeFlavors.MACH3: - settings["gcodeFlavor"] = 4 - elif self.get("gcode_flavor") == GcodeFlavors.REPRAP_VOLUME: - settings["gcodeFlavor"] = 5 - - # extras - if self.get_boolean("spiralize"): - settings["spiralizeMode"] = 1 - if self.get_boolean("follow_surface"): - settings["simpleMode"] = 1 - - # dual extrusion - if self.get_boolean("wipe_tower") and extruder_count > 1: - import math - settings["wipeTowerSize"] = int(math.sqrt(self.get_float("wipe_tower_volume") * 1000 * 1000 * 1000 / settings["layerThickness"])) - if self.get_boolean("ooze_shield"): - settings["enableOozeShield"] = 1 - - return settings diff --git a/src/octoprint/plugins/cura/profiles/default.profile.yaml b/src/octoprint/plugins/cura/profiles/default.profile.yaml deleted file mode 100644 index d53fabc6..00000000 --- a/src/octoprint/plugins/cura/profiles/default.profile.yaml +++ /dev/null @@ -1,4 +0,0 @@ -layer_height: 0.2 -print_temperature: -- 220.0 -- 220.0 \ No newline at end of file diff --git a/src/octoprint/plugins/cura/static/css/cura.css b/src/octoprint/plugins/cura/static/css/cura.css deleted file mode 100644 index f35eab40..00000000 --- a/src/octoprint/plugins/cura/static/css/cura.css +++ /dev/null @@ -1 +0,0 @@ -table th.settings_plugin_cura_profiles_key,table td.settings_plugin_cura_profiles_key{text-overflow:ellipsis;text-align:left;width:200px}table th.settings_plugin_cura_profiles_name,table td.settings_plugin_cura_profiles_name{text-overflow:ellipsis;text-align:left}table th.settings_plugin_cura_profiles_actions,table td.settings_plugin_cura_profiles_actions{text-align:center;width:100px}table th.settings_plugin_cura_profiles_actions a,table td.settings_plugin_cura_profiles_actions a{text-decoration:none;color:#000}table th.settings_plugin_cura_profiles_actions a.disabled,table td.settings_plugin_cura_profiles_actions a.disabled{color:#ccc;cursor:default} \ No newline at end of file diff --git a/src/octoprint/plugins/cura/static/js/cura.js b/src/octoprint/plugins/cura/static/js/cura.js deleted file mode 100644 index 3c152ae2..00000000 --- a/src/octoprint/plugins/cura/static/js/cura.js +++ /dev/null @@ -1,191 +0,0 @@ -$(function() { - function CuraViewModel(parameters) { - var self = this; - - self.loginState = parameters[0]; - self.settingsViewModel = parameters[1]; - self.slicingViewModel = parameters[2]; - - self.fileName = ko.observable(); - - self.placeholderName = ko.observable(); - self.placeholderDisplayName = ko.observable(); - self.placeholderDescription = ko.observable(); - - self.profileName = ko.observable(); - self.profileDisplayName = ko.observable(); - self.profileDescription = ko.observable(); - self.profileAllowOverwrite = ko.observable(true); - - self.uploadElement = $("#settings-cura-import"); - self.uploadButton = $("#settings-cura-import-start"); - - self.profiles = new ItemListHelper( - "plugin_cura_profiles", - { - "id": function(a, b) { - if (a["key"].toLocaleLowerCase() < b["key"].toLocaleLowerCase()) return -1; - if (a["key"].toLocaleLowerCase() > b["key"].toLocaleLowerCase()) return 1; - return 0; - }, - "name": function(a, b) { - // sorts ascending - var aName = a.name(); - if (aName === undefined) { - aName = ""; - } - var bName = b.name(); - if (bName === undefined) { - bName = ""; - } - - if (aName.toLocaleLowerCase() < bName.toLocaleLowerCase()) return -1; - if (aName.toLocaleLowerCase() > bName.toLocaleLowerCase()) return 1; - return 0; - } - }, - {}, - "id", - [], - [], - 5 - ); - - self._sanitize = function(name) { - return name.replace(/[^a-zA-Z0-9\-_\.\(\) ]/g, "").replace(/ /g, "_"); - }; - - self.uploadElement.fileupload({ - dataType: "json", - maxNumberOfFiles: 1, - autoUpload: false, - add: function(e, data) { - if (data.files.length == 0) { - return false; - } - - self.fileName(data.files[0].name); - - var name = self.fileName().substr(0, self.fileName().lastIndexOf(".")); - self.placeholderName(self._sanitize(name).toLowerCase()); - self.placeholderDisplayName(name); - self.placeholderDescription("Imported from " + self.fileName() + " on " + formatDate(new Date().getTime() / 1000)); - - self.uploadButton.on("click", function() { - var form = { - allowOverwrite: self.profileAllowOverwrite() - }; - - if (self.profileName() !== undefined) { - form["name"] = self.profileName(); - } - if (self.profileDisplayName() !== undefined) { - form["displayName"] = self.profileDisplayName(); - } - if (self.profileDescription() !== undefined) { - form["description"] = self.profileDescription(); - } - - data.formData = form; - data.submit(); - }); - }, - done: function(e, data) { - self.fileName(undefined); - self.placeholderName(undefined); - self.placeholderDisplayName(undefined); - self.placeholderDescription(undefined); - self.profileName(undefined); - self.profileDisplayName(undefined); - self.profileDescription(undefined); - self.profileAllowOverwrite(true); - - $("#settings-plugin-cura-import").modal("hide"); - self.requestData(); - self.slicingViewModel.requestData(); - } - }); - - self.removeProfile = function(data) { - if (!data.resource) { - return; - } - - self.profiles.removeItem(function(item) { - return (item.key == data.key); - }); - - $.ajax({ - url: data.resource(), - type: "DELETE", - success: function() { - self.requestData(); - self.slicingViewModel.requestData(); - } - }); - }; - - self.makeProfileDefault = function(data) { - if (!data.resource) { - return; - } - - _.each(self.profiles.items(), function(item) { - item.isdefault(false); - }); - var item = self.profiles.getItem(function(item) { - return item.key == data.key; - }); - if (item !== undefined) { - item.isdefault(true); - } - - $.ajax({ - url: data.resource(), - type: "PATCH", - dataType: "json", - data: JSON.stringify({default: true}), - contentType: "application/json; charset=UTF-8", - success: function() { - self.requestData(); - } - }); - }; - - self.showImportProfileDialog = function() { - $("#settings_plugin_cura_import").modal("show"); - }; - - self.requestData = function() { - $.ajax({ - url: API_BASEURL + "slicing/cura/profiles", - type: "GET", - dataType: "json", - success: self.fromResponse - }); - }; - - self.fromResponse = function(data) { - var profiles = []; - _.each(_.keys(data), function(key) { - profiles.push({ - key: key, - name: ko.observable(data[key].displayName), - description: ko.observable(data[key].description), - isdefault: ko.observable(data[key].default), - resource: ko.observable(data[key].resource) - }); - }); - self.profiles.updateItems(profiles); - }; - - self.onBeforeBinding = function () { - self.settings = self.settingsViewModel.settings; - self.requestData(); - }; - - } - - // view model class, parameters for constructor, container to bind to - ADDITIONAL_VIEWMODELS.push([CuraViewModel, ["loginStateViewModel", "settingsViewModel", "slicingViewModel"], document.getElementById("settings_plugin_cura_dialog")]); -}); \ No newline at end of file diff --git a/src/octoprint/plugins/cura/static/less/cura.less b/src/octoprint/plugins/cura/static/less/cura.less deleted file mode 100644 index 0d28da21..00000000 --- a/src/octoprint/plugins/cura/static/less/cura.less +++ /dev/null @@ -1,29 +0,0 @@ -table { - th, td { - &.settings_plugin_cura_profiles_key { - text-overflow: ellipsis; - text-align: left; - width: 200px; - } - - &.settings_plugin_cura_profiles_name { - text-overflow: ellipsis; - text-align: left; - } - - &.settings_plugin_cura_profiles_actions { - text-align: center; - width: 100px; - - a { - text-decoration: none; - color: #000; - - &.disabled { - color: #ccc; - cursor: default; - } - } - } - } -} \ No newline at end of file diff --git a/src/octoprint/plugins/cura/templates/cura_settings_dialog.jinja2 b/src/octoprint/plugins/cura/templates/cura_settings_dialog.jinja2 deleted file mode 100644 index 92db6175..00000000 --- a/src/octoprint/plugins/cura/templates/cura_settings_dialog.jinja2 +++ /dev/null @@ -1,247 +0,0 @@ -
-

{{ _('General') }}

- -
-
- -
- -
-
-
-
- -
-
-
- -

{{ _('Profiles') }}

- - - - - - - - - - - - - - - - - -
{{ _('Identifier') }}{{ _('Name') }}{{ _('Actions') }}
-  |  -
- - - - - - - - - - -
\ No newline at end of file diff --git a/src/octoprint/plugins/svgtogcode/static/js/working_area.js b/src/octoprint/plugins/svgtogcode/static/js/working_area.js index cff770b7..0f51f77d 100644 --- a/src/octoprint/plugins/svgtogcode/static/js/working_area.js +++ b/src/octoprint/plugins/svgtogcode/static/js/working_area.js @@ -16,34 +16,7 @@ function WorkingAreaViewModel(loginStateViewModel, settingsViewModel, printerSta self.isError = ko.observable(undefined); self.isReady = ko.observable(undefined); self.isLoading = ko.observable(undefined); - self.currentPos = ko.observable(undefined); - self.laserPos = ko.computed(function(){ - var pos = self.currentPos(); - if(!pos){ - - return "(?, ?)"; - } else { - return "("+ pos.x + ", "+ pos.y + ")"; - } - }, this); - self._processPos = function(posStr) { - // example posStr: "X: 73.0000 Y: 192.0000 Z: 0.0000" - var parts = posStr.split(" "); - var x = parseFloat(parts[1]).toFixed(2) - var y = parseFloat(parts[3]).toFixed(2) - self.currentPos({x:x, y:y}); - }; - - self._fromData = function(data) { - if(data.workPosition){ - self._processPos(data.workPosition); - } - }; - - self.fromCurrentData = function(data) { - self._fromData(data); - }; self.move_laser = function(el){ var x = event.offsetX; @@ -56,66 +29,22 @@ function WorkingAreaViewModel(loginStateViewModel, settingsViewModel, printerSta contentType: "application/json; charset=UTF-8", data: JSON.stringify({"command": command}) }); - } + }; - self.laser_start = function(e){ - console.log("start lasering...", e); - return false; + self.crosshairX = function(){ + var pos = self.state.currentPos(); + return pos !== undefined ? (pos.x - 15) : -100; // subtract width/2; + + }; + self.crosshairY = function(){ + var h = document.getElementById('area_preview').clientHeight; + var pos = self.state.currentPos(); + return pos !== undefined ? (h - pos.y - 15) : -100; // subtract height/2; }; - - self.titlePrintButton = self.state.titlePrintButton; - self.titlePauseButton = self.state.titlePauseButton; - self.pause = self.state.pause; - self.cancel = self.state.cancel; - -// -// self.getLaserPos = function(){ -// console.log("foo") -// x = self.x === undefined ? '?' : self.x; -// y = self.y === undefined ? '?' : self.y; -// return "x"+ x + ", y"+ y; -// } -// -// self.sendCommand = function() { -// var command = self.command(); -// if (!command) { -// return; -// } -// -// -// }; -// -// self.handleKeyDown = function(event) { -// var keyCode = event.keyCode; -// -// if (keyCode == 38 || keyCode == 40) { -// if (keyCode == 38 && self.cmdHistory.length > 0 && self.cmdHistoryIdx > 0) { -// console.log("keycode 38") -// } else if (keyCode == 40 && self.cmdHistoryIdx < self.cmdHistory.length - 1) { -// console.log("keycode 40") -// } -// -// // prevent the cursor from being moved to the beginning of the input field (this is actually the reason -// // why we do the arrow key handling in the keydown event handler, keyup would be too late already to -// // prevent this from happening, causing a jumpy cursor) -// return false; -// } -// -// // do not prevent default action -// return true; -// }; -// -// self.handleKeyUp = function(event) { -// if (event.keyCode == 13) { -// self.sendCommand(); -// } -// -// // do not prevent default action -// return true; -// }; + } diff --git a/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 b/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 index 5caa37b9..edd7d14a 100644 --- a/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 +++ b/src/octoprint/plugins/svgtogcode/templates/override_index.jinja2 @@ -43,29 +43,28 @@ +var UI_API_KEY = "{{ uiApiKey }}"; + var VERSION = "{{ version }}"; + var DISPLAY_VERSION = "{{ display_version }}"; + var LOCALE = "{{ g.locale }}"; + var ADDITIONAL_VIEWMODELS = [];