mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-15 13:55:57 +08:00
Merge branch 'master' into libArachne_rebased
This commit is contained in:
commit
bbfbadc981
@ -30,24 +30,16 @@ configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desk
|
||||
configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY)
|
||||
|
||||
|
||||
# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
|
||||
# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
|
||||
# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||
# Use FindPythonInterp and FindPythonLibs for CMake <3.12
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
# FIXME: The new FindPython3 finds the system's Python3.6 reather than the Python3.5 that we built for Cura's environment.
|
||||
# So we're using the old method here, with FindPythonInterp for now.
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
|
||||
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
|
||||
set(Python3_VERSION ${PYTHON_VERSION_STRING})
|
||||
set(Python3_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
|
||||
set(Python3_VERSION_MINOR ${PYTHON_VERSION_MINOR})
|
||||
set(Python3_VERSION_PATCH ${PYTHON_VERSION_PATCH})
|
||||
else()
|
||||
# Use FindPython3 for CMake >=3.12
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
|
||||
endif()
|
||||
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
|
||||
set(Python3_VERSION ${PYTHON_VERSION_STRING})
|
||||
set(Python3_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
|
||||
set(Python3_VERSION_MINOR ${PYTHON_VERSION_MINOR})
|
||||
set(Python3_VERSION_PATCH ${PYTHON_VERSION_PATCH})
|
||||
|
||||
if(NOT ${URANIUM_DIR} STREQUAL "")
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${URANIUM_DIR}/cmake")
|
||||
|
@ -4,18 +4,11 @@
|
||||
include(CTest)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
|
||||
# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
|
||||
# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||
# Use FindPythonInterp and FindPythonLibs for CMake <3.12
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
# FIXME: The new FindPython3 finds the system's Python3.6 reather than the Python3.5 that we built for Cura's environment.
|
||||
# So we're using the old method here, with FindPythonInterp for now.
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
|
||||
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
else()
|
||||
# Use FindPython3 for CMake >=3.12
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
|
||||
endif()
|
||||
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
|
||||
add_custom_target(test-verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
|
||||
|
||||
|
@ -122,6 +122,8 @@ class ContainerManager(QObject):
|
||||
root_material.setMetaDataEntry(entry_name, entry_value)
|
||||
if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
|
||||
root_material.metaDataChanged.emit(root_material)
|
||||
|
||||
cura.CuraApplication.CuraApplication.getInstance().getMachineManager().updateUponMaterialMetadataChange()
|
||||
return True
|
||||
|
||||
@pyqtSlot(str, result = str)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Any, cast, List, Optional
|
||||
from typing import Any, cast, List, Optional, Dict
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject
|
||||
|
||||
from UM.Application import Application
|
||||
@ -60,6 +60,8 @@ class CuraContainerStack(ContainerStack):
|
||||
import cura.CuraApplication #Here to prevent circular imports.
|
||||
self.setMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion)
|
||||
|
||||
self._settable_per_extruder_cache = {} # type: Dict[str, Any]
|
||||
|
||||
self.setDirty(False)
|
||||
|
||||
# This is emitted whenever the containersChanged signal from the ContainerStack base class is emitted.
|
||||
@ -387,6 +389,18 @@ class CuraContainerStack(ContainerStack):
|
||||
value = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
|
||||
return value
|
||||
|
||||
def getProperty(self, key: str, property_name: str, context = None) -> Any:
|
||||
if property_name == "settable_per_extruder":
|
||||
# Setable per extruder isn't a value that can ever change. So once we requested it once, we can just keep
|
||||
# that in memory.
|
||||
try:
|
||||
return self._settable_per_extruder_cache[key]
|
||||
except KeyError:
|
||||
self._settable_per_extruder_cache[key] = super().getProperty(key, property_name, context)
|
||||
return self._settable_per_extruder_cache[key]
|
||||
|
||||
return super().getProperty(key, property_name, context)
|
||||
|
||||
|
||||
class _ContainerIndexes:
|
||||
"""Private helper class to keep track of container positions and their types."""
|
||||
|
@ -16,13 +16,13 @@ from .ExtruderStack import ExtruderStack
|
||||
class CuraStackBuilder:
|
||||
"""Contains helper functions to create new machines."""
|
||||
|
||||
|
||||
@classmethod
|
||||
def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]:
|
||||
def createMachine(cls, name: str, definition_id: str, machine_extruder_count: Optional[int] = None) -> Optional[GlobalStack]:
|
||||
"""Create a new instance of a machine.
|
||||
|
||||
:param name: The name of the new machine.
|
||||
:param definition_id: The ID of the machine definition to use.
|
||||
:param machine_extruder_count: The number of extruders in the machine.
|
||||
|
||||
:return: The new global stack or None if an error occurred.
|
||||
"""
|
||||
@ -66,7 +66,14 @@ class CuraStackBuilder:
|
||||
Logger.logException("e", "Failed to create an extruder stack for position {pos}: {err}".format(pos = position, err = str(e)))
|
||||
return None
|
||||
|
||||
for new_extruder in new_global_stack.extruderList: # Only register the extruders if we're sure that all of them are correct.
|
||||
# If given, set the machine_extruder_count when creating the machine, or else the extruderList used bellow will
|
||||
# not return the correct extruder list (since by default, the machine_extruder_count is 1) in machines with
|
||||
# settable number of extruders.
|
||||
if machine_extruder_count and 0 <= machine_extruder_count <= len(extruder_dict):
|
||||
new_global_stack.setProperty("machine_extruder_count", "value", machine_extruder_count)
|
||||
|
||||
# Only register the extruders if we're sure that all of them are correct.
|
||||
for new_extruder in new_global_stack.extruderList:
|
||||
registry.addContainer(new_extruder)
|
||||
|
||||
# Register the global stack after the extruder stacks are created. This prevents the registry from adding another
|
||||
|
@ -131,13 +131,13 @@ class ExtruderStack(CuraContainerStack):
|
||||
if not self._next_stack:
|
||||
raise Exceptions.NoGlobalStackError("Extruder {id} is missing the next stack!".format(id = self.id))
|
||||
|
||||
if context is None:
|
||||
context = PropertyEvaluationContext()
|
||||
context.pushContainer(self)
|
||||
if context:
|
||||
context.pushContainer(self)
|
||||
|
||||
if not super().getProperty(key, "settable_per_extruder", context):
|
||||
result = self.getNextStack().getProperty(key, property_name, context)
|
||||
context.popContainer()
|
||||
if context:
|
||||
context.popContainer()
|
||||
return result
|
||||
|
||||
limit_to_extruder = super().getProperty(key, "limit_to_extruder", context)
|
||||
@ -150,13 +150,15 @@ class ExtruderStack(CuraContainerStack):
|
||||
try:
|
||||
result = self.getNextStack().extruderList[int(limit_to_extruder)].getProperty(key, property_name, context)
|
||||
if result is not None:
|
||||
context.popContainer()
|
||||
if context:
|
||||
context.popContainer()
|
||||
return result
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
result = super().getProperty(key, property_name, context)
|
||||
context.popContainer()
|
||||
if context:
|
||||
context.popContainer()
|
||||
return result
|
||||
|
||||
@override(CuraContainerStack)
|
||||
|
@ -211,9 +211,8 @@ class GlobalStack(CuraContainerStack):
|
||||
if not self.definition.findDefinitions(key = key):
|
||||
return None
|
||||
|
||||
if context is None:
|
||||
context = PropertyEvaluationContext()
|
||||
context.pushContainer(self)
|
||||
if context:
|
||||
context.pushContainer(self)
|
||||
|
||||
# Handle the "resolve" property.
|
||||
#TODO: Why the hell does this involve threading?
|
||||
@ -238,13 +237,15 @@ class GlobalStack(CuraContainerStack):
|
||||
if super().getProperty(key, "settable_per_extruder", context):
|
||||
result = self._extruders[str(limit_to_extruder)].getProperty(key, property_name, context)
|
||||
if result is not None:
|
||||
context.popContainer()
|
||||
if context:
|
||||
context.popContainer()
|
||||
return result
|
||||
else:
|
||||
Logger.log("e", "Setting {setting} has limit_to_extruder but is not settable per extruder!", setting = key)
|
||||
|
||||
result = super().getProperty(key, property_name, context)
|
||||
context.popContainer()
|
||||
if context:
|
||||
context.popContainer()
|
||||
return result
|
||||
|
||||
@override(ContainerStack)
|
||||
@ -256,8 +257,6 @@ class GlobalStack(CuraContainerStack):
|
||||
|
||||
raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!")
|
||||
|
||||
# protected:
|
||||
|
||||
# Determine whether or not we should try to get the "resolve" property instead of the
|
||||
# requested property.
|
||||
def _shouldResolve(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> bool:
|
||||
@ -265,6 +264,10 @@ class GlobalStack(CuraContainerStack):
|
||||
# Do not try to resolve anything but the "value" property
|
||||
return False
|
||||
|
||||
if not self.definition.getProperty(key, "resolve"):
|
||||
# If there isn't a resolve set for this setting, there isn't anything to do here.
|
||||
return False
|
||||
|
||||
current_thread = threading.current_thread()
|
||||
if key in self._resolving_settings[current_thread.name]:
|
||||
# To prevent infinite recursion, if getProperty is called with the same key as
|
||||
@ -273,10 +276,8 @@ class GlobalStack(CuraContainerStack):
|
||||
# track all settings that are being resolved.
|
||||
return False
|
||||
|
||||
setting_state = super().getProperty(key, "state", context = context)
|
||||
if setting_state is not None and setting_state != InstanceState.Default:
|
||||
# When the user has explicitly set a value, we should ignore any resolve and
|
||||
# just return that value.
|
||||
if self.hasUserValue(key):
|
||||
# When the user has explicitly set a value, we should ignore any resolve and just return that value.
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -1703,7 +1703,7 @@ class MachineManager(QObject):
|
||||
return False
|
||||
return global_stack.qualityChanges != empty_quality_changes_container
|
||||
|
||||
def _updateUponMaterialMetadataChange(self) -> None:
|
||||
def updateUponMaterialMetadataChange(self) -> None:
|
||||
if self._global_container_stack is None:
|
||||
return
|
||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||
|
@ -506,6 +506,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
# Now we know which material is in which extruder. Let's use that to sort the material_labels according to
|
||||
# their extruder position
|
||||
material_labels = [material_name for pos, material_name in sorted(materials_in_extruders_dict.items())]
|
||||
machine_extruder_count = self._getMachineExtruderCount()
|
||||
if machine_extruder_count:
|
||||
material_labels = material_labels[:machine_extruder_count]
|
||||
|
||||
num_visible_settings = 0
|
||||
try:
|
||||
@ -665,7 +668,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
# We need to create a new machine
|
||||
machine_name = self._container_registry.uniqueName(self._machine_info.name)
|
||||
|
||||
global_stack = CuraStackBuilder.createMachine(machine_name, self._machine_info.definition_id)
|
||||
# Printers with modifiable number of extruders (such as CFFF) will specify a machine_extruder_count in their
|
||||
# quality_changes file. If that's the case, take the extruder count into account when creating the machine
|
||||
# or else the extruderList will return only the first extruder, leading to missing non-global settings in
|
||||
# the other extruders.
|
||||
machine_extruder_count = self._getMachineExtruderCount() # type: Optional[int]
|
||||
global_stack = CuraStackBuilder.createMachine(machine_name, self._machine_info.definition_id, machine_extruder_count)
|
||||
if global_stack: # Only switch if creating the machine was successful.
|
||||
extruder_stack_dict = {str(position): extruder for position, extruder in enumerate(global_stack.extruderList)}
|
||||
|
||||
@ -922,6 +930,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
|
||||
self._machine_info.quality_changes_info.name = quality_changes_name
|
||||
|
||||
def _getMachineExtruderCount(self) -> Optional[int]:
|
||||
"""
|
||||
Extracts the machine extruder count from the definition_changes file of the printer. If it is not specified in
|
||||
the file, None is returned instead.
|
||||
|
||||
:return: The count of the machine's extruders
|
||||
"""
|
||||
machine_extruder_count = None
|
||||
if self._machine_info \
|
||||
and self._machine_info.definition_changes_info \
|
||||
and "values" in self._machine_info.definition_changes_info.parser \
|
||||
and "machine_extruder_count" in self._machine_info.definition_changes_info.parser["values"]:
|
||||
try:
|
||||
# Theoretically, if the machine_extruder_count is a setting formula (e.g. "=3"), this will produce a
|
||||
# value error and the project file loading will load the settings in the first extruder only.
|
||||
# This is not expected to happen though, since all machine definitions define the machine_extruder_count
|
||||
# as an integer.
|
||||
machine_extruder_count = int(self._machine_info.definition_changes_info.parser["values"]["machine_extruder_count"])
|
||||
except ValueError:
|
||||
Logger.log("w", "'machine_extruder_count' in file '{file_name}' is not a number."
|
||||
.format(file_name = self._machine_info.definition_changes_info.file_name))
|
||||
return machine_extruder_count
|
||||
|
||||
def _createNewQualityChanges(self, quality_type: str, intent_category: Optional[str], name: str, global_stack: GlobalStack, extruder_stack: Optional[ExtruderStack]) -> InstanceContainer:
|
||||
"""Helper class to create a new quality changes profile.
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
||||
# M207 S<mm> F<mm/m> - set the retract length <S> or feed rate <F>
|
||||
# M117 - output the current changes
|
||||
|
||||
from typing import List, Optional, Dict
|
||||
from typing import List, Dict
|
||||
from ..Script import Script
|
||||
import re
|
||||
|
||||
@ -336,7 +336,7 @@ class ChangeAtZ(Script):
|
||||
|
||||
caz_instance = ChangeAtZProcessor()
|
||||
|
||||
caz_instance.TargetValues = {}
|
||||
caz_instance.targetValues = {}
|
||||
|
||||
# copy over our settings to our change z class
|
||||
self.setIntSettingIfEnabled(caz_instance, "e1_Change_speed", "speed", "e2_speed")
|
||||
@ -352,23 +352,23 @@ class ChangeAtZ(Script):
|
||||
self.setFloatSettingIfEnabled(caz_instance, "caz_change_retractlength", "retractlength", "caz_retractlength")
|
||||
|
||||
# is this mod enabled?
|
||||
caz_instance.IsEnabled = self.getSettingValueByKey("caz_enabled")
|
||||
caz_instance.enabled = self.getSettingValueByKey("caz_enabled")
|
||||
|
||||
# are we emitting data to the LCD?
|
||||
caz_instance.IsDisplayingChangesToLcd = self.getSettingValueByKey("caz_output_to_display")
|
||||
caz_instance.displayChangesToLcd = self.getSettingValueByKey("caz_output_to_display")
|
||||
|
||||
# are we doing linear move retractions?
|
||||
caz_instance.IsLinearRetraction = self.getSettingValueByKey("caz_retractstyle") == "linear"
|
||||
caz_instance.linearRetraction = self.getSettingValueByKey("caz_retractstyle") == "linear"
|
||||
|
||||
# see if we're applying to a single layer or to all layers hence forth
|
||||
caz_instance.IsApplyToSingleLayer = self.getSettingValueByKey("c_behavior") == "single_layer"
|
||||
caz_instance.applyToSingleLayer = self.getSettingValueByKey("c_behavior") == "single_layer"
|
||||
|
||||
# used for easy reference of layer or height targeting
|
||||
caz_instance.IsTargetByLayer = self.getSettingValueByKey("a_trigger") == "layer_no"
|
||||
caz_instance.targetByLayer = self.getSettingValueByKey("a_trigger") == "layer_no"
|
||||
|
||||
# change our target based on what we're targeting
|
||||
caz_instance.TargetLayer = self.getIntSettingByKey("b_targetL", None)
|
||||
caz_instance.TargetZ = self.getFloatSettingByKey("b_targetZ", None)
|
||||
caz_instance.targetLayer = self.getIntSettingByKey("b_targetL", None)
|
||||
caz_instance.targetZ = self.getFloatSettingByKey("b_targetZ", None)
|
||||
|
||||
# run our script
|
||||
return caz_instance.execute(data)
|
||||
@ -388,7 +388,7 @@ class ChangeAtZ(Script):
|
||||
return
|
||||
|
||||
# set our value in the target settings
|
||||
caz_instance.TargetValues[target] = value
|
||||
caz_instance.targetValues[target] = value
|
||||
|
||||
# Sets the given TargetValue in the ChangeAtZ instance if the trigger is specified
|
||||
def setFloatSettingIfEnabled(self, caz_instance, trigger, target, setting):
|
||||
@ -405,7 +405,7 @@ class ChangeAtZ(Script):
|
||||
return
|
||||
|
||||
# set our value in the target settings
|
||||
caz_instance.TargetValues[target] = value
|
||||
caz_instance.targetValues[target] = value
|
||||
|
||||
# Returns the given settings value as an integer or the default if it cannot parse it
|
||||
def getIntSettingByKey(self, key, default):
|
||||
@ -430,13 +430,13 @@ class ChangeAtZ(Script):
|
||||
class GCodeCommand:
|
||||
|
||||
# The GCode command itself (ex: G10)
|
||||
Command = None,
|
||||
command = None,
|
||||
|
||||
# Contains any arguments passed to the command. The key is the argument name, the value is the value of the argument.
|
||||
Arguments = {}
|
||||
arguments = {}
|
||||
|
||||
# Contains the components of the command broken into pieces
|
||||
Components = []
|
||||
components = []
|
||||
|
||||
# Constructor. Sets up defaults
|
||||
def __init__(self):
|
||||
@ -468,10 +468,10 @@ class GCodeCommand:
|
||||
return None
|
||||
|
||||
# stores all the components of the command within the class for later
|
||||
command.Components = command_pieces
|
||||
command.components = command_pieces
|
||||
|
||||
# set the actual command
|
||||
command.Command = command_pieces[0]
|
||||
command.command = command_pieces[0]
|
||||
|
||||
# stop here if we don't have any parameters
|
||||
if len(command_pieces) == 1:
|
||||
@ -488,15 +488,15 @@ class GCodeCommand:
|
||||
linear_command = GCodeCommand.getFromLine(line)
|
||||
|
||||
# if it's not a linear move, we don't care
|
||||
if linear_command is None or (linear_command.Command != "G0" and linear_command.Command != "G1"):
|
||||
if linear_command is None or (linear_command.command != "G0" and linear_command.command != "G1"):
|
||||
return None
|
||||
|
||||
# convert our values to floats (or defaults)
|
||||
linear_command.Arguments["F"] = linear_command.getArgumentAsFloat("F", None)
|
||||
linear_command.Arguments["X"] = linear_command.getArgumentAsFloat("X", None)
|
||||
linear_command.Arguments["Y"] = linear_command.getArgumentAsFloat("Y", None)
|
||||
linear_command.Arguments["Z"] = linear_command.getArgumentAsFloat("Z", None)
|
||||
linear_command.Arguments["E"] = linear_command.getArgumentAsFloat("E", None)
|
||||
linear_command.arguments["F"] = linear_command.getArgumentAsFloat("F", None)
|
||||
linear_command.arguments["X"] = linear_command.getArgumentAsFloat("X", None)
|
||||
linear_command.arguments["Y"] = linear_command.getArgumentAsFloat("Y", None)
|
||||
linear_command.arguments["Z"] = linear_command.getArgumentAsFloat("Z", None)
|
||||
linear_command.arguments["E"] = linear_command.getArgumentAsFloat("E", None)
|
||||
|
||||
# return our new command
|
||||
return linear_command
|
||||
@ -508,11 +508,11 @@ class GCodeCommand:
|
||||
self.parseArguments()
|
||||
|
||||
# if we don't have the parameter, return the default
|
||||
if name not in self.Arguments:
|
||||
if name not in self.arguments:
|
||||
return default
|
||||
|
||||
# otherwise return the value
|
||||
return self.Arguments[name]
|
||||
return self.arguments[name]
|
||||
|
||||
# Gets the value of a parameter as a float or returns the default
|
||||
def getArgumentAsFloat(self, name: str, default: float = None) -> float:
|
||||
@ -593,14 +593,14 @@ class GCodeCommand:
|
||||
def parseArguments(self):
|
||||
|
||||
# stop here if we don't have any remaining components
|
||||
if len(self.Components) <= 1:
|
||||
if len(self.components) <= 1:
|
||||
return None
|
||||
|
||||
# iterate and index all of our parameters, skip the first component as it's the command
|
||||
for i in range(1, len(self.Components)):
|
||||
for i in range(1, len(self.components)):
|
||||
|
||||
# get our component
|
||||
component = self.Components[i]
|
||||
component = self.components[i]
|
||||
|
||||
# get the first character of the parameter, which is the name
|
||||
component_name = component[0]
|
||||
@ -613,10 +613,10 @@ class GCodeCommand:
|
||||
component_value = component[1:]
|
||||
|
||||
# index the argument
|
||||
self.Arguments[component_name] = component_value
|
||||
self.arguments[component_name] = component_value
|
||||
|
||||
# clear the components to we don't process again
|
||||
self.Components = []
|
||||
self.components = []
|
||||
|
||||
# Easy function for replacing any GCODE parameter variable in a given GCODE command
|
||||
@staticmethod
|
||||
@ -625,8 +625,8 @@ class GCodeCommand:
|
||||
|
||||
# Resets the model back to defaults
|
||||
def reset(self):
|
||||
self.Command = None
|
||||
self.Arguments = {}
|
||||
self.command = None
|
||||
self.arguments = {}
|
||||
|
||||
|
||||
# The primary ChangeAtZ class that does all the gcode editing. This was broken out into an
|
||||
@ -634,55 +634,55 @@ class GCodeCommand:
|
||||
class ChangeAtZProcessor:
|
||||
|
||||
# Holds our current height
|
||||
CurrentZ = None
|
||||
currentZ = None
|
||||
|
||||
# Holds our current layer number
|
||||
CurrentLayer = None
|
||||
currentLayer = None
|
||||
|
||||
# Indicates if we're only supposed to apply our settings to a single layer or multiple layers
|
||||
IsApplyToSingleLayer = False
|
||||
applyToSingleLayer = False
|
||||
|
||||
# Indicates if this should emit the changes as they happen to the LCD
|
||||
IsDisplayingChangesToLcd = False
|
||||
displayChangesToLcd = False
|
||||
|
||||
# Indicates that this mod is still enabled (or not)
|
||||
IsEnabled = True
|
||||
enabled = True
|
||||
|
||||
# Indicates if we're processing inside the target layer or not
|
||||
IsInsideTargetLayer = False
|
||||
insideTargetLayer = False
|
||||
|
||||
# Indicates if we have restored the previous values from before we started our pass
|
||||
IsLastValuesRestored = False
|
||||
lastValuesRestored = False
|
||||
|
||||
# Indicates if the user has opted for linear move retractions or firmware retractions
|
||||
IsLinearRetraction = True
|
||||
linearRetraction = True
|
||||
|
||||
# Indicates if we're targetting by layer or height value
|
||||
IsTargetByLayer = True
|
||||
targetByLayer = True
|
||||
|
||||
# Indicates if we have injected our changed values for the given layer yet
|
||||
IsTargetValuesInjected = False
|
||||
targetValuesInjected = False
|
||||
|
||||
# Holds the last extrusion value, used with detecting when a retraction is made
|
||||
LastE = None
|
||||
lastE = None
|
||||
|
||||
# An index of our gcodes which we're monitoring
|
||||
LastValues = {}
|
||||
lastValues = {}
|
||||
|
||||
# The detected layer height from the gcode
|
||||
LayerHeight = None
|
||||
layerHeight = None
|
||||
|
||||
# The target layer
|
||||
TargetLayer = None
|
||||
targetLayer = None
|
||||
|
||||
# Holds the values the user has requested to change
|
||||
TargetValues = {}
|
||||
targetValues = {}
|
||||
|
||||
# The target height in mm
|
||||
TargetZ = None
|
||||
targetZ = None
|
||||
|
||||
# Used to track if we've been inside our target layer yet
|
||||
WasInsideTargetLayer = False
|
||||
wasInsideTargetLayer = False
|
||||
|
||||
# boots up the class with defaults
|
||||
def __init__(self):
|
||||
@ -692,7 +692,7 @@ class ChangeAtZProcessor:
|
||||
def execute(self, data):
|
||||
|
||||
# short cut the whole thing if we're not enabled
|
||||
if not self.IsEnabled:
|
||||
if not self.enabled:
|
||||
return data
|
||||
|
||||
# our layer cursor
|
||||
@ -750,14 +750,14 @@ class ChangeAtZProcessor:
|
||||
|
||||
# for each of our target values, get the value to restore
|
||||
# no point in restoring values we haven't changed
|
||||
for key in self.TargetValues:
|
||||
for key in self.targetValues:
|
||||
|
||||
# skip target values we can't restore
|
||||
if key not in self.LastValues:
|
||||
if key not in self.lastValues:
|
||||
continue
|
||||
|
||||
# save into our changed
|
||||
changed[key] = self.LastValues[key]
|
||||
changed[key] = self.lastValues[key]
|
||||
|
||||
# return our collection of changed values
|
||||
return changed
|
||||
@ -766,7 +766,7 @@ class ChangeAtZProcessor:
|
||||
def getDisplayChangesFromValues(self, values: Dict[str, any]) -> str:
|
||||
|
||||
# stop here if we're not outputting data
|
||||
if not self.IsDisplayingChangesToLcd:
|
||||
if not self.displayChangesToLcd:
|
||||
return ""
|
||||
|
||||
# will hold all the default settings for the target layer
|
||||
@ -833,7 +833,7 @@ class ChangeAtZProcessor:
|
||||
def getTargetDisplayValues(self) -> str:
|
||||
|
||||
# convert our target values to something we can output
|
||||
return self.getDisplayChangesFromValues(self.TargetValues)
|
||||
return self.getDisplayChangesFromValues(self.targetValues)
|
||||
|
||||
# Builds the the relevant GCODE lines from the given collection of values
|
||||
def getCodeFromValues(self, values: Dict[str, any]) -> str:
|
||||
@ -898,7 +898,7 @@ class ChangeAtZProcessor:
|
||||
# set retract rate
|
||||
if "retractfeedrate" in values:
|
||||
|
||||
if self.IsLinearRetraction:
|
||||
if self.linearRetraction:
|
||||
codes.append(";RETRACTFEEDRATE " + str(values["retractfeedrate"] * 60) + "")
|
||||
else:
|
||||
codes.append("M207 F" + str(values["retractfeedrate"] * 60) + "")
|
||||
@ -906,7 +906,7 @@ class ChangeAtZProcessor:
|
||||
# set retract length
|
||||
if "retractlength" in values:
|
||||
|
||||
if self.IsLinearRetraction:
|
||||
if self.linearRetraction:
|
||||
codes.append(";RETRACTLENGTH " + str(values["retractlength"]) + "")
|
||||
else:
|
||||
codes.append("M207 S" + str(values["retractlength"]) + "")
|
||||
@ -923,19 +923,19 @@ class ChangeAtZProcessor:
|
||||
def getInjectCode(self) -> str:
|
||||
|
||||
# if we're now outside of our target layer and haven't restored our last values, do so now
|
||||
if not self.IsInsideTargetLayer and self.WasInsideTargetLayer and not self.IsLastValuesRestored:
|
||||
if not self.insideTargetLayer and self.wasInsideTargetLayer and not self.lastValuesRestored:
|
||||
|
||||
# mark that we've injected the last values
|
||||
self.IsLastValuesRestored = True
|
||||
self.lastValuesRestored = True
|
||||
|
||||
# inject the defaults
|
||||
return self.getLastValues() + "\n" + self.getLastDisplayValues()
|
||||
|
||||
# if we're inside our target layer but haven't added our values yet, do so now
|
||||
if self.IsInsideTargetLayer and not self.IsTargetValuesInjected:
|
||||
if self.insideTargetLayer and not self.targetValuesInjected:
|
||||
|
||||
# mark that we've injected the target values
|
||||
self.IsTargetValuesInjected = True
|
||||
self.targetValuesInjected = True
|
||||
|
||||
# inject the defaults
|
||||
return self.getTargetValues() + "\n" + self.getTargetDisplayValues()
|
||||
@ -960,35 +960,35 @@ class ChangeAtZProcessor:
|
||||
def getTargetValues(self) -> str:
|
||||
|
||||
# build the gcode to change our current values
|
||||
return self.getCodeFromValues(self.TargetValues)
|
||||
return self.getCodeFromValues(self.targetValues)
|
||||
|
||||
# Determines if the current line is at or below the target required to start modifying
|
||||
def isTargetLayerOrHeight(self) -> bool:
|
||||
|
||||
# target selected by layer no.
|
||||
if self.IsTargetByLayer:
|
||||
if self.targetByLayer:
|
||||
|
||||
# if we don't have a current layer, we're not there yet
|
||||
if self.CurrentLayer is None:
|
||||
if self.currentLayer is None:
|
||||
return False
|
||||
|
||||
# if we're applying to a single layer, stop if our layer is not identical
|
||||
if self.IsApplyToSingleLayer:
|
||||
return self.CurrentLayer == self.TargetLayer
|
||||
if self.applyToSingleLayer:
|
||||
return self.currentLayer == self.targetLayer
|
||||
else:
|
||||
return self.CurrentLayer >= self.TargetLayer
|
||||
return self.currentLayer >= self.targetLayer
|
||||
|
||||
else:
|
||||
|
||||
# if we don't have a current Z, we're not there yet
|
||||
if self.CurrentZ is None:
|
||||
if self.currentZ is None:
|
||||
return False
|
||||
|
||||
# if we're applying to a single layer, stop if our Z is not identical
|
||||
if self.IsApplyToSingleLayer:
|
||||
return self.CurrentZ == self.TargetZ
|
||||
if self.applyToSingleLayer:
|
||||
return self.currentZ == self.targetZ
|
||||
else:
|
||||
return self.CurrentZ >= self.TargetZ
|
||||
return self.currentZ >= self.targetZ
|
||||
|
||||
# Marks any current ChangeZ layer defaults in the layer for deletion
|
||||
@staticmethod
|
||||
@ -999,7 +999,7 @@ class ChangeAtZProcessor:
|
||||
def processLayerHeight(self, line: str):
|
||||
|
||||
# stop here if we haven't entered a layer yet
|
||||
if self.CurrentLayer is None:
|
||||
if self.currentLayer is None:
|
||||
return
|
||||
|
||||
# get our gcode command
|
||||
@ -1010,7 +1010,7 @@ class ChangeAtZProcessor:
|
||||
return
|
||||
|
||||
# stop here if this isn't a linear move command
|
||||
if command.Command != "G0" and command.Command != "G1":
|
||||
if command.command != "G0" and command.command != "G1":
|
||||
return
|
||||
|
||||
# get our value from the command
|
||||
@ -1021,15 +1021,15 @@ class ChangeAtZProcessor:
|
||||
return
|
||||
|
||||
# stop if there's no change
|
||||
if current_z == self.CurrentZ:
|
||||
if current_z == self.currentZ:
|
||||
return
|
||||
|
||||
# set our current Z value
|
||||
self.CurrentZ = current_z
|
||||
self.currentZ = current_z
|
||||
|
||||
# if we don't have a layer height yet, set it based on the current Z value
|
||||
if self.LayerHeight is None:
|
||||
self.LayerHeight = self.CurrentZ
|
||||
if self.layerHeight is None:
|
||||
self.layerHeight = self.currentZ
|
||||
|
||||
# Grabs the current layer number
|
||||
def processLayerNumber(self, line: str):
|
||||
@ -1042,11 +1042,11 @@ class ChangeAtZProcessor:
|
||||
current_layer = GCodeCommand.getDirectArgumentAsInt(line, ";LAYER:", None)
|
||||
|
||||
# this should never happen, but if our layer number hasn't changed, stop here
|
||||
if current_layer == self.CurrentLayer:
|
||||
if current_layer == self.currentLayer:
|
||||
return
|
||||
|
||||
# update our current layer
|
||||
self.CurrentLayer = current_layer
|
||||
self.currentLayer = current_layer
|
||||
|
||||
# Makes any linear move changes and also injects either target or restored values depending on the plugin state
|
||||
def processLine(self, line: str) -> str:
|
||||
@ -1059,10 +1059,10 @@ class ChangeAtZProcessor:
|
||||
|
||||
# if we're not inside the target layer, simply read the any
|
||||
# settings we can and revert any ChangeAtZ deletions
|
||||
if not self.IsInsideTargetLayer:
|
||||
if not self.insideTargetLayer:
|
||||
|
||||
# read any settings if we haven't hit our target layer yet
|
||||
if not self.WasInsideTargetLayer:
|
||||
if not self.wasInsideTargetLayer:
|
||||
self.processSetting(line)
|
||||
|
||||
# if we haven't hit our target yet, leave the defaults as is (unmark them for deletion)
|
||||
@ -1074,7 +1074,7 @@ class ChangeAtZProcessor:
|
||||
modified_gcode += self.getInjectCode()
|
||||
|
||||
# modify our command if we're still inside our target layer, otherwise pass unmodified
|
||||
if self.IsInsideTargetLayer:
|
||||
if self.insideTargetLayer:
|
||||
modified_gcode += self.processLinearMove(line) + "\n"
|
||||
else:
|
||||
modified_gcode += line + "\n"
|
||||
@ -1104,11 +1104,11 @@ class ChangeAtZProcessor:
|
||||
return line
|
||||
|
||||
# get our linear move parameters
|
||||
feed_rate = linear_command.Arguments["F"]
|
||||
x_coord = linear_command.Arguments["X"]
|
||||
y_coord = linear_command.Arguments["Y"]
|
||||
z_coord = linear_command.Arguments["Z"]
|
||||
extrude_length = linear_command.Arguments["E"]
|
||||
feed_rate = linear_command.arguments["F"]
|
||||
x_coord = linear_command.arguments["X"]
|
||||
y_coord = linear_command.arguments["Y"]
|
||||
z_coord = linear_command.arguments["Z"]
|
||||
extrude_length = linear_command.arguments["E"]
|
||||
|
||||
# set our new line to our old line
|
||||
new_line = line
|
||||
@ -1124,7 +1124,7 @@ class ChangeAtZProcessor:
|
||||
new_line = self.processPrintSpeed(feed_rate, new_line)
|
||||
|
||||
# set our current extrude position
|
||||
self.LastE = extrude_length if extrude_length is not None else self.LastE
|
||||
self.lastE = extrude_length if extrude_length is not None else self.lastE
|
||||
|
||||
# if no changes have been made, stop here
|
||||
if new_line == line:
|
||||
@ -1137,11 +1137,11 @@ class ChangeAtZProcessor:
|
||||
def processPrintSpeed(self, feed_rate: float, new_line: str) -> str:
|
||||
|
||||
# if we're not setting print speed or we don't have a feed rate, stop here
|
||||
if "printspeed" not in self.TargetValues or feed_rate is None:
|
||||
if "printspeed" not in self.targetValues or feed_rate is None:
|
||||
return new_line
|
||||
|
||||
# get our requested print speed
|
||||
print_speed = int(self.TargetValues["printspeed"])
|
||||
print_speed = int(self.targetValues["printspeed"])
|
||||
|
||||
# if they requested no change to print speed (ie: 100%), stop here
|
||||
if print_speed == 100:
|
||||
@ -1157,11 +1157,11 @@ class ChangeAtZProcessor:
|
||||
def processRetractLength(self, extrude_length: float, feed_rate: float, new_line: str, x_coord: float, y_coord: float, z_coord: float) -> str:
|
||||
|
||||
# if we don't have a retract length in the file we can't add one
|
||||
if "retractlength" not in self.LastValues or self.LastValues["retractlength"] == 0:
|
||||
if "retractlength" not in self.lastValues or self.lastValues["retractlength"] == 0:
|
||||
return new_line
|
||||
|
||||
# if we're not changing retraction length, stop here
|
||||
if "retractlength" not in self.TargetValues:
|
||||
if "retractlength" not in self.targetValues:
|
||||
return new_line
|
||||
|
||||
# retractions are only F (feed rate) and E (extrude), at least in cura
|
||||
@ -1173,22 +1173,22 @@ class ChangeAtZProcessor:
|
||||
return new_line
|
||||
|
||||
# stop here if we don't know our last extrude value
|
||||
if self.LastE is None:
|
||||
if self.lastE is None:
|
||||
return new_line
|
||||
|
||||
# if there's no change in extrude we have nothing to change
|
||||
if self.LastE == extrude_length:
|
||||
if self.lastE == extrude_length:
|
||||
return new_line
|
||||
|
||||
# if our last extrude was lower than our current, we're restoring, so skip
|
||||
if self.LastE < extrude_length:
|
||||
if self.lastE < extrude_length:
|
||||
return new_line
|
||||
|
||||
# get our desired retract length
|
||||
retract_length = float(self.TargetValues["retractlength"])
|
||||
retract_length = float(self.targetValues["retractlength"])
|
||||
|
||||
# subtract the difference between the default and the desired
|
||||
extrude_length -= (retract_length - self.LastValues["retractlength"])
|
||||
extrude_length -= (retract_length - self.lastValues["retractlength"])
|
||||
|
||||
# replace our extrude amount
|
||||
return GCodeCommand.replaceDirectArgument(new_line, "E", extrude_length)
|
||||
@ -1197,7 +1197,7 @@ class ChangeAtZProcessor:
|
||||
def processRetractLengthSetting(self, line: str):
|
||||
|
||||
# skip if we're not doing linear retractions
|
||||
if not self.IsLinearRetraction:
|
||||
if not self.linearRetraction:
|
||||
return
|
||||
|
||||
# get our command from the line
|
||||
@ -1208,11 +1208,11 @@ class ChangeAtZProcessor:
|
||||
return
|
||||
|
||||
# get our linear move parameters
|
||||
feed_rate = linear_command.Arguments["F"]
|
||||
x_coord = linear_command.Arguments["X"]
|
||||
y_coord = linear_command.Arguments["Y"]
|
||||
z_coord = linear_command.Arguments["Z"]
|
||||
extrude_length = linear_command.Arguments["E"]
|
||||
feed_rate = linear_command.arguments["F"]
|
||||
x_coord = linear_command.arguments["X"]
|
||||
y_coord = linear_command.arguments["Y"]
|
||||
z_coord = linear_command.arguments["Z"]
|
||||
extrude_length = linear_command.arguments["E"]
|
||||
|
||||
# the command we're looking for only has extrude and feed rate
|
||||
if x_coord is not None or y_coord is not None or z_coord is not None:
|
||||
@ -1230,17 +1230,17 @@ class ChangeAtZProcessor:
|
||||
return
|
||||
|
||||
# what ever the last negative retract length is it wins
|
||||
self.LastValues["retractlength"] = extrude_length
|
||||
self.lastValues["retractlength"] = extrude_length
|
||||
|
||||
# Handles any changes to retraction feed rate for the given linear motion command
|
||||
def processRetractFeedRate(self, extrude_length: float, feed_rate: float, new_line: str, x_coord: float, y_coord: float, z_coord: float) -> str:
|
||||
|
||||
# skip if we're not doing linear retractions
|
||||
if not self.IsLinearRetraction:
|
||||
if not self.linearRetraction:
|
||||
return new_line
|
||||
|
||||
# if we're not changing retraction length, stop here
|
||||
if "retractfeedrate" not in self.TargetValues:
|
||||
if "retractfeedrate" not in self.targetValues:
|
||||
return new_line
|
||||
|
||||
# retractions are only F (feed rate) and E (extrude), at least in cura
|
||||
@ -1252,7 +1252,7 @@ class ChangeAtZProcessor:
|
||||
return new_line
|
||||
|
||||
# get our desired retract feed rate
|
||||
retract_feed_rate = float(self.TargetValues["retractfeedrate"])
|
||||
retract_feed_rate = float(self.targetValues["retractfeedrate"])
|
||||
|
||||
# convert to units/min
|
||||
retract_feed_rate *= 60
|
||||
@ -1264,7 +1264,7 @@ class ChangeAtZProcessor:
|
||||
def processSetting(self, line: str):
|
||||
|
||||
# if we're in layers already we're out of settings
|
||||
if self.CurrentLayer is not None:
|
||||
if self.currentLayer is not None:
|
||||
return
|
||||
|
||||
# check our retract length
|
||||
@ -1277,16 +1277,16 @@ class ChangeAtZProcessor:
|
||||
if not self.isTargetLayerOrHeight():
|
||||
|
||||
# flag that we're outside our target layer
|
||||
self.IsInsideTargetLayer = False
|
||||
self.insideTargetLayer = False
|
||||
|
||||
# skip to the next line
|
||||
return
|
||||
|
||||
# flip if we hit our target layer
|
||||
self.WasInsideTargetLayer = True
|
||||
self.wasInsideTargetLayer = True
|
||||
|
||||
# flag that we're inside our target layer
|
||||
self.IsInsideTargetLayer = True
|
||||
self.insideTargetLayer = True
|
||||
|
||||
# Removes all the ChangeZ layer defaults from the given layer
|
||||
@staticmethod
|
||||
@ -1296,22 +1296,22 @@ class ChangeAtZProcessor:
|
||||
# Resets the class contents to defaults
|
||||
def reset(self):
|
||||
|
||||
self.TargetValues = {}
|
||||
self.IsApplyToSingleLayer = False
|
||||
self.LastE = None
|
||||
self.CurrentZ = None
|
||||
self.CurrentLayer = None
|
||||
self.IsTargetByLayer = True
|
||||
self.TargetLayer = None
|
||||
self.TargetZ = None
|
||||
self.LayerHeight = None
|
||||
self.LastValues = {}
|
||||
self.IsLinearRetraction = True
|
||||
self.IsInsideTargetLayer = False
|
||||
self.IsTargetValuesInjected = False
|
||||
self.IsLastValuesRestored = False
|
||||
self.WasInsideTargetLayer = False
|
||||
self.IsEnabled = True
|
||||
self.targetValues = {}
|
||||
self.applyToSingleLayer = False
|
||||
self.lastE = None
|
||||
self.currentZ = None
|
||||
self.currentLayer = None
|
||||
self.targetByLayer = True
|
||||
self.targetLayer = None
|
||||
self.targetZ = None
|
||||
self.layerHeight = None
|
||||
self.lastValues = {}
|
||||
self.linearRetraction = True
|
||||
self.insideTargetLayer = False
|
||||
self.targetValuesInjected = False
|
||||
self.lastValuesRestored = False
|
||||
self.wasInsideTargetLayer = False
|
||||
self.enabled = True
|
||||
|
||||
# Sets the original GCODE line in a given GCODE command
|
||||
@staticmethod
|
||||
@ -1341,31 +1341,31 @@ class ChangeAtZProcessor:
|
||||
return
|
||||
|
||||
# handle retract length changes
|
||||
if command.Command == "M207":
|
||||
if command.command == "M207":
|
||||
|
||||
# get our retract length if provided
|
||||
if "S" in command.Arguments:
|
||||
self.LastValues["retractlength"] = command.getArgumentAsFloat("S")
|
||||
if "S" in command.arguments:
|
||||
self.lastValues["retractlength"] = command.getArgumentAsFloat("S")
|
||||
|
||||
# get our retract feedrate if provided, convert from mm/m to mm/s
|
||||
if "F" in command.Arguments:
|
||||
self.LastValues["retractfeedrate"] = command.getArgumentAsFloat("F") / 60.0
|
||||
if "F" in command.arguments:
|
||||
self.lastValues["retractfeedrate"] = command.getArgumentAsFloat("F") / 60.0
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle bed temp changes
|
||||
if command.Command == "M140" or command.Command == "M190":
|
||||
if command.command == "M140" or command.command == "M190":
|
||||
|
||||
# get our bed temp if provided
|
||||
if "S" in command.Arguments:
|
||||
self.LastValues["bedTemp"] = command.getArgumentAsFloat("S")
|
||||
if "S" in command.arguments:
|
||||
self.lastValues["bedTemp"] = command.getArgumentAsFloat("S")
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle extruder temp changes
|
||||
if command.Command == "M104" or command.Command == "M109":
|
||||
if command.command == "M104" or command.command == "M109":
|
||||
|
||||
# get our tempurature
|
||||
tempurature = command.getArgumentAsFloat("S")
|
||||
@ -1379,26 +1379,26 @@ class ChangeAtZProcessor:
|
||||
|
||||
# set our extruder temp based on the extruder
|
||||
if extruder is None or extruder == 0:
|
||||
self.LastValues["extruderOne"] = tempurature
|
||||
self.lastValues["extruderOne"] = tempurature
|
||||
|
||||
if extruder is None or extruder == 1:
|
||||
self.LastValues["extruderTwo"] = tempurature
|
||||
self.lastValues["extruderTwo"] = tempurature
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle fan speed changes
|
||||
if command.Command == "M106":
|
||||
if command.command == "M106":
|
||||
|
||||
# get our bed temp if provided
|
||||
if "S" in command.Arguments:
|
||||
self.LastValues["fanSpeed"] = (command.getArgumentAsInt("S") / 255.0) * 100
|
||||
if "S" in command.arguments:
|
||||
self.lastValues["fanSpeed"] = (command.getArgumentAsInt("S") / 255.0) * 100
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle flow rate changes
|
||||
if command.Command == "M221":
|
||||
if command.command == "M221":
|
||||
|
||||
# get our flow rate
|
||||
tempurature = command.getArgumentAsFloat("S")
|
||||
@ -1412,21 +1412,21 @@ class ChangeAtZProcessor:
|
||||
|
||||
# set our extruder temp based on the extruder
|
||||
if extruder is None:
|
||||
self.LastValues["flowrate"] = tempurature
|
||||
self.lastValues["flowrate"] = tempurature
|
||||
elif extruder == 1:
|
||||
self.LastValues["flowrateOne"] = tempurature
|
||||
self.lastValues["flowrateOne"] = tempurature
|
||||
elif extruder == 1:
|
||||
self.LastValues["flowrateTwo"] = tempurature
|
||||
self.lastValues["flowrateTwo"] = tempurature
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle print speed changes
|
||||
if command.Command == "M220":
|
||||
if command.command == "M220":
|
||||
|
||||
# get our speed if provided
|
||||
if "S" in command.Arguments:
|
||||
self.LastValues["speed"] = command.getArgumentAsInt("S")
|
||||
if "S" in command.arguments:
|
||||
self.lastValues["speed"] = command.getArgumentAsInt("S")
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
79
resources/definitions/cocoon_create.def.json
Normal file
79
resources/definitions/cocoon_create.def.json
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "Cocoon Create",
|
||||
"version": 2,
|
||||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Thushan Fernando",
|
||||
"manufacturer": "Cocoon Create",
|
||||
"file_formats": "text/x-gcode",
|
||||
"preferred_quality_type": "fine",
|
||||
"has_materials": true,
|
||||
"platform": "wanhao_200_200_platform.obj",
|
||||
"platform_texture": "Cocoon-backplate.png",
|
||||
"machine_extruder_trains": {
|
||||
"0": "cocoon_create_extruder_0"
|
||||
},
|
||||
"platform_offset": [
|
||||
0,
|
||||
-28,
|
||||
0
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"machine_name": {
|
||||
"default_value": "Cocoon Create"
|
||||
},
|
||||
"machine_width": {
|
||||
"default_value": 200
|
||||
},
|
||||
"machine_height": {
|
||||
"default_value": 180
|
||||
},
|
||||
"machine_depth": {
|
||||
"default_value": 200
|
||||
},
|
||||
"machine_heated_bed": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_gcode_flavor": {
|
||||
"default_value": "RepRap (Marlin/Sprinter)"
|
||||
},
|
||||
"machine_start_gcode": {
|
||||
"default_value": "G21 ;metric values\n G90 ;absolute positioning\n M82 ;set extruder to absolute mode\n M107 ;start with the fan off\n G28 X0 Y0 ;move X/Y to min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E3 ;extrude 3mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
|
||||
},
|
||||
"machine_end_gcode": {
|
||||
"default_value": "M104 S0 ;extruder heater off \n G91 ;relative positioning\n G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n G1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\n G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\n M84 ;steppers off\n G90 ;absolute positioning"
|
||||
},
|
||||
"material_diameter": {
|
||||
"default_value": 1.75
|
||||
},
|
||||
"layer_height": {
|
||||
"default_value": 0.10
|
||||
},
|
||||
"layer_height_0": {
|
||||
"default_value": 0.2
|
||||
},
|
||||
"wall_thickness": {
|
||||
"value": "0.8"
|
||||
},
|
||||
"top_bottom_thickness": {
|
||||
"default_value": 0.6
|
||||
},
|
||||
"speed_print": {
|
||||
"default_value": 50
|
||||
},
|
||||
"support_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_amount": {
|
||||
"default_value": 4.5
|
||||
},
|
||||
"retraction_speed": {
|
||||
"default_value": 25
|
||||
}
|
||||
}
|
||||
}
|
79
resources/definitions/cocoon_create_touch.def.json
Normal file
79
resources/definitions/cocoon_create_touch.def.json
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "Cocoon Create Touch",
|
||||
"version": 2,
|
||||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Thushan Fernando",
|
||||
"manufacturer": "Cocoon Create",
|
||||
"file_formats": "text/x-gcode",
|
||||
"preferred_quality_type": "fine",
|
||||
"has_materials": true,
|
||||
"platform": "wanhao_200_200_platform.obj",
|
||||
"platform_texture": "Cocoon-backplate.png",
|
||||
"machine_extruder_trains": {
|
||||
"0": "cocoon_create_touch_extruder_0"
|
||||
},
|
||||
"platform_offset": [
|
||||
0,
|
||||
-28,
|
||||
0
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"machine_name": {
|
||||
"default_value": "Cocoon Create Touch"
|
||||
},
|
||||
"machine_width": {
|
||||
"default_value": 200
|
||||
},
|
||||
"machine_height": {
|
||||
"default_value": 180
|
||||
},
|
||||
"machine_depth": {
|
||||
"default_value": 200
|
||||
},
|
||||
"machine_heated_bed": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_gcode_flavor": {
|
||||
"default_value": "RepRap (Marlin/Sprinter)"
|
||||
},
|
||||
"machine_start_gcode": {
|
||||
"default_value": "G21 ;metric values\n G90 ;absolute positioning\n M82 ;set extruder to absolute mode\n M107 ;start with the fan off\n G28 X0 Y0 ;move X/Y to min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E3 ;extrude 3mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
|
||||
},
|
||||
"machine_end_gcode": {
|
||||
"default_value": "M104 S0 ;extruder heater off \n G91 ;relative positioning\n G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n G1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\n G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\n M84 ;steppers off\n G90 ;absolute positioning"
|
||||
},
|
||||
"material_diameter": {
|
||||
"default_value": 1.75
|
||||
},
|
||||
"layer_height": {
|
||||
"default_value": 0.10
|
||||
},
|
||||
"layer_height_0": {
|
||||
"default_value": 0.2
|
||||
},
|
||||
"wall_thickness": {
|
||||
"value": "0.8"
|
||||
},
|
||||
"top_bottom_thickness": {
|
||||
"default_value": 0.6
|
||||
},
|
||||
"speed_print": {
|
||||
"default_value": 50
|
||||
},
|
||||
"support_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_amount": {
|
||||
"default_value": 4.5
|
||||
},
|
||||
"retraction_speed": {
|
||||
"default_value": 25
|
||||
}
|
||||
}
|
||||
}
|
@ -4299,7 +4299,7 @@
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"value": "support_pattern == 'cross' or support_pattern == 'gyroid'",
|
||||
"enabled": "(support_enable or support_meshes_present) and (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid')",
|
||||
"enabled": "(support_enable or support_meshes_present) and (support_pattern == 'lines' or support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid')",
|
||||
"limit_to_extruder": "support_infill_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
|
15
resources/extruders/cocoon_create_extruder_0.def.json
Normal file
15
resources/extruders/cocoon_create_extruder_0.def.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "cocoon_create",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
15
resources/extruders/cocoon_create_touch_extruder_0.def.json
Normal file
15
resources/extruders/cocoon_create_touch_extruder_0.def.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "cocoon_create_touch",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
BIN
resources/images/Cocoon-backplate.png
Normal file
BIN
resources/images/Cocoon-backplate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -77,7 +77,7 @@ Item
|
||||
Repeater
|
||||
{
|
||||
id: extrudersRepeater
|
||||
model: activePrinter != null ? activePrinter.extruderList : null
|
||||
model: activePrinter != null ? activePrinter.extruders : null
|
||||
|
||||
ExtruderBox
|
||||
{
|
||||
|
@ -104,16 +104,6 @@ Popup
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
// We set it by means of a binding, since then we can use the when condition, which we need to
|
||||
// prevent a binding loop.
|
||||
Binding
|
||||
{
|
||||
target: parent
|
||||
property: "height"
|
||||
value: parent.childrenRect.height
|
||||
when: parent.visibleChildren.length > 0
|
||||
}
|
||||
|
||||
// Add the qualities that belong to the intent
|
||||
Repeater
|
||||
{
|
||||
@ -148,11 +138,7 @@ Popup
|
||||
Item
|
||||
{
|
||||
height: childrenRect.height
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
width: popup.contentWidth
|
||||
|
||||
Label
|
||||
{
|
||||
|
@ -410,13 +410,13 @@ def test_getPropertyInstancesBeforeResolve(global_stack):
|
||||
|
||||
value = unittest.mock.MagicMock() #Sets just the value.
|
||||
value.getProperty = unittest.mock.MagicMock(side_effect = getValueProperty)
|
||||
value.getMetaDataEntry = unittest.mock.MagicMock(return_value = "quality")
|
||||
value.getMetaDataEntry = unittest.mock.MagicMock(return_value = "quality_changes")
|
||||
resolve = unittest.mock.MagicMock() #Sets just the resolve.
|
||||
resolve.getProperty = unittest.mock.MagicMock(side_effect = getResolveProperty)
|
||||
|
||||
with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock): #To guard against the type checking.
|
||||
global_stack.definition = resolve
|
||||
global_stack.quality = value
|
||||
global_stack.qualityChanges = value
|
||||
|
||||
assert global_stack.getProperty("material_bed_temperature", "value") == 10
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user