featurescript icon indicating copy to clipboard operation
featurescript copied to clipboard

puthon script

Open tacomakes opened this issue 2 months ago • 0 comments

The script inserts a small Z lift, moves to the target X, then returns Z so the move doesn't drag through the print. Defaults: move to X=0 every 10 layers with a 5 mm lift and a 6000 mm/min travel feed.

#!/usr/bin/env python3 """ insert_move_every_n_layers.py

Usage (PrusaSlicer post-processing): prusaslicer will invoke the script; it usually passes input and output filenames. Example args in PrusaSlicer: --x 0 --every 10 --lift 5 --feed 6000

This script finds lines like ";LAYER:123" and after every Nth layer inserts a short safe sequence to lift Z, move to X position, then restore Z.

Default values: x=0.0, every=10, lift=5.0, feed=6000 """

import sys import argparse import re

def parse_args(): p = argparse.ArgumentParser(description="Insert a move to X every N layers in G-code") p.add_argument("--x", type=float, default=0.0, help="X coordinate to move to (mm)") p.add_argument("--every", type=int, default=10, help="Do it every N layers (use 1 for every layer)") p.add_argument("--lift", type=float, default=5.0, help="Relative Z lift before moving (mm)") p.add_argument("--feed", type=float, default=6000, help="Feedrate for travel move (mm/min)") p.add_argument("--marker", type=str, default=";MOVE_INSERTED", help="Marker comment to avoid double-insertions") p.add_argument("infile", nargs="?", default=None, help="Input gcode file (optional, PrusaSlicer usually passes it)") p.add_argument("outfile", nargs="?", default=None, help="Output gcode file (optional)") return p.parse_args()

def make_move_block(x, lift, feed, marker): # Use relative moves for lift and return so we don't need current Z value. # Sequence: # ; marker # G91 ; relative mode # G1 Z{lift} F3000 # G90 ; absolute mode # G1 X{x} F{feed} # G91 # G1 Z-{lift} F3000 # G90 # You may want to tweak feed and retracts for your setup. lines = [ f"{marker} ; inserted by insert_move_every_n_layers.py", "G91", f"G1 Z{lift:.3f} F3000 ; lift before move", "G90", f"G1 X{x:.3f} F{feed:.0f} ; travel to X", "G91", f"G1 Z-{lift:.3f} F3000 ; lower back down", "G90", "" # blank line for readability ] return "\n".join(lines)

def main(): args = parse_args()

# Input / output file handling
if args.infile and args.outfile:
    infile = args.infile
    outfile = args.outfile
elif args.infile and not args.outfile:
    # If only one file provided, overwrite it safely
    infile = args.infile
    outfile = infile + ".tmp"
else:
    # When PrusaSlicer runs the script it usually supplies input and output file paths.
    # But to be safe, read stdin and write stdout if no files provided.
    infile = None
    outfile = None

content = None
if infile:
    with open(infile, "r", encoding="utf-8") as f:
        content = f.read()
else:
    content = sys.stdin.read()

# Avoid double-inserting by checking for marker presence
if args.marker and args.marker in content:
    # Already ran (or file already contains marker) — do nothing and output original
    out_text = content
else:
    # Process content line by line
    out_lines = []
    layer_re = re.compile(r"^;LAYER:(\s*\d+)", re.IGNORECASE)
    for line in content.splitlines():
        out_lines.append(line)
        m = layer_re.match(line)
        if m:
            try:
                layer_num = int(m.group(1))
            except:
                # fallback: skip if can't parse
                continue
            if args.every > 0 and (layer_num % args.every) == 0:
                # skip inserting at layer 0 (optional) — many people want to skip layer 0
                # If you want to run at layer 0 too, remove the next condition.
                if layer_num == 0:
                    continue
                move_block = make_move_block(args.x, args.lift, args.feed, args.marker)
                out_lines.append(move_block)

    out_text = "\n".join(out_lines) + "\n"

if outfile:
    with open(outfile, "w", encoding="utf-8") as f:
        f.write(out_text)
    # If we created a temp file (infile.tmp), replace original
    if args.infile and not args.outfile:
        import os
        os.replace(outfile, infile)
else:
    sys.stdout.write(out_text)

if name == "main": main()

tacomakes avatar Oct 30 '25 14:10 tacomakes