mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-25 15:48:16 +08:00
Merge branch 'Ultimaker:main' into zyyx_profile_addition
This commit is contained in:
commit
78bface21a
2
.github/workflows/printer-linter-format.yml
vendored
2
.github/workflows/printer-linter-format.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: technote-space/get-diff-action@v6
|
- uses: technote-space/get-diff-action@v6
|
||||||
with:
|
with:
|
||||||
|
@ -15,7 +15,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ jobs:
|
|||||||
echo ${{ github.event.pull_request.head.repo.full_name }} > printer-linter-result/pr-head-repo.txt
|
echo ${{ github.event.pull_request.head.repo.full_name }} > printer-linter-result/pr-head-repo.txt
|
||||||
echo ${{ github.event.pull_request.head.sha }} > printer-linter-result/pr-head-sha.txt
|
echo ${{ github.event.pull_request.head.sha }} > printer-linter-result/pr-head-sha.txt
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: printer-linter-result
|
name: printer-linter-result
|
||||||
path: printer-linter-result/
|
path: printer-linter-result/
|
||||||
|
@ -9,6 +9,11 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
publish_release_description:
|
||||||
|
description: 'Create the GitHub release (if existing, the description will be overridden based on the changelog)'
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
parse-version:
|
parse-version:
|
||||||
name: Parse input version string
|
name: Parse input version string
|
||||||
@ -153,10 +158,12 @@ jobs:
|
|||||||
ref: ${{ needs.parse-version.outputs.branch_name }}
|
ref: ${{ needs.parse-version.outputs.branch_name }}
|
||||||
|
|
||||||
- name: Extract changelog
|
- name: Extract changelog
|
||||||
|
if: ${{ inputs.publish_release_description }}
|
||||||
run: python ./scripts/extract_changelog.py --version ${{ needs.parse-version.outputs.version_major }}.${{ needs.parse-version.outputs.version_minor }}.${{ needs.parse-version.outputs.version_patch }} --changelog ./resources/texts/change_log.txt > formatted_changelog.txt
|
run: python ./scripts/extract_changelog.py --version ${{ needs.parse-version.outputs.version_major }}.${{ needs.parse-version.outputs.version_minor }}.${{ needs.parse-version.outputs.version_patch }} --changelog ./resources/texts/change_log.txt > formatted_changelog.txt
|
||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
uses: notpeelz/action-gh-create-release@v5.0.1
|
uses: notpeelz/action-gh-create-release@v5.0.1
|
||||||
|
if: ${{ inputs.publish_release_description }}
|
||||||
with:
|
with:
|
||||||
target: ${{ needs.create-tags.outputs.main_commit }}
|
target: ${{ needs.create-tags.outputs.main_commit }}
|
||||||
tag: ${{ inputs.cura_version }}
|
tag: ${{ inputs.cura_version }}
|
||||||
|
@ -10,7 +10,7 @@ requirements:
|
|||||||
- "pynest2d/5.3.0"
|
- "pynest2d/5.3.0"
|
||||||
- "native_cad_plugin/2.0.0"
|
- "native_cad_plugin/2.0.0"
|
||||||
requirements_internal:
|
requirements_internal:
|
||||||
- "fdm_materials/(latest)@internal/testing"
|
- "fdm_materials/5.8.1"
|
||||||
- "cura_private_data/(latest)@internal/testing"
|
- "cura_private_data/(latest)@internal/testing"
|
||||||
urls:
|
urls:
|
||||||
default:
|
default:
|
||||||
|
@ -127,13 +127,12 @@ class QualityManagementModel(ListModel):
|
|||||||
# have no container for the global stack, because "my_profile" just got renamed to "my_new_profile". This results
|
# have no container for the global stack, because "my_profile" just got renamed to "my_new_profile". This results
|
||||||
# in crashes because the rest of the system assumes that all data in a QualityChangesGroup will be correct.
|
# in crashes because the rest of the system assumes that all data in a QualityChangesGroup will be correct.
|
||||||
#
|
#
|
||||||
# Renaming the container for the global stack in the end seems to be ok, because the assumption is mostly based
|
# This is why we use the "supress_signals" flag for the set name. This basically makes the change silent.
|
||||||
# on the quality changes container for the global stack.
|
|
||||||
for metadata in quality_changes_group.metadata_per_extruder.values():
|
for metadata in quality_changes_group.metadata_per_extruder.values():
|
||||||
extruder_container = cast(InstanceContainer, container_registry.findContainers(id = metadata["id"])[0])
|
extruder_container = cast(InstanceContainer, container_registry.findContainers(id = metadata["id"])[0])
|
||||||
extruder_container.setName(new_name)
|
extruder_container.setName(new_name, supress_signals=True)
|
||||||
global_container = cast(InstanceContainer, container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])[0])
|
global_container = cast(InstanceContainer, container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])[0])
|
||||||
global_container.setName(new_name)
|
global_container.setName(new_name, supress_signals=True)
|
||||||
|
|
||||||
quality_changes_group.name = new_name
|
quality_changes_group.name = new_name
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from typing import Any, cast, List, Optional, Dict
|
|||||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, QObject
|
from PyQt6.QtCore import pyqtProperty, pyqtSignal, QObject
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Decorators import override
|
from UM.Decorators import CachedMemberFunctions, override
|
||||||
from UM.FlameProfiler import pyqtSlot
|
from UM.FlameProfiler import pyqtSlot
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Settings.ContainerStack import ContainerStack, InvalidContainerStackError
|
from UM.Settings.ContainerStack import ContainerStack, InvalidContainerStackError
|
||||||
@ -237,6 +237,7 @@ class CuraContainerStack(ContainerStack):
|
|||||||
:param new_value: The new value to set the property to.
|
:param new_value: The new value to set the property to.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
CachedMemberFunctions.clearInstanceCache(self)
|
||||||
container_index = _ContainerIndexes.UserChanges
|
container_index = _ContainerIndexes.UserChanges
|
||||||
self._containers[container_index].setProperty(key, property_name, property_value, container, set_from_cache)
|
self._containers[container_index].setProperty(key, property_name, property_value, container, set_from_cache)
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from typing import Any, Dict, TYPE_CHECKING, Optional
|
|||||||
|
|
||||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal
|
from PyQt6.QtCore import pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
from UM.Decorators import override
|
from UM.Decorators import CachedMemberFunctions, override
|
||||||
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
|
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
@ -86,6 +86,7 @@ class ExtruderStack(CuraContainerStack):
|
|||||||
def setCompatibleMaterialDiameter(self, value: float) -> None:
|
def setCompatibleMaterialDiameter(self, value: float) -> None:
|
||||||
old_approximate_diameter = self.getApproximateMaterialDiameter()
|
old_approximate_diameter = self.getApproximateMaterialDiameter()
|
||||||
if self.getCompatibleMaterialDiameter() != value:
|
if self.getCompatibleMaterialDiameter() != value:
|
||||||
|
CachedMemberFunctions.clearInstanceCache(self)
|
||||||
self.definitionChanges.setProperty("material_diameter", "value", value)
|
self.definitionChanges.setProperty("material_diameter", "value", value)
|
||||||
self.compatibleMaterialDiameterChanged.emit()
|
self.compatibleMaterialDiameterChanged.emit()
|
||||||
|
|
||||||
|
@ -198,6 +198,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||||||
|
|
||||||
self._resetLastSliceTimeStats()
|
self._resetLastSliceTimeStats()
|
||||||
self._snapshot: Optional[QImage] = None
|
self._snapshot: Optional[QImage] = None
|
||||||
|
self._last_socket_error: Optional[Arcus.Error] = None
|
||||||
|
|
||||||
application.initializationFinished.connect(self.initialize)
|
application.initializationFinished.connect(self.initialize)
|
||||||
|
|
||||||
@ -569,7 +570,19 @@ class CuraEngineBackend(QObject, Backend):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Preparation completed, send it to the backend.
|
# Preparation completed, send it to the backend.
|
||||||
self._socket.sendMessage(job.getSliceMessage())
|
if not self._socket.sendMessage(job.getSliceMessage()):
|
||||||
|
if self._last_socket_error is not None and self._last_socket_error.getErrorCode() == Arcus.ErrorCode.MessageTooBigError:
|
||||||
|
error_txt = catalog.i18nc("@info:status", "Unable to send the model data to the engine. Please try to use a less detailed model, or reduce the number of instances.")
|
||||||
|
else:
|
||||||
|
error_txt = catalog.i18nc("@info:status", "Unable to send the model data to the engine. Please try again, or contact support.")
|
||||||
|
|
||||||
|
self._error_message = Message(error_txt,
|
||||||
|
title=catalog.i18nc("@info:title", "Unable to slice"),
|
||||||
|
message_type=Message.MessageType.WARNING)
|
||||||
|
self._error_message.show()
|
||||||
|
self.setState(BackendState.Error)
|
||||||
|
self.backendError.emit(job)
|
||||||
|
return
|
||||||
|
|
||||||
# Notify the user that it's now up to the backend to do its job
|
# Notify the user that it's now up to the backend to do its job
|
||||||
self.setState(BackendState.Processing)
|
self.setState(BackendState.Processing)
|
||||||
@ -691,6 +704,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||||||
if error.getErrorCode() == Arcus.ErrorCode.Debug:
|
if error.getErrorCode() == Arcus.ErrorCode.Debug:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._last_socket_error = error
|
||||||
self._terminate()
|
self._terminate()
|
||||||
self._createSocket()
|
self._createSocket()
|
||||||
|
|
||||||
|
@ -49,7 +49,20 @@ class StartJobResult(IntEnum):
|
|||||||
ObjectsWithDisabledExtruder = 8
|
ObjectsWithDisabledExtruder = 8
|
||||||
|
|
||||||
|
|
||||||
class GcodeStartEndFormatter(Formatter):
|
class GcodeConditionState(IntEnum):
|
||||||
|
OutsideCondition = 1
|
||||||
|
ConditionFalse = 2
|
||||||
|
ConditionTrue = 3
|
||||||
|
ConditionDone = 4
|
||||||
|
|
||||||
|
|
||||||
|
class GcodeInstruction(IntEnum):
|
||||||
|
Skip = 1
|
||||||
|
Evaluate = 2
|
||||||
|
EvaluateAndWrite = 3
|
||||||
|
|
||||||
|
|
||||||
|
class GcodeStartEndFormatter:
|
||||||
# Formatter class that handles token expansion in start/end gcode
|
# Formatter class that handles token expansion in start/end gcode
|
||||||
# Example of a start/end gcode string:
|
# Example of a start/end gcode string:
|
||||||
# ```
|
# ```
|
||||||
@ -63,22 +76,50 @@ class GcodeStartEndFormatter(Formatter):
|
|||||||
# will be used. Alternatively, if the expression is formatted as "{[expression], [extruder_nr]}",
|
# will be used. Alternatively, if the expression is formatted as "{[expression], [extruder_nr]}",
|
||||||
# then the expression will be evaluated with the extruder stack of the specified extruder_nr.
|
# then the expression will be evaluated with the extruder stack of the specified extruder_nr.
|
||||||
|
|
||||||
_extruder_regex = re.compile(r"^\s*(?P<expression>.*)\s*,\s*(?P<extruder_nr_expr>.*)\s*$")
|
_instruction_regex = re.compile(r"{(?P<condition>if|else|elif|endif)?\s*(?P<expression>.*?)\s*(?:,\s*(?P<extruder_nr_expr>.*))?\s*}(?P<end_of_line>\n?)")
|
||||||
|
|
||||||
def __init__(self, all_extruder_settings: Dict[str, Any], default_extruder_nr: int = -1) -> None:
|
def __init__(self, all_extruder_settings: Dict[str, Dict[str, Any]], default_extruder_nr: int = -1) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._all_extruder_settings: Dict[str, Any] = all_extruder_settings
|
self._all_extruder_settings: Dict[str, Dict[str, Any]] = all_extruder_settings
|
||||||
self._default_extruder_nr: int = default_extruder_nr
|
self._default_extruder_nr: int = default_extruder_nr
|
||||||
|
self._cura_application = CuraApplication.getInstance()
|
||||||
|
self._extruder_manager = ExtruderManager.getInstance()
|
||||||
|
|
||||||
def get_field(self, field_name, args: [str], kwargs: dict) -> Tuple[str, str]:
|
def format(self, text: str) -> str:
|
||||||
# get_field method parses all fields in the format-string and parses them individually to the get_value method.
|
remaining_text: str = text
|
||||||
# e.g. for a string "Hello {foo.bar}" would the complete field "foo.bar" would be passed to get_field, and then
|
result: str = ""
|
||||||
# the individual parts "foo" and "bar" would be passed to get_value. This poses a problem for us, because want
|
|
||||||
# to parse the entire field as a single expression. To solve this, we override the get_field method and return
|
|
||||||
# the entire field as the expression.
|
|
||||||
return self.get_value(field_name, args, kwargs), field_name
|
|
||||||
|
|
||||||
def get_value(self, expression: str, args: [str], kwargs: dict) -> str:
|
self._condition_state: GcodeConditionState = GcodeConditionState.OutsideCondition
|
||||||
|
|
||||||
|
while len(remaining_text) > 0:
|
||||||
|
next_code_match = self._instruction_regex.search(remaining_text)
|
||||||
|
if next_code_match is not None:
|
||||||
|
expression_start, expression_end = next_code_match.span()
|
||||||
|
|
||||||
|
if expression_start > 0:
|
||||||
|
result += self._process_statement(remaining_text[:expression_start])
|
||||||
|
|
||||||
|
result += self._process_code(next_code_match)
|
||||||
|
|
||||||
|
remaining_text = remaining_text[expression_end:]
|
||||||
|
|
||||||
|
else:
|
||||||
|
result += self._process_statement(remaining_text)
|
||||||
|
remaining_text = ""
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _process_statement(self, statement: str) -> str:
|
||||||
|
if self._condition_state in [GcodeConditionState.OutsideCondition, GcodeConditionState.ConditionTrue]:
|
||||||
|
return statement
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def _process_code(self, code: re.Match) -> str:
|
||||||
|
condition: Optional[str] = code.group("condition")
|
||||||
|
expression: Optional[str] = code.group("expression")
|
||||||
|
extruder_nr_expr: Optional[str] = code.group("extruder_nr_expr")
|
||||||
|
end_of_line: Optional[str] = code.group("end_of_line")
|
||||||
|
|
||||||
# The following variables are not settings, but only become available after slicing.
|
# The following variables are not settings, but only become available after slicing.
|
||||||
# when these variables are encountered, we return them as-is. They are replaced later
|
# when these variables are encountered, we return them as-is. They are replaced later
|
||||||
@ -87,53 +128,100 @@ class GcodeStartEndFormatter(Formatter):
|
|||||||
if expression in post_slice_data_variables:
|
if expression in post_slice_data_variables:
|
||||||
return f"{{{expression}}}"
|
return f"{{{expression}}}"
|
||||||
|
|
||||||
extruder_nr = str(self._default_extruder_nr)
|
extruder_nr: str = str(self._default_extruder_nr)
|
||||||
|
instruction: GcodeInstruction = GcodeInstruction.Skip
|
||||||
|
|
||||||
# The settings may specify a specific extruder to use. This is done by
|
# The settings may specify a specific extruder to use. This is done by
|
||||||
# formatting the expression as "{expression}, {extruder_nr_expr}". If the
|
# formatting the expression as "{expression}, {extruder_nr_expr}". If the
|
||||||
# expression is formatted like this, we extract the extruder_nr and use
|
# expression is formatted like this, we extract the extruder_nr and use
|
||||||
# it to get the value from the correct extruder stack.
|
# it to get the value from the correct extruder stack.
|
||||||
match = self._extruder_regex.match(expression)
|
if condition is None:
|
||||||
if match:
|
# This is a classic statement
|
||||||
expression = match.group("expression")
|
if self._condition_state in [GcodeConditionState.OutsideCondition, GcodeConditionState.ConditionTrue]:
|
||||||
extruder_nr_expr = match.group("extruder_nr_expr")
|
# Skip and move to next
|
||||||
|
instruction = GcodeInstruction.EvaluateAndWrite
|
||||||
if extruder_nr_expr.isdigit():
|
|
||||||
extruder_nr = extruder_nr_expr
|
|
||||||
else:
|
else:
|
||||||
# We get the value of the extruder_nr_expr from `_all_extruder_settings` dictionary
|
# This is a condition statement, first check validity
|
||||||
# rather than the global container stack. The `_all_extruder_settings["-1"]` is a
|
if condition == "if":
|
||||||
# dict-representation of the global container stack, with additional properties such
|
if self._condition_state != GcodeConditionState.OutsideCondition:
|
||||||
# as `initial_extruder_nr`. As users may enter such expressions we can't use the
|
raise SyntaxError("Nested conditions are not supported")
|
||||||
# global container stack.
|
else:
|
||||||
extruder_nr = str(self._all_extruder_settings["-1"].get(extruder_nr_expr, "-1"))
|
if self._condition_state == GcodeConditionState.OutsideCondition:
|
||||||
|
raise SyntaxError("Condition should start with an 'if' statement")
|
||||||
|
|
||||||
|
if condition == "if":
|
||||||
|
# First instruction, just evaluate it
|
||||||
|
instruction = GcodeInstruction.Evaluate
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self._condition_state == GcodeConditionState.ConditionTrue:
|
||||||
|
# We have reached the next condition after a valid one has been found, skip the rest
|
||||||
|
self._condition_state = GcodeConditionState.ConditionDone
|
||||||
|
|
||||||
|
if condition == "elif":
|
||||||
|
if self._condition_state == GcodeConditionState.ConditionFalse:
|
||||||
|
# New instruction, and valid condition has not been reached so far => evaluate it
|
||||||
|
instruction = GcodeInstruction.Evaluate
|
||||||
|
else:
|
||||||
|
# New instruction, but valid condition has already been reached => skip it
|
||||||
|
instruction = GcodeInstruction.Skip
|
||||||
|
|
||||||
|
elif condition == "else":
|
||||||
|
instruction = GcodeInstruction.Skip # Never evaluate, expression should be empty
|
||||||
|
if self._condition_state == GcodeConditionState.ConditionFalse:
|
||||||
|
# Fallback instruction, and valid condition has not been reached so far => active next
|
||||||
|
self._condition_state = GcodeConditionState.ConditionTrue
|
||||||
|
|
||||||
|
elif condition == "endif":
|
||||||
|
instruction = GcodeInstruction.Skip # Never evaluate, expression should be empty
|
||||||
|
self._condition_state = GcodeConditionState.OutsideCondition
|
||||||
|
|
||||||
|
if instruction >= GcodeInstruction.Evaluate and extruder_nr_expr is not None:
|
||||||
|
extruder_nr_function = SettingFunction(extruder_nr_expr)
|
||||||
|
container_stack = self._cura_application.getGlobalContainerStack()
|
||||||
|
|
||||||
|
# We add the variables contained in `_all_extruder_settings["-1"]`, which is a dict-representation of the
|
||||||
|
# global container stack, with additional properties such as `initial_extruder_nr`. As users may enter such
|
||||||
|
# expressions we can't use the global container stack. The variables contained in the global container stack
|
||||||
|
# will then be inserted twice, which is not optimal but works well.
|
||||||
|
extruder_nr = str(extruder_nr_function(container_stack, additional_variables=self._all_extruder_settings["-1"]))
|
||||||
|
|
||||||
|
if instruction >= GcodeInstruction.Evaluate:
|
||||||
if extruder_nr in self._all_extruder_settings:
|
if extruder_nr in self._all_extruder_settings:
|
||||||
additional_variables = self._all_extruder_settings[extruder_nr].copy()
|
additional_variables = self._all_extruder_settings[extruder_nr].copy()
|
||||||
else:
|
else:
|
||||||
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
||||||
additional_variables = self._all_extruder_settings["-1"].copy()
|
additional_variables = self._all_extruder_settings["-1"].copy()
|
||||||
|
|
||||||
# Add the arguments and keyword arguments to the additional settings. These
|
|
||||||
# are currently _not_ used, but they are added for consistency with the
|
|
||||||
# base Formatter class.
|
|
||||||
for key, value in enumerate(args):
|
|
||||||
additional_variables[key] = value
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
additional_variables[key] = value
|
|
||||||
|
|
||||||
if extruder_nr == "-1":
|
if extruder_nr == "-1":
|
||||||
container_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
container_stack = self._cura_application.getGlobalContainerStack()
|
||||||
else:
|
else:
|
||||||
container_stack = ExtruderManager.getInstance().getExtruderStack(extruder_nr)
|
container_stack = self._extruder_manager.getExtruderStack(extruder_nr)
|
||||||
if not container_stack:
|
if not container_stack:
|
||||||
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
||||||
container_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
container_stack = self._cura_application.getGlobalContainerStack()
|
||||||
|
|
||||||
setting_function = SettingFunction(expression)
|
setting_function = SettingFunction(expression)
|
||||||
value = setting_function(container_stack, additional_variables=additional_variables)
|
value = setting_function(container_stack, additional_variables=additional_variables)
|
||||||
|
|
||||||
return value
|
if instruction == GcodeInstruction.Evaluate:
|
||||||
|
if value:
|
||||||
|
self._condition_state = GcodeConditionState.ConditionTrue
|
||||||
|
else:
|
||||||
|
self._condition_state = GcodeConditionState.ConditionFalse
|
||||||
|
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
value_str = str(value)
|
||||||
|
|
||||||
|
if end_of_line is not None:
|
||||||
|
# If we are evaluating an expression that is not a condition, restore the end of line
|
||||||
|
value_str += end_of_line
|
||||||
|
|
||||||
|
return value_str
|
||||||
|
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class StartSliceJob(Job):
|
class StartSliceJob(Job):
|
||||||
@ -470,6 +558,9 @@ class StartSliceJob(Job):
|
|||||||
result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]
|
result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]
|
||||||
result["initial_extruder_nr"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()
|
result["initial_extruder_nr"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()
|
||||||
|
|
||||||
|
# If adding or changing a setting here, please update the associated wiki page
|
||||||
|
# https://github.com/Ultimaker/Cura/wiki/Start-End-G%E2%80%90Code
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _cacheAllExtruderSettings(self):
|
def _cacheAllExtruderSettings(self):
|
||||||
|
@ -182,7 +182,7 @@ Item
|
|||||||
Cura.GcodeTextArea // "Extruder Start G-code"
|
Cura.GcodeTextArea // "Extruder Start G-code"
|
||||||
{
|
{
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: buttonLearnMore.top
|
||||||
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
width: base.columnWidth - UM.Theme.getSize("default_margin").width
|
width: base.columnWidth - UM.Theme.getSize("default_margin").width
|
||||||
@ -196,7 +196,7 @@ Item
|
|||||||
Cura.GcodeTextArea // "Extruder End G-code"
|
Cura.GcodeTextArea // "Extruder End G-code"
|
||||||
{
|
{
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: buttonLearnMore.top
|
||||||
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
width: base.columnWidth - UM.Theme.getSize("default_margin").width
|
width: base.columnWidth - UM.Theme.getSize("default_margin").width
|
||||||
@ -206,5 +206,17 @@ Item
|
|||||||
settingKey: "machine_extruder_end_code"
|
settingKey: "machine_extruder_end_code"
|
||||||
settingStoreIndex: propertyStoreIndex
|
settingStoreIndex: propertyStoreIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cura.TertiaryButton
|
||||||
|
{
|
||||||
|
id: buttonLearnMore
|
||||||
|
|
||||||
|
text: catalog.i18nc("@button", "Learn more")
|
||||||
|
iconSource: UM.Theme.getIcon("LinkExternal")
|
||||||
|
isIconOnRightSide: true
|
||||||
|
onClicked: Qt.openUrlExternally("https://github.com/Ultimaker/Cura/wiki/Start-End-G%E2%80%90Code")
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ Item
|
|||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: upperBlock.bottom
|
top: upperBlock.bottom
|
||||||
bottom: parent.bottom
|
bottom: buttonLearnMore.top
|
||||||
left: parent.left
|
left: parent.left
|
||||||
right: parent.right
|
right: parent.right
|
||||||
margins: UM.Theme.getSize("default_margin").width
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
@ -403,5 +403,19 @@ Item
|
|||||||
settingKey: "machine_end_gcode"
|
settingKey: "machine_end_gcode"
|
||||||
settingStoreIndex: propertyStoreIndex
|
settingStoreIndex: propertyStoreIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.TertiaryButton
|
||||||
|
{
|
||||||
|
id: buttonLearnMore
|
||||||
|
|
||||||
|
text: catalog.i18nc("@button", "Learn more")
|
||||||
|
iconSource: UM.Theme.getIcon("LinkExternal")
|
||||||
|
isIconOnRightSide: true
|
||||||
|
onClicked: Qt.openUrlExternally("https://github.com/Ultimaker/Cura/wiki/Start-End-G%E2%80%90Code")
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import xml.etree.ElementTree as ET
|
|||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Decorators import CachedMemberFunctions
|
||||||
import UM.Dictionary
|
import UM.Dictionary
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
@ -71,6 +72,8 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
Logger.log("w", "Can't change metadata {key} of material {material_id} because it's read-only.".format(key = key, material_id = self.getId()))
|
Logger.log("w", "Can't change metadata {key} of material {material_id} because it's read-only.".format(key = key, material_id = self.getId()))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
CachedMemberFunctions.clearInstanceCache(self)
|
||||||
|
|
||||||
# Some metadata such as diameter should also be instantiated to be a setting. Go though all values for the
|
# Some metadata such as diameter should also be instantiated to be a setting. Go though all values for the
|
||||||
# "properties" field and apply the new values to SettingInstances as well.
|
# "properties" field and apply the new values to SettingInstances as well.
|
||||||
new_setting_values_dict = {}
|
new_setting_values_dict = {}
|
||||||
@ -480,6 +483,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
first.append(element)
|
first.append(element)
|
||||||
|
|
||||||
def clearData(self):
|
def clearData(self):
|
||||||
|
CachedMemberFunctions.clearInstanceCache(self)
|
||||||
self._metadata = {
|
self._metadata = {
|
||||||
"id": self.getId(),
|
"id": self.getId(),
|
||||||
"name": ""
|
"name": ""
|
||||||
@ -519,6 +523,8 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
def deserialize(self, serialized, file_name = None):
|
def deserialize(self, serialized, file_name = None):
|
||||||
"""Overridden from InstanceContainer"""
|
"""Overridden from InstanceContainer"""
|
||||||
|
|
||||||
|
CachedMemberFunctions.clearInstanceCache(self)
|
||||||
|
|
||||||
containers_to_add = []
|
containers_to_add = []
|
||||||
# update the serialized data first
|
# update the serialized data first
|
||||||
from UM.Settings.Interfaces import ContainerInterface
|
from UM.Settings.Interfaces import ContainerInterface
|
||||||
|
@ -1 +1 @@
|
|||||||
version: "5.8.0"
|
version: "5.9.0-alpha.0"
|
||||||
|
@ -172,7 +172,6 @@
|
|||||||
"default_value": 3,
|
"default_value": 3,
|
||||||
"description": "The height difference between the tip of the nozzle and the lowest part of the print head.",
|
"description": "The height difference between the tip of the nozzle and the lowest part of the print head.",
|
||||||
"label": "Nozzle Length",
|
"label": "Nozzle Length",
|
||||||
"settable_globally": false,
|
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_meshgroup": false,
|
"settable_per_meshgroup": false,
|
||||||
|
@ -70,14 +70,12 @@
|
|||||||
"machine_max_feedrate_e": { "default_value": 45 },
|
"machine_max_feedrate_e": { "default_value": 45 },
|
||||||
"material_bed_temperature":
|
"material_bed_temperature":
|
||||||
{
|
{
|
||||||
"maximum_value": "140",
|
"maximum_value": "120",
|
||||||
"maximum_value_warning": "120",
|
|
||||||
"minimum_value": "0"
|
"minimum_value": "0"
|
||||||
},
|
},
|
||||||
"material_bed_temperature_layer_0":
|
"material_bed_temperature_layer_0":
|
||||||
{
|
{
|
||||||
"maximum_value": "140",
|
"maximum_value": "120",
|
||||||
"maximum_value_warning": "120",
|
|
||||||
"minimum_value": "0"
|
"minimum_value": "0"
|
||||||
},
|
},
|
||||||
"material_print_temp_wait": { "value": false },
|
"material_print_temp_wait": { "value": false },
|
||||||
|
@ -112,10 +112,10 @@
|
|||||||
"machine_head_with_fans_polygon":
|
"machine_head_with_fans_polygon":
|
||||||
{
|
{
|
||||||
"default_value": [
|
"default_value": [
|
||||||
[-30, -80],
|
[-35, -80],
|
||||||
[-30, 20],
|
[-35, 30],
|
||||||
[50, 20],
|
[55, 30],
|
||||||
[50, -80]
|
[55, -80]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"machine_heated_bed": { "default_value": true },
|
"machine_heated_bed": { "default_value": true },
|
||||||
|
@ -62,7 +62,6 @@ Item
|
|||||||
|
|
||||||
property alias showProfileFolder: showProfileFolderAction
|
property alias showProfileFolder: showProfileFolderAction
|
||||||
property alias documentation: documentationAction
|
property alias documentation: documentationAction
|
||||||
property alias showTroubleshooting: showTroubleShootingAction
|
|
||||||
property alias openSponsershipPage: openSponsershipPageAction
|
property alias openSponsershipPage: openSponsershipPageAction
|
||||||
property alias reportBug: reportBugAction
|
property alias reportBug: reportBugAction
|
||||||
property alias whatsNew: whatsNewAction
|
property alias whatsNew: whatsNewAction
|
||||||
@ -86,14 +85,6 @@ Item
|
|||||||
|
|
||||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
|
|
||||||
|
|
||||||
Action
|
|
||||||
{
|
|
||||||
id: showTroubleShootingAction
|
|
||||||
onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/troubleshooting?utm_source=cura&utm_medium=software&utm_campaign=dropdown-troubleshooting")
|
|
||||||
text: catalog.i18nc("@action:inmenu", "Show Online Troubleshooting")
|
|
||||||
}
|
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: openSponsershipPageAction
|
id: openSponsershipPageAction
|
||||||
|
@ -12,20 +12,16 @@ import Cura 1.1 as Cura
|
|||||||
//
|
//
|
||||||
// TextArea widget for editing Gcode in the Machine Settings dialog.
|
// TextArea widget for editing Gcode in the Machine Settings dialog.
|
||||||
//
|
//
|
||||||
UM.TooltipArea
|
Item
|
||||||
{
|
{
|
||||||
id: control
|
id: control
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||||
|
|
||||||
text: tooltip
|
|
||||||
|
|
||||||
property alias containerStackId: propertyProvider.containerStackId
|
property alias containerStackId: propertyProvider.containerStackId
|
||||||
property alias settingKey: propertyProvider.key
|
property alias settingKey: propertyProvider.key
|
||||||
property alias settingStoreIndex: propertyProvider.storeIndex
|
property alias settingStoreIndex: propertyProvider.storeIndex
|
||||||
|
|
||||||
property string tooltip: propertyProvider.properties.description ? propertyProvider.properties.description : ""
|
|
||||||
|
|
||||||
property alias labelText: titleLabel.text
|
property alias labelText: titleLabel.text
|
||||||
property alias labelFont: titleLabel.font
|
property alias labelFont: titleLabel.font
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ Cura.Menu
|
|||||||
title: catalog.i18nc("@title:menu menubar:toplevel", "&Help")
|
title: catalog.i18nc("@title:menu menubar:toplevel", "&Help")
|
||||||
|
|
||||||
Cura.MenuItem { action: Cura.Actions.showProfileFolder }
|
Cura.MenuItem { action: Cura.Actions.showProfileFolder }
|
||||||
Cura.MenuItem { action: Cura.Actions.showTroubleshooting}
|
|
||||||
Cura.MenuItem { action: Cura.Actions.documentation }
|
Cura.MenuItem { action: Cura.Actions.documentation }
|
||||||
Cura.MenuItem { action: Cura.Actions.reportBug }
|
Cura.MenuItem { action: Cura.Actions.reportBug }
|
||||||
Cura.MenuItem { action: Cura.Actions.openSponsershipPage }
|
Cura.MenuItem { action: Cura.Actions.openSponsershipPage }
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
[general]
|
||||||
|
definition = ultimaker_factor4
|
||||||
|
name = Extra Fast
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
material = generic_tpu
|
||||||
|
quality_type = verydraft
|
||||||
|
setting_version = 23
|
||||||
|
type = quality
|
||||||
|
variant = AA 0.8
|
||||||
|
weight = -3
|
||||||
|
|
||||||
|
[values]
|
||||||
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
|
gradual_flow_enabled = True
|
||||||
|
infill_pattern = ='zigzag' if infill_sparse_density > 50 else 'cross_3d'
|
||||||
|
infill_sparse_density = 20
|
||||||
|
inset_direction = outside_in
|
||||||
|
material_print_temperature = =default_material_print_temperature + 5
|
||||||
|
max_flow_acceleration = 1
|
||||||
|
skin_material_flow = =material_flow * 0.9
|
||||||
|
skin_material_flow_layer_0 = 90
|
||||||
|
speed_layer_0 = 20
|
||||||
|
speed_print = 35
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
[general]
|
||||||
|
definition = ultimaker_factor4
|
||||||
|
name = Sprint
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
material = generic_tpu
|
||||||
|
quality_type = superdraft
|
||||||
|
setting_version = 23
|
||||||
|
type = quality
|
||||||
|
variant = AA 0.8
|
||||||
|
weight = -4
|
||||||
|
|
||||||
|
[values]
|
||||||
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
|
gradual_flow_enabled = True
|
||||||
|
infill_pattern = ='zigzag' if infill_sparse_density > 50 else 'cross_3d'
|
||||||
|
infill_sparse_density = 20
|
||||||
|
inset_direction = outside_in
|
||||||
|
material_print_temperature = =default_material_print_temperature + 8
|
||||||
|
max_flow_acceleration = 1
|
||||||
|
skin_material_flow = =material_flow * 0.9
|
||||||
|
skin_material_flow_layer_0 = 90
|
||||||
|
speed_layer_0 = 20
|
||||||
|
speed_print = 35
|
||||||
|
|
@ -12,20 +12,32 @@ variant = BB 0.4
|
|||||||
weight = -1
|
weight = -1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,21 +12,32 @@ variant = BB 0.4
|
|||||||
weight = 0
|
weight = 0
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
speed_print = 50
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,21 +12,32 @@ variant = BB 0.4
|
|||||||
weight = -2
|
weight = -2
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
speed_print = 50
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,21 +12,32 @@ variant = BB 0.4
|
|||||||
weight = -3
|
weight = -3
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
speed_print = 40
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,20 +12,32 @@ variant = BB 0.8
|
|||||||
weight = -2
|
weight = -2
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,20 +12,32 @@ variant = BB 0.8
|
|||||||
weight = -3
|
weight = -3
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -12,20 +12,32 @@ variant = BB 0.8
|
|||||||
weight = -4
|
weight = -4
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
acceleration_print = 1000.0
|
||||||
acceleration_support_bottom = 100
|
acceleration_support_bottom = 100
|
||||||
acceleration_support_interface = 1500
|
acceleration_support_interface = 1000
|
||||||
brim_replaces_support = False
|
brim_replaces_support = False
|
||||||
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
build_volume_temperature = =40 if extruders_enabled_count > 1 else 35
|
||||||
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
default_material_bed_temperature = =0 if extruders_enabled_count > 1 else 60
|
||||||
gradual_flow_discretisation_step_size = 0.1
|
gradual_flow_discretisation_step_size = 0.1
|
||||||
gradual_flow_enabled = True
|
gradual_flow_enabled = True
|
||||||
initial_layer_line_width_factor = 150
|
gradual_support_infill_steps = 0
|
||||||
|
initial_layer_line_width_factor = 125
|
||||||
|
jerk_print = 10
|
||||||
|
material_flow_layer_0 = 90
|
||||||
max_flow_acceleration = 1
|
max_flow_acceleration = 1
|
||||||
minimum_support_area = 4
|
minimum_support_area = 4
|
||||||
|
prime_tower_flow = 90
|
||||||
prime_tower_min_volume = 15
|
prime_tower_min_volume = 15
|
||||||
|
retraction_min_travel = 5.0
|
||||||
|
retraction_prime_speed = 10.0
|
||||||
skin_material_flow = =material_flow * 0.93
|
skin_material_flow = =material_flow * 0.93
|
||||||
|
speed_print = 30
|
||||||
|
support_angle = 45
|
||||||
|
support_infill_rate = 20
|
||||||
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
support_infill_sparse_thickness = =min(layer_height * 2, machine_nozzle_size * 3 / 4) if layer_height <= 0.15 / 0.4 * machine_nozzle_size else layer_height
|
||||||
support_interface_offset = 1
|
support_interface_offset = 1
|
||||||
support_offset = 3
|
support_offset = 3
|
||||||
|
support_xy_distance = 2
|
||||||
support_z_distance = 0
|
support_z_distance = 0
|
||||||
|
switch_extruder_prime_speed = 10.0
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[general]
|
[general]
|
||||||
definition = ultimaker_factor4
|
definition = ultimaker_factor4
|
||||||
name = Sprint
|
name = Extra Fast
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
[5.8.1]
|
||||||
|
|
||||||
|
* Bug fixes:
|
||||||
|
- Fixed an issue where materials could not be synced to UltiMaker Printers
|
||||||
|
|
||||||
|
* Profile Improvements
|
||||||
|
- Significant improvements for PVA and TPU 95A profiles for UltiMaker Factor 4
|
||||||
|
|
||||||
[5.8]
|
[5.8]
|
||||||
|
|
||||||
* New Z Seam Settings:
|
* New Z Seam Settings:
|
||||||
|
310
tests/Machines/TestStartEndGCode.py
Normal file
310
tests/Machines/TestStartEndGCode.py
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
# Copyright (c) 2024 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from plugins.CuraEngineBackend.StartSliceJob import GcodeStartEndFormatter
|
||||||
|
|
||||||
|
|
||||||
|
# def createMockedInstanceContainer(container_id):
|
||||||
|
# result = MagicMock()
|
||||||
|
# result.getId = MagicMock(return_value=container_id)
|
||||||
|
# result.getMetaDataEntry = MagicMock(side_effect=getMetadataEntrySideEffect)
|
||||||
|
# return result
|
||||||
|
|
||||||
|
class MockValueProvider:
|
||||||
|
## Creates a mock value provider.
|
||||||
|
#
|
||||||
|
# This initialises a dictionary with key-value pairs.
|
||||||
|
def __init__(self, values):
|
||||||
|
self._values = values
|
||||||
|
|
||||||
|
## Provides a value.
|
||||||
|
#
|
||||||
|
# \param name The key of the value to provide.
|
||||||
|
def getProperty(self, key, property_name, context = None):
|
||||||
|
if not (key in self._values):
|
||||||
|
return None
|
||||||
|
return self._values[key]
|
||||||
|
|
||||||
|
extruder_0_values = {
|
||||||
|
"material_temperature": 190.0
|
||||||
|
}
|
||||||
|
|
||||||
|
extruder_1_values = {
|
||||||
|
"material_temperature": 210.0
|
||||||
|
}
|
||||||
|
|
||||||
|
global_values = {
|
||||||
|
"bed_temperature": 50.0,
|
||||||
|
"initial_extruder": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
extruder_0_provider = MockValueProvider(extruder_0_values)
|
||||||
|
extruder_1_provider = MockValueProvider(extruder_1_values)
|
||||||
|
|
||||||
|
all_extruder_settings = {"-1": global_values, "0": extruder_0_values, "1": extruder_1_values}
|
||||||
|
|
||||||
|
test_cases = [
|
||||||
|
('Static code', None, 'G0', 'G0'),
|
||||||
|
|
||||||
|
('Basic replacement', None, 'M128 {bed_temperature}', 'M128 50.0'),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with global setting',
|
||||||
|
None,
|
||||||
|
'''{if bed_temperature > 30}
|
||||||
|
G123
|
||||||
|
{else}
|
||||||
|
G456
|
||||||
|
{endif}''',
|
||||||
|
'''G123
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with extruder setting directly specified by index 0',
|
||||||
|
None,
|
||||||
|
'''{if material_temperature > 200, 0}
|
||||||
|
G10
|
||||||
|
{else}
|
||||||
|
G20
|
||||||
|
{endif}''',
|
||||||
|
'''G20
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'Conditional expression with extruder setting directly specified by index 1',
|
||||||
|
None,
|
||||||
|
'''{if material_temperature > 200, 1}
|
||||||
|
G100
|
||||||
|
{else}
|
||||||
|
G200
|
||||||
|
{endif}''',
|
||||||
|
'''G100
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with extruder index specified by setting',
|
||||||
|
None,
|
||||||
|
'''{if material_temperature > 200, initial_extruder}
|
||||||
|
G1000
|
||||||
|
{else}
|
||||||
|
G2000
|
||||||
|
{endif}''',
|
||||||
|
'''G2000
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with extruder index specified by formula',
|
||||||
|
None,
|
||||||
|
'''{if material_temperature > 200, (initial_extruder + 1) % 2}
|
||||||
|
X1000
|
||||||
|
{else}
|
||||||
|
X2000
|
||||||
|
{endif}''',
|
||||||
|
'''X1000
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with elsif',
|
||||||
|
None,
|
||||||
|
'''{if bed_temperature < 30}
|
||||||
|
T30
|
||||||
|
{elif bed_temperature >= 30 and bed_temperature < 40}
|
||||||
|
T40
|
||||||
|
{elif bed_temperature >= 40 and bed_temperature < 50}
|
||||||
|
T50
|
||||||
|
{elif bed_temperature >= 50 and bed_temperature < 60}
|
||||||
|
T60
|
||||||
|
{elif bed_temperature >= 60 and bed_temperature < 70}
|
||||||
|
T70
|
||||||
|
{else}
|
||||||
|
T-800
|
||||||
|
{endif}''',
|
||||||
|
'''T60
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Formula inside a conditional expression',
|
||||||
|
None,
|
||||||
|
'''{if bed_temperature < 30}
|
||||||
|
Z000
|
||||||
|
{else}
|
||||||
|
Z{bed_temperature + 10}
|
||||||
|
{endif}''',
|
||||||
|
'''Z60.0
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Other commands around conditional expression',
|
||||||
|
None,
|
||||||
|
'''
|
||||||
|
R000
|
||||||
|
# My super initial command
|
||||||
|
R111 X123 Y456 Z789
|
||||||
|
{if bed_temperature > 30}
|
||||||
|
R987
|
||||||
|
R654 X321
|
||||||
|
{else}
|
||||||
|
R963 X852 Y741
|
||||||
|
R321 X654 Y987
|
||||||
|
{endif}
|
||||||
|
# And finally, the end of the start at the beginning of the header
|
||||||
|
R369
|
||||||
|
R357 X951 Y843''',
|
||||||
|
'''
|
||||||
|
R000
|
||||||
|
# My super initial command
|
||||||
|
R111 X123 Y456 Z789
|
||||||
|
R987
|
||||||
|
R654 X321
|
||||||
|
# And finally, the end of the start at the beginning of the header
|
||||||
|
R369
|
||||||
|
R357 X951 Y843'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Multiple conditional expressions',
|
||||||
|
None,
|
||||||
|
'''
|
||||||
|
A999
|
||||||
|
{if bed_temperature > 30}
|
||||||
|
A000
|
||||||
|
{else}
|
||||||
|
A100
|
||||||
|
{endif}
|
||||||
|
A888
|
||||||
|
{if material_temperature > 200, 0}
|
||||||
|
A200
|
||||||
|
{else}
|
||||||
|
A300
|
||||||
|
{endif}
|
||||||
|
A777
|
||||||
|
''',
|
||||||
|
'''
|
||||||
|
A999
|
||||||
|
A000
|
||||||
|
A888
|
||||||
|
A300
|
||||||
|
A777
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Nested condition expression',
|
||||||
|
SyntaxError,
|
||||||
|
'''{if bed_temperature < 30}
|
||||||
|
{if material_temperature < 30, 0}
|
||||||
|
M000
|
||||||
|
{else}
|
||||||
|
M888
|
||||||
|
{endif}
|
||||||
|
{else}
|
||||||
|
M{bed_temperature + 10}
|
||||||
|
{endif}''',
|
||||||
|
''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Wrong condition expression',
|
||||||
|
SyntaxError,
|
||||||
|
'''{of material_temperature > 200, 1}
|
||||||
|
G100
|
||||||
|
{else}
|
||||||
|
G200
|
||||||
|
{endif}''',
|
||||||
|
''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Condition expression without start',
|
||||||
|
SyntaxError,
|
||||||
|
'''
|
||||||
|
W100
|
||||||
|
{else}
|
||||||
|
W200
|
||||||
|
{endif}''',
|
||||||
|
''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Formula with non-existing variable',
|
||||||
|
None,
|
||||||
|
'{material_storage_temperature}',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Missing formula end character',
|
||||||
|
None,
|
||||||
|
'{material_temperature, 0',
|
||||||
|
'{material_temperature, 0'
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Conditional expression with missing end character',
|
||||||
|
SyntaxError,
|
||||||
|
'''{if material_temperature > 200, 0
|
||||||
|
Q1000
|
||||||
|
{else}
|
||||||
|
Q2000
|
||||||
|
{endif}''',
|
||||||
|
''
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
'Unexpected end character',
|
||||||
|
None,
|
||||||
|
'''{if material_temperature > 200, 0}}
|
||||||
|
S1000
|
||||||
|
{else}
|
||||||
|
S2000
|
||||||
|
{endif}''',
|
||||||
|
'''S2000
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
if "original_gcode" in metafunc.fixturenames:
|
||||||
|
tests_ids = [test[0] for test in test_cases]
|
||||||
|
tests_data = [test[1:] for test in test_cases]
|
||||||
|
metafunc.parametrize("exception_type, original_gcode, expected_gcode", tests_data, ids = tests_ids)
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def cura_application():
|
||||||
|
result = MagicMock()
|
||||||
|
result.getGlobalContainerStack = MagicMock(return_value = MockValueProvider(global_values))
|
||||||
|
return result
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def extruder_manager():
|
||||||
|
def get_extruder(extruder_nr: str):
|
||||||
|
if extruder_nr == "0":
|
||||||
|
return extruder_0_provider
|
||||||
|
elif extruder_nr == "1":
|
||||||
|
return extruder_1_provider
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
result = MagicMock()
|
||||||
|
result.getExtruderStack = MagicMock(side_effect = get_extruder)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def test_startEndGCode_replace(cura_application, extruder_manager, exception_type, original_gcode, expected_gcode):
|
||||||
|
formatter = GcodeStartEndFormatter(all_extruder_settings, -1)
|
||||||
|
formatter._cura_application = cura_application
|
||||||
|
formatter._extruder_manager = extruder_manager
|
||||||
|
|
||||||
|
if exception_type is not None:
|
||||||
|
with pytest.raises(exception_type):
|
||||||
|
formatter.format(original_gcode)
|
||||||
|
else:
|
||||||
|
assert formatter.format(original_gcode) == expected_gcode
|
Loading…
x
Reference in New Issue
Block a user