485 lines
20 KiB
INI
485 lines
20 KiB
INI
# Copyright (C) 2022 Justin Schuh <code@justinschuh.com>
|
|
#
|
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
|
|
|
[gcode_macro print_start]
|
|
description: Inserted by slicer at start of print. Rather than using this macro
|
|
directly you should configure your slicer as instructed in the readme.
|
|
Usage: PRINT_START BED=<temp> EXTRUDER=<temp> [CHAMBER=<temp>]
|
|
[MESH_MIN=<x,y>] [MESH_MAX=<x,y>] [LAYERS=<num>]
|
|
[NOZZLE_SIZE=<mm>]
|
|
gcode:
|
|
{action_respond_info(
|
|
"This file is using an old The PRINT_START format. This print will run "
|
|
"fine, but you should update your slicer config to take advantage of the "
|
|
"phased PRINT_START macros. The slicer documentation is here:\n"
|
|
"https://github.com/jschuh/klipper-macros\x23slicer-configuration"
|
|
)}
|
|
|
|
_PRINT_START_PHASE_INIT {rawparams}
|
|
_PRINT_START_PHASE_PREHEAT
|
|
_PRINT_START_PHASE_PROBING
|
|
_PRINT_START_PHASE_EXTRUDER
|
|
_PRINT_START_PHASE_PURGE
|
|
|
|
[gcode_macro _print_start_phase_init]
|
|
description: Inserted by slicer at start of print. Initializes PRINT_START
|
|
phases.
|
|
Usage: See PRINT_START.
|
|
gcode:
|
|
CHECK_KM_CONFIG # Need this in case startup errors were missed.
|
|
SET_GCODE_VARIABLE MACRO=_print_end_inner VARIABLE=cancelled VALUE="{False}"
|
|
_KM_APPLY_PRINT_OFFSET RESET=1
|
|
_PRINT_START_PHASE_CHECK PHASE=none
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
|
|
{% if not params.BED %}
|
|
{% set dummy = params.__setitem__('BED', params.BED_TEMP|int) %}
|
|
{% endif %}
|
|
{% if not params.EXTRUDER %}
|
|
{% set dummy = params.__setitem__('EXTRUDER', params.EXTRUDER_TEMP|int) %}
|
|
{% endif %}
|
|
|
|
# Stash all the params for use by the other phases.
|
|
PRINT_START_SET PRINT_START_PHASE="init" {% for k in params %}{' %s=\"%s\"' %
|
|
(k,params[k]|replace('\\','\\\\')|replace('\'','\\\'')|replace('\"','\\\"'))
|
|
}{% endfor %}
|
|
|
|
# Check and propogate the printable bounds.'
|
|
_km_check_and_set_print_bounds
|
|
|
|
M107 # Turn off part cooling fan in case it was on.
|
|
CLEAR_PAUSE
|
|
# Kick off the longest preheats in the init.
|
|
M140 S{params.BED}
|
|
{% if params.CHAMBER %}M141 S{params.CHAMBER|int}{% endif %}
|
|
{% if printer.bed_mesh %}BED_MESH_CLEAR{% endif %}
|
|
# Load a saved mesh if configured.
|
|
{% if km.start_try_saved_surface_mesh and printer.bed_mesh %}
|
|
LOAD_SURFACE_MESH
|
|
{% endif %}
|
|
PRINT_START_SET PRINT_START_PHASE="preheat"
|
|
|
|
[gcode_macro _print_start_phase_preheat]
|
|
description: Inserted by slicer at start of print. Handles the bed and chamber
|
|
heating phases and ends when both are stabilized at their target temperatures.
|
|
Usage: See PRINT_START.
|
|
gcode:
|
|
_PRINT_START_PHASE_CHECK PHASE=preheat
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% set BED = print.BED|int %}
|
|
{% set EXTRUDER = print.EXTRUDER|int %}
|
|
{% set CHAMBER = print.CHAMBER|default(0)|int %}
|
|
{% set LAYERS = print.LAYERS|default(0)|int %}
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
# The bed started at no more than 0.2C below and 1.0C above the target temp.
|
|
{% set bed_at_target = (BED + 0.4 - printer.heater_bed.temperature) |
|
|
abs <= 0.6 %}
|
|
PRINT_START_SET BED_AT_TARGET={1 if bed_at_target else 0}
|
|
{% set start_level_bed_at_temp = km.start_level_bed_at_temp and
|
|
not printer.bed_mesh.profile_name %}
|
|
{% set actions_at_temp = start_level_bed_at_temp or
|
|
km.start_quad_gantry_level_at_temp or
|
|
km.start_z_tilt_adjust_at_temp or
|
|
(km.start_home_z_at_temp and not bed_at_target) %}
|
|
{% set bed_overshoot = (BED + (km.start_bed_heat_overshoot if
|
|
(BED and not bed_at_target) else 0.0),
|
|
printer.configfile.settings.heater_bed.max_temp ) | min %}
|
|
|
|
INIT_LAYER_GCODE LAYERS="{LAYERS}"
|
|
{% if CHAMBER > 0.0 %}
|
|
M141 S{CHAMBER}
|
|
{% endif %}
|
|
# Start bed heating
|
|
M140 S{bed_overshoot}
|
|
{% if actions_at_temp %}
|
|
# If we're going to run a bed level we either have a probing temp specified
|
|
# or we heat the extruder part way to avoid oozing while probing.
|
|
M104 S{km.start_extruder_probing_temp if km.start_extruder_probing_temp > 0
|
|
else (km.start_extruder_preheat_scale * EXTRUDER)|round(0,'ceil')|int}
|
|
{% else %}
|
|
# Honor the extruder probing temp, in case we just want to delay extruder
|
|
# heating until after the bed is ready.
|
|
M104 S{km.start_extruder_probing_temp if km.start_extruder_probing_temp > 0
|
|
else EXTRUDER}
|
|
{% endif %}
|
|
# home all axes
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=homing RESET_STACK=1
|
|
G28
|
|
G90
|
|
{% if BED > 0.0 %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=bed_heating RESET_STACK=1
|
|
# Skip this if the bed was already at target when START_PRINT was called.
|
|
{% if not bed_at_target %}
|
|
PARK
|
|
# Overshoot the target a bit.
|
|
M190 S{bed_overshoot}
|
|
G4 P{km.start_bed_heat_delay / 2}
|
|
M190 R{BED} # Settle down after the overshoot.
|
|
G4 P{km.start_bed_heat_delay / 2}
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
{% if CHAMBER > 0.0 %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=chamber_heating RESET_STACK=1
|
|
_KM_PARK_IF_NEEDED HEATER="chamber" RANGE=ABOVE
|
|
M191 S{CHAMBER}
|
|
{% endif %}
|
|
|
|
{% if BED > 0.0 and bed_at_target%}
|
|
M190 R{BED} # Extra bed stabilization if we skipped it earlier.
|
|
{% endif %}
|
|
PRINT_START_SET PRINT_START_PHASE="probing"
|
|
|
|
[gcode_macro _print_start_phase_probing]
|
|
description: Inserted by slicer at start of print. Performs probing (including
|
|
mesh bed level) and other operations that should be run when the bed and
|
|
chamber are stabilized at their target temps.
|
|
Usage: See PRINT_START.
|
|
gcode:
|
|
_PRINT_START_PHASE_CHECK PHASE=probing
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
{% set MESH_MIN = print.MESH_MIN|default(None) %}
|
|
{% set MESH_MAX = print.MESH_MAX|default(None) %}
|
|
# Randomize the placement of the print on the bed.
|
|
{% if km.start_random_placement_max > 0 and print.PRINT_MIN and MESH_MIN %}
|
|
{% set PRINT_MIN = print.PRINT_MIN.split(",")|map('float')|list %}
|
|
{% set PRINT_MAX = print.PRINT_MAX.split(",")|map('float')|list %}
|
|
{% set x_offset = (((km.print_max[0] - km.print_min[0] - PRINT_MAX[0] +
|
|
PRINT_MIN[0] - 2 * km.start_random_placement_padding)|int,
|
|
km.start_random_placement_max * 2)|min, 0)|max %}
|
|
{% set y_offset = (((km.print_max[1] - km.print_min[1] - PRINT_MAX[1] +
|
|
PRINT_MIN[1] - 2 * km.start_random_placement_padding)|int,
|
|
km.start_random_placement_max * 2)|min, 0)|max %}
|
|
{% if x_offset > 0 %}
|
|
{% set x_offset = range(x_offset)|random + km.print_min[0] -
|
|
PRINT_MIN[0] + km.start_random_placement_padding %}
|
|
{% endif %}
|
|
{% if y_offset > 0 %}
|
|
{% set y_offset = range(y_offset)|random + km.print_min[1] -
|
|
PRINT_MIN[1] + km.start_random_placement_padding %}
|
|
{% endif %}
|
|
# This MESH_MIN/MESH_MAX gets passed to BED_MESH_CALIBRATE below, but the
|
|
# rest of the macros rely on SET_GCODE_OFFSET performing the adjustment.
|
|
{% set MESH_MIN = MESH_MIN.split(",")|map('float')|list %}
|
|
{% set MESH_MAX = MESH_MAX.split(",")|map('float')|list %}
|
|
{% set MESH_MIN_NEW = (MESH_MIN[0] + x_offset, MESH_MIN[1] + y_offset) %}
|
|
{% set MESH_MAX_NEW = (MESH_MAX[0] + x_offset, MESH_MAX[1] + y_offset) %}
|
|
{action_respond_info(
|
|
"Relocating print origin from (%.3f,%.3f) "|format(*MESH_MIN) +
|
|
"to (%.3f,%.3f)"|format(*MESH_MIN_NEW))}
|
|
{% set MESH_MIN = (MESH_MIN_NEW[0], MESH_MIN_NEW[1])|join(',') %}
|
|
{% set MESH_MAX = (MESH_MAX_NEW[0], MESH_MAX_NEW[1])|join(',') %}
|
|
PRINT_START_SET PRINT_OFFSET={"%d,%d" % (x_offset,y_offset)}
|
|
{% endif %}
|
|
|
|
{% set EXTRUDER = print.EXTRUDER|int %}
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
{% set start_level_bed_at_temp = km.start_level_bed_at_temp and
|
|
not printer.bed_mesh.profile_name %}
|
|
{% set start_home_z_at_temp = km.start_home_z_at_temp and
|
|
not print.BED_AT_TARGET|int %}
|
|
{% set actions_at_temp = start_level_bed_at_temp or
|
|
km.start_quad_gantry_level_at_temp or
|
|
km.start_z_tilt_adjust_at_temp or
|
|
start_home_z_at_temp %}
|
|
{% if actions_at_temp %}
|
|
{% if km.start_extruder_probing_temp > 0 %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=extruder_heating RESET_STACK=1
|
|
_KM_PARK_IF_NEEDED HEATER={printer.toolhead.extruder} RANGE=2
|
|
M109 R{km.start_extruder_probing_temp}
|
|
{% else %}
|
|
M104 S{EXTRUDER} # set the final extruder target temperature
|
|
{% endif %}
|
|
{% if km.start_z_tilt_adjust_at_temp %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=calibrating_z RESET_STACK=1
|
|
Z_TILT_ADJUST
|
|
{% endif %}
|
|
{% if km.start_quad_gantry_level_at_temp %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=leveling_gantry RESET_STACK=1
|
|
QUAD_GANTRY_LEVEL
|
|
{% endif %}
|
|
{% if start_home_z_at_temp %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=homing RESET_STACK=1
|
|
G28 Z # Re-home only the Z axis now that the bed has stabilized.
|
|
{% endif %}
|
|
{% if start_level_bed_at_temp %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=meshing RESET_STACK=1
|
|
_km_mesh_if_needed {% if MESH_MIN %} MESH_MIN={MESH_MIN}{% endif
|
|
%}{% if MESH_MAX %} MESH_MAX={MESH_MAX}{% endif %}
|
|
{% endif %}
|
|
{% if km.start_extruder_probing_temp > 0 %}
|
|
M104 S{EXTRUDER} # set the final extruder target temperature
|
|
{% endif %}
|
|
G4
|
|
{% endif %}
|
|
PRINT_START_SET PRINT_START_PHASE="extruder"
|
|
|
|
[gcode_macro _print_start_phase_extruder]
|
|
description: Inserted by slicer at start of print. Preheats the extruder.
|
|
Usage: See PRINT_START.
|
|
gcode:
|
|
_PRINT_START_PHASE_CHECK PHASE=extruder
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% set EXTRUDER = print.EXTRUDER|default(print.EXTRUDER_TEMP)|float %}
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
|
|
# Wait for extruder to reach temperature
|
|
{% if EXTRUDER > 0 %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=extruder_heating RESET_STACK=1
|
|
_KM_PARK_IF_NEEDED HEATER={printer.toolhead.extruder} RANGE=ABOVE
|
|
M109 S{EXTRUDER}
|
|
{% endif %}
|
|
PRINT_START_SET PRINT_START_PHASE="purge"
|
|
|
|
[gcode_macro _print_start_phase_purge]
|
|
description: Inserted by slicer at start of print. Generates purge lines.
|
|
Usage: See PRINT_START.
|
|
gcode:
|
|
_PRINT_START_PHASE_CHECK PHASE=purge
|
|
# Apply the offset for bed placement randomization.
|
|
_KM_APPLY_PRINT_OFFSET
|
|
# apply Z offset for bed surface (just in case it was reset).
|
|
_APPLY_BED_SURFACE_OFFSET
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% set MESH_MIN = print.MESH_MIN|default(None) %}
|
|
{% set MESH_MAX = print.MESH_MAX|default(None) %}
|
|
{% set NOZZLE_SIZE = print.NOZZLE_SIZE|default(print.NOZZLE_SIZE)|
|
|
default(printer.configfile.settings.extruder.nozzle_diameter)|float %}
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
{% if km.start_purge_length > 0.0 and printer.extruder.can_extrude %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=purging RESET_STACK=1
|
|
DRAW_PURGE_LINE WIDTH="{NOZZLE_SIZE * 1.25}" HEIGHT="{NOZZLE_SIZE * 0.625
|
|
}"{% if MESH_MIN %} PRINT_MIN={MESH_MIN}{% endif
|
|
%}{% if MESH_MAX %} PRINT_MAX={MESH_MAX}{% endif %}
|
|
{% endif %}
|
|
PRINT_START_SET PRINT_START_PHASE="printing"
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=printing RESET_STACK=1
|
|
|
|
[gcode_macro _km_park_if_needed]
|
|
description: Parks the extruder if the current temperature of the supplied
|
|
heater is not within the specified target range.
|
|
Usage: _KM_PARK_IF_NEEDED HEATER=<heater> RANGE=[<percentage>|ABOVE|BELOW]
|
|
gcode:
|
|
# This needs to get called as its own macro to get the current temp evaluated.
|
|
{% set HEATER = params.HEATER if params.HEATER in
|
|
printer.heaters.available_heaters else
|
|
("heater_generic " ~ params.HEATER) %}
|
|
{% set RANGE = (params.RANGE|default(1))|string|upper %}
|
|
|
|
{% if printer[HEATER].target %}
|
|
{% if RANGE == "ABOVE" %}
|
|
{% if printer[HEATER].temperature < printer[HEATER].target %}
|
|
PARK
|
|
{% endif %}
|
|
{% elif RANGE == "BELOW" %}
|
|
{% if printer[HEATER].temperature > printer[HEATER].target %}
|
|
PARK
|
|
{% endif %}
|
|
{% elif (printer[HEATER].temperature - printer[HEATER].target)|abs >
|
|
(printer[HEATER].target * RANGE|float * 0.01)|abs %}
|
|
PARK
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
[gcode_macro _km_apply_print_offset]
|
|
variable_offset: []
|
|
gcode:
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% if params.RESET|default(0)|int and offset and
|
|
not printer["gcode_macro _km_save_state"].is_ephemeral%}
|
|
{% set PRINT_OFFSET = [offset.pop(0) * -1, offset.pop() * -1] %}
|
|
{% elif print.PRINT_OFFSET and not offset and
|
|
not printer["gcode_macro _km_save_state"].is_ephemeral %}
|
|
{% set PRINT_OFFSET = print.PRINT_OFFSET.split(",")|map('float')|list %}
|
|
{% set dummy = offset.extend(PRINT_OFFSET) %}
|
|
{% endif %}
|
|
|
|
{% if PRINT_OFFSET %}
|
|
_KM_SET_GCODE_OFFSET_BASE {"X_ADJUST=%.2f Y_ADJUST=%.2f"|
|
|
format(*PRINT_OFFSET)}
|
|
{% endif %}
|
|
|
|
[gcode_macro _km_mesh_if_needed]
|
|
gcode:
|
|
# TODO: Instead of blindly using the loaded mesh we could probe a few key
|
|
# points on the saved grid. If those probes show that the saved grid is no
|
|
# longer in tolerance we could just run BED_MESH_CALIBRATE_FAST anyway.
|
|
{% if not printer.bed_mesh.profile_name %}
|
|
BED_MESH_CALIBRATE_FAST {rawparams}
|
|
{% endif %}
|
|
|
|
[gcode_macro print_start_set]
|
|
description: Inserted by slicer to set values used by PRINT_START.
|
|
Usage: PRINT_START_SET <VARIABLE>=<value>
|
|
variable_print: {}
|
|
gcode:
|
|
{%for k in params %}
|
|
{% set dummy = print.__setitem__(k|upper, params[k]) %}
|
|
{% endfor %}
|
|
|
|
[gcode_macro _print_start_phase_check]
|
|
gcode:
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
{% set PRINT_START_PHASE = print.PRINT_START_PHASE|default("none") %}
|
|
{% if PRINT_START_PHASE != params.PHASE %}
|
|
# Reset the phases manually just to be sure.
|
|
SET_GCODE_VARIABLE MACRO=print_start_set VARIABLE=print VALUE="{{}}"
|
|
{% if params.PHASE != 'none' %}
|
|
{% set error = "PRINT_START phase error. Expected '%s' but found '%s'" %
|
|
(params.PHASE, PRINT_START_PHASE) %}
|
|
# Do the cancel manually if we're not confident it will fire.
|
|
{% if not 'virtual_sdcard' in printer or
|
|
not printer.virtual_sdcard.is_active or 'CANCEL_PRINT' not in
|
|
printer.configfile.settings.virtual_sdcard.on_error_gcode|
|
|
default("")|upper %}
|
|
{action_respond_info(error)}
|
|
CANCEL_PRINT
|
|
{% else %}
|
|
{action_raise_error(error)}
|
|
{% endif %}
|
|
{% else %}
|
|
{ action_respond_info("Expected phase '%s' but found '%s'. Resetting."
|
|
% (params.PHASE, PRINT_START_PHASE)) }
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
[gcode_macro print_end]
|
|
description: Inserted by slicer at end of print.
|
|
Usage: PRINT_END
|
|
gcode:
|
|
_KM_CHECK_IS_PRINTING
|
|
M400
|
|
_PRINT_END_INNER
|
|
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
|
|
{% if km.start_clear_adjustments_at_end != 0 %}
|
|
RESET_HEATER_SCALING
|
|
RESET_FAN_SCALING
|
|
M220 S100
|
|
M221 S100
|
|
{% endif %}
|
|
_RESET_LAYER_GCODE
|
|
_RESET_VELOCITY_LIMITS
|
|
TURN_OFF_HEATERS
|
|
M107; turn off fan
|
|
{% if printer.bed_mesh %}BED_MESH_CLEAR{% endif %}
|
|
# Park the toolhead and present the bed
|
|
{% if printer.toolhead.homed_axes|lower == "xyz" %}
|
|
PARK Y="{km.start_end_park_y}"
|
|
{% endif %}
|
|
M84 ; disable steppers
|
|
CLEAR_PAUSE
|
|
SET_GCODE_VARIABLE MACRO=print_start_set VARIABLE=print VALUE="{{}}"
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=ready RESET_STACK=1
|
|
|
|
[gcode_macro _print_end_inner]
|
|
variable_cancelled: False
|
|
gcode:
|
|
SET_GCODE_VARIABLE MACRO=_print_end_inner VARIABLE=cancelled VALUE="{False}"
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
{% set toolhead = printer.toolhead %}
|
|
{% set origin = printer.gcode_move.homing_origin%}
|
|
{% set max_x = km.print_max[0] - origin.x %}
|
|
{% set max_y = km.print_max[1] - origin.y %}
|
|
{% set max_z = toolhead.axis_maximum.z - origin.z %}
|
|
|
|
{% if not cancelled %}
|
|
_KM_PRINT_STATUS ACTION=CHANGE STATUS=completing
|
|
{% endif %}
|
|
|
|
{% if printer.extruder.can_extrude %}
|
|
# Wipe if we're not cancelling a paused print.
|
|
{% if not printer.pause_resume.is_paused and not cancelled and
|
|
toolhead.homed_axes|lower == "xyz" %}
|
|
{% set x_safe = (max_x - toolhead.position.x, 2.0)|min %}
|
|
{% set y_safe = (max_y - toolhead.position.y, 2.0)|min %}
|
|
{% set z_safe = (max_z - toolhead.position.z, 2.0)|min %}
|
|
G91
|
|
G0 Z{z_safe} E-1.0 F{km.travel_speed_z * 2} ; move nozzle up
|
|
G0 X{x_safe} Y{y_safe} E-1.0 F{km.travel_speed_xy} ; remove stringing
|
|
# Remove the offset now that we're done.
|
|
_KM_APPLY_PRINT_OFFSET RESET=1
|
|
{% endif %}
|
|
|
|
# Small retract to prevent ooze
|
|
G92 E0
|
|
G1 E{"%.2f" % ((0, 2 - km.load_priming_length / 4)|min)} F1200
|
|
M400
|
|
{% endif %}
|
|
|
|
[gcode_macro _km_check_is_printing]
|
|
variable_debug_state: False # Disables print state check for debugging.
|
|
description: Throws an error if print is not currently in progress.
|
|
gcode:
|
|
{% if not debug_state and
|
|
printer.idle_timeout.state|string != "Printing" and
|
|
not (printer.virtual_sdcard|default({})).is_active|default(False) and
|
|
not printer.pause_resume.is_paused %}
|
|
{ action_raise_error("No active print.") }
|
|
{% endif %}
|
|
|
|
[gcode_macro _km_check_and_set_print_bounds]
|
|
description: Validates all print bounds and caches their values.
|
|
gcode:
|
|
{% set km = printer["gcode_macro _km_globals"] %}
|
|
{% set print = printer["gcode_macro print_start_set"].print %}
|
|
|
|
# Check the mesh bounds.
|
|
{% if print.MESH_MIN %}
|
|
{% set MESH_MIN = print.MESH_MIN.split(",")|map('float')|list %}
|
|
{% set MESH_MAX = print.MESH_MAX.split(",")|map('float')|list %}
|
|
{%if MESH_MIN[0] < km.print_min[0] or MESH_MIN[1] < km.print_min[1] %}
|
|
{action_raise_error("MESH_MIN %s is outside the printable bounds %s" %
|
|
(MESH_MIN|string, km.print_min|string))}
|
|
{%elif MESH_MAX[0] > km.print_max[0] or MESH_MAX[1] > km.print_max[1] %}
|
|
{action_raise_error("MESH_MAX %s is outside the printable bounds %s" %
|
|
(MESH_MAX|string, km.print_max|string))}
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
# Find all the model bounds (including any bounds passed in).
|
|
{% set points = [] %}
|
|
{% if print.MODEL_MIN or print.MODEL_MAX %}
|
|
{% set MODEL_MIN = print.MODEL_MIN.split(",")|map('float')|list %}
|
|
{% set MODEL_MAX = print.MODEL_MAX.split(",")|map('float')|list %}
|
|
{% set points = [MODEL_MIN, MODEL_MAX] %}
|
|
{% endif %}
|
|
{% if (printer.exclude_object|default({})).objects %}
|
|
{% set points = printer.exclude_object.objects|selectattr('polygon')|
|
|
map(attribute='polygon')|sum(start=points) %}
|
|
{% set points_len = points|length %}
|
|
{% if points_len >= 2 %}
|
|
{% set x_coords = (points|map(attribute=0)|sort|list)[0::points_len-1] %}
|
|
{% set y_coords = (points|map(attribute=1)|sort|list)[0::points_len-1] %}
|
|
{% set MODEL_MIN = (x_coords[0],y_coords[0])|map('float')|list %}
|
|
{% set MODEL_MAX = (x_coords[1],y_coords[1])|map('float')|list %}
|
|
PRINT_START_SET MODEL_MIN="{MODEL_MIN|join(',')
|
|
}" MODEL_MAX="{MODEL_MAX|join(',')}"
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
{% if MODEL_MIN %}
|
|
# Check the model bounds.
|
|
{% if MODEL_MIN[0] < km.print_min[0] or MODEL_MIN[1] < km.print_min[1] %}
|
|
{action_raise_error("MODEL_MIN %s is outside the printable bounds %s" %
|
|
(MODEL_MIN|string, km.print_min|string))}
|
|
{% elif MODEL_MAX[0] > km.print_max[0] or MODEL_MAX[1] > km.print_max[1] %}
|
|
{action_raise_error("MODEL_MAX %s is outside the printable bounds %s" %
|
|
(MODEL_MAX|string, km.print_max|string))}
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
# Set the PRINT_LIMITS
|
|
{% if MESH_MIN and MODEL_MIN %}
|
|
PRINT_START_SET PRINT_MIN="{((MODEL_MIN[0],MESH_MIN[0])|min,
|
|
(MODEL_MIN[1],MESH_MIN[1])|min)|join(',')
|
|
}" PRINT_MAX="{((MODEL_MAX[0],MESH_MAX[0])|max,
|
|
(MODEL_MAX[1],MESH_MAX[1])|max)|join(',')}"
|
|
{% else %}
|
|
PRINT_START_SET PRINT_MIN="{km.print_min|join(',')
|
|
}" PRINT_MAX="{km.print_max|join(',')}"
|
|
{% endif %}
|