Merge branch 'master' of github.com:Ultimaker/Cura into CURA-7122_Include_description_in_search_field

This commit is contained in:
Jaime van Kessel 2020-06-29 13:55:09 +02:00
commit 134d79608f
No known key found for this signature in database
GPG key ID: 3710727397403C91
38 changed files with 559 additions and 216 deletions

View file

@ -1,5 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import QCoreApplication
from UM.Application import Application
from UM.Job import Job
@ -94,6 +95,7 @@ class ArrangeObjectsJob(Job):
status_message.setProgress((idx + 1) / len(nodes_arr) * 100)
Job.yieldThread()
QCoreApplication.processEvents()
grouped_operation.push()

View file

@ -92,6 +92,8 @@ class BuildVolume(SceneNode):
self._adhesion_type = None # type: Any
self._platform = Platform(self)
self._edge_disallowed_size = None
self._build_volume_message = Message(catalog.i18nc("@info:status",
"The build volume height has been reduced due to the value of the"
" \"Print Sequence\" setting to prevent the gantry from colliding"
@ -106,8 +108,6 @@ class BuildVolume(SceneNode):
self._application.globalContainerStackChanged.connect(self._onStackChanged)
self._onStackChanged()
self._engine_ready = False
self._application.engineCreatedSignal.connect(self._onEngineCreated)
@ -118,7 +118,7 @@ class BuildVolume(SceneNode):
self._scene_objects = set() # type: Set[SceneNode]
self._scene_change_timer = QTimer()
self._scene_change_timer.setInterval(100)
self._scene_change_timer.setInterval(200)
self._scene_change_timer.setSingleShot(True)
self._scene_change_timer.timeout.connect(self._onSceneChangeTimerFinished)
@ -747,6 +747,7 @@ class BuildVolume(SceneNode):
self._error_areas = []
used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
self._edge_disallowed_size = None # Force a recalculation
disallowed_border_size = self.getEdgeDisallowedSize()
result_areas = self._computeDisallowedAreasStatic(disallowed_border_size, used_extruders) # Normal machine disallowed areas can always be added.
@ -1124,6 +1125,9 @@ class BuildVolume(SceneNode):
if not self._global_container_stack or not self._global_container_stack.extruderList:
return 0
if self._edge_disallowed_size is not None:
return self._edge_disallowed_size
container_stack = self._global_container_stack
used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
@ -1139,8 +1143,8 @@ class BuildVolume(SceneNode):
# Now combine our different pieces of data to get the final border size.
# Support expansion is added to the bed adhesion, since the bed adhesion goes around support.
# Support expansion is added to farthest shield distance, since the shields go around support.
border_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size)
return border_size
self._edge_disallowed_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size)
return self._edge_disallowed_size
def _clamp(self, value, min_value, max_value):
return max(min(value, max_value), min_value)

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import time
@ -14,6 +14,7 @@ from UM.Settings.Validator import ValidatorState
import cura.CuraApplication
class MachineErrorChecker(QObject):
"""This class performs setting error checks for the currently active machine.
@ -50,6 +51,8 @@ class MachineErrorChecker(QObject):
self._error_check_timer.setInterval(100)
self._error_check_timer.setSingleShot(True)
self._keys_to_check = set() # type: Set[str]
def initialize(self) -> None:
self._error_check_timer.timeout.connect(self._rescheduleCheck)
@ -103,6 +106,7 @@ class MachineErrorChecker(QObject):
if property_name != "value":
return
self._keys_to_check.add(key)
self.startErrorCheck()
def startErrorCheck(self, *args: Any) -> None:
@ -140,7 +144,10 @@ class MachineErrorChecker(QObject):
# Populate the (stack, key) tuples to check
self._stacks_and_keys_to_check = deque()
for stack in global_stack.extruderList:
for key in stack.getAllKeys():
if not self._keys_to_check:
self._keys_to_check = stack.getAllKeys()
for key in self._keys_to_check:
self._stacks_and_keys_to_check.append((stack, key))
self._application.callLater(self._checkStack)
@ -181,18 +188,25 @@ class MachineErrorChecker(QObject):
validator = validator_type(key)
validation_state = validator(stack)
if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError, ValidatorState.Invalid):
# Finish
self._setResult(True)
# Since we don't know if any of the settings we didn't check is has an error value, store the list for the
# next check.
keys_to_recheck = {setting_key for stack, setting_key in self._stacks_and_keys_to_check}
keys_to_recheck.add(key)
self._setResult(True, keys_to_recheck = keys_to_recheck)
return
# Schedule the check for the next key
self._application.callLater(self._checkStack)
def _setResult(self, result: bool) -> None:
def _setResult(self, result: bool, keys_to_recheck = None) -> None:
if result != self._has_errors:
self._has_errors = result
self.hasErrorUpdated.emit()
self._machine_manager.stacksValidationChanged.emit()
if keys_to_recheck is None:
self._keys_to_check = set()
else:
self._keys_to_check = keys_to_recheck
self._need_to_check = False
self._check_in_progress = False
self.needToWaitForResultChanged.emit()

View file

@ -4,6 +4,8 @@
import copy
from typing import List
from PyQt5.QtCore import QCoreApplication
from UM.Job import Job
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Message import Message
@ -93,8 +95,9 @@ class MultiplyObjectsJob(Job):
nodes.append(new_node)
current_progress += 1
status_message.setProgress((current_progress / total_progress) * 100)
QCoreApplication.processEvents()
Job.yieldThread()
QCoreApplication.processEvents()
Job.yieldThread()
if nodes:

View file

@ -54,7 +54,7 @@ class PickingPass(RenderPass):
# Fill up the batch with objects that can be sliced. `
for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
batch.addItem(node.getWorldTransformation(), node.getMeshData())
batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData())
self.bind()
batch.render(self._scene.getActiveCamera())

View file

@ -114,12 +114,12 @@ class PreviewPass(RenderPass):
1.0]
uniforms["diffuse_color"] = prettier_color(diffuse_color)
uniforms["diffuse_color_2"] = diffuse_color2
batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
batch_support_mesh.addItem(node.getWorldTransformation(copy = False), node.getMeshData(), uniforms = uniforms)
else:
# Normal scene node
uniforms = {}
uniforms["diffuse_color"] = prettier_color(cast(CuraSceneNode, node).getDiffuseColor())
batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData(), uniforms = uniforms)
self.bind()

View file

@ -53,6 +53,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
CuraApplication.getInstance().getController().toolOperationStarted.connect(self._onChanged)
CuraApplication.getInstance().getController().toolOperationStopped.connect(self._onChanged)
self._root = Application.getInstance().getController().getScene().getRoot()
self._onGlobalStackChanged()
def createRecomputeConvexHullTimer(self) -> None:
@ -198,23 +200,16 @@ class ConvexHullDecorator(SceneNodeDecorator):
CuraApplication.getInstance().callLater(self.recomputeConvexHullDelayed)
def recomputeConvexHull(self) -> None:
controller = Application.getInstance().getController()
root = controller.getScene().getRoot()
if self._node is None or controller.isToolOperationActive() or not self.__isDescendant(root, self._node):
# If the tool operation is still active, we need to compute the convex hull later after the controller is
# no longer active.
if controller.isToolOperationActive():
self.recomputeConvexHullDelayed()
return
if self._node is None or not self.__isDescendant(self._root, self._node):
if self._convex_hull_node:
# Convex hull node still exists, but the node is removed or no longer in the scene.
self._convex_hull_node.setParent(None)
self._convex_hull_node = None
return
if self._convex_hull_node:
self._convex_hull_node.setParent(None)
hull_node = ConvexHullNode.ConvexHullNode(self._node, self.getPrintingArea(), self._raft_thickness, root)
hull_node = ConvexHullNode.ConvexHullNode(self._node, self.getPrintingArea(), self._raft_thickness, self._root)
self._convex_hull_node = hull_node
def _onSettingValueChanged(self, key: str, property_name: str) -> None:
@ -273,7 +268,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
if mesh is None:
return Polygon([]) # Node has no mesh data, so just return an empty Polygon.
world_transform = self._node.getWorldTransformation()
world_transform = self._node.getWorldTransformation(copy= False)
# Check the cache
if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform:

View file

@ -57,13 +57,20 @@ class ConvexHullNode(SceneNode):
self._hull = hull
if self._hull:
hull_mesh_builder = MeshBuilder()
if self._thickness == 0:
if hull_mesh_builder.addConvexPolygon(
self._hull.getPoints()[::], # bottom layer is reversed
self._mesh_height, color = self._color):
if hull_mesh_builder.addConvexPolygonExtrusion(
self._hull.getPoints()[::-1], # bottom layer is reversed
self._mesh_height - thickness, self._mesh_height, color = self._color):
hull_mesh = hull_mesh_builder.build()
self.setMeshData(hull_mesh)
else:
if hull_mesh_builder.addConvexPolygonExtrusion(
self._hull.getPoints()[::-1], # bottom layer is reversed
self._mesh_height - thickness, self._mesh_height, color = self._color):
hull_mesh = hull_mesh_builder.build()
self.setMeshData(hull_mesh)
hull_mesh = hull_mesh_builder.build()
self.setMeshData(hull_mesh)
def getHull(self):
return self._hull
@ -79,15 +86,15 @@ class ConvexHullNode(SceneNode):
ConvexHullNode.shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "transparent_object.shader"))
ConvexHullNode.shader.setUniformValue("u_diffuseColor", self._color)
ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
if self.getParent():
if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate:
# The object itself (+ adhesion in one-at-a-time mode)
renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
if self._convex_hull_head_mesh:
# The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
# cannot be printed after A, because the head would hit A while printing the current object
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
batch = renderer.getNamedBatch("convex_hull_node")
if not batch:
batch = renderer.createRenderBatch(transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
renderer.addRenderBatch(batch, name = "convex_hull_node")
batch.addItem(self.getWorldTransformation(copy = False), self.getMeshData())
if self._convex_hull_head_mesh:
# The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
# cannot be printed after A, because the head would hit A while printing the current object
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
return True
@ -97,7 +104,3 @@ class ConvexHullNode(SceneNode):
convex_hull_head_builder = MeshBuilder()
convex_hull_head_builder.addConvexPolygon(convex_hull_head.getPoints(), self._mesh_height - self._thickness)
self._convex_hull_head_mesh = convex_hull_head_builder.build()
if not node:
return

View file

@ -118,7 +118,7 @@ class CuraSceneNode(SceneNode):
self._aabb = None
if self._mesh_data:
self._aabb = self._mesh_data.getExtents(self.getWorldTransformation())
self._aabb = self._mesh_data.getExtents(self.getWorldTransformation(copy = False))
else: # If there is no mesh_data, use a bounding box that encompasses the local (0,0,0)
position = self.getWorldPosition()
self._aabb = AxisAlignedBox(minimum = position, maximum = position)
@ -139,7 +139,7 @@ class CuraSceneNode(SceneNode):
"""Taken from SceneNode, but replaced SceneNode with CuraSceneNode"""
copy = CuraSceneNode(no_setting_override = True) # Setting override will be added later
copy.setTransformation(self.getLocalTransformation())
copy.setTransformation(self.getLocalTransformation(copy= False))
copy.setMeshData(self._mesh_data)
copy.setVisible(cast(bool, deepcopy(self._visible, memo)))
copy._selectable = cast(bool, deepcopy(self._selectable, memo))

View file

@ -204,49 +204,50 @@ class ExtruderManager(QObject):
# If no extruders are registered in the extruder manager yet, return an empty array
if len(self.extruderIds) == 0:
return []
number_active_extruders = len([extruder for extruder in self.getActiveExtruderStacks() if extruder.isEnabled])
# Get the extruders of all printable meshes in the scene
meshes = [node for node in DepthFirstIterator(scene_root) if isinstance(node, SceneNode) and node.isSelectable()] #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
nodes = [node for node in DepthFirstIterator(scene_root) if node.isSelectable() and not node.callDecoration("isAntiOverhangMesh") and not node.callDecoration("isSupportMesh")] #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
# Exclude anti-overhang meshes
mesh_list = []
for mesh in meshes:
stack = mesh.callDecoration("getStack")
if stack is not None and (stack.getProperty("anti_overhang_mesh", "value") or stack.getProperty("support_mesh", "value")):
continue
mesh_list.append(mesh)
for mesh in mesh_list:
extruder_stack_id = mesh.callDecoration("getActiveExtruder")
for node in nodes:
extruder_stack_id = node.callDecoration("getActiveExtruder")
if not extruder_stack_id:
# No per-object settings for this node
extruder_stack_id = self.extruderIds["0"]
used_extruder_stack_ids.add(extruder_stack_id)
if len(used_extruder_stack_ids) == number_active_extruders:
# We're already done. Stop looking.
# Especially with a lot of models on the buildplate, this will speed up things rather dramatically.
break
# Get whether any of them use support.
stack_to_use = mesh.callDecoration("getStack") # if there is a per-mesh stack, we use it
stack_to_use = node.callDecoration("getStack") # if there is a per-mesh stack, we use it
if not stack_to_use:
# if there is no per-mesh stack, we use the build extruder for this mesh
stack_to_use = container_registry.findContainerStacks(id = extruder_stack_id)[0]
support_enabled |= stack_to_use.getProperty("support_enable", "value")
support_bottom_enabled |= stack_to_use.getProperty("support_bottom_enable", "value")
support_roof_enabled |= stack_to_use.getProperty("support_roof_enable", "value")
if not support_enabled:
support_enabled |= stack_to_use.getProperty("support_enable", "value")
if not support_bottom_enabled:
support_bottom_enabled |= stack_to_use.getProperty("support_bottom_enable", "value")
if not support_roof_enabled:
support_roof_enabled |= stack_to_use.getProperty("support_roof_enable", "value")
# Check limit to extruders
limit_to_extruder_feature_list = ["wall_0_extruder_nr",
"wall_x_extruder_nr",
"roofing_extruder_nr",
"top_bottom_extruder_nr",
"infill_extruder_nr",
]
for extruder_nr_feature_name in limit_to_extruder_feature_list:
extruder_nr = int(global_stack.getProperty(extruder_nr_feature_name, "value"))
if extruder_nr == -1:
continue
if str(extruder_nr) not in self.extruderIds:
extruder_nr = int(self._application.getMachineManager().defaultExtruderPosition)
used_extruder_stack_ids.add(self.extruderIds[str(extruder_nr)])
# Check limit to extruders
limit_to_extruder_feature_list = ["wall_0_extruder_nr",
"wall_x_extruder_nr",
"roofing_extruder_nr",
"top_bottom_extruder_nr",
"infill_extruder_nr",
]
for extruder_nr_feature_name in limit_to_extruder_feature_list:
extruder_nr = int(global_stack.getProperty(extruder_nr_feature_name, "value"))
if extruder_nr == -1:
continue
if str(extruder_nr) not in self.extruderIds:
extruder_nr = int(self._application.getMachineManager().defaultExtruderPosition)
used_extruder_stack_ids.add(self.extruderIds[str(extruder_nr)])
# Check support extruders
if support_enabled:

View file

@ -35,7 +35,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
"""
_non_thumbnail_visible_settings = {"anti_overhang_mesh", "infill_mesh", "cutting_mesh", "support_mesh"}
def __init__(self):
def __init__(self, *, force_update = True):
super().__init__()
self._stack = PerObjectContainerStack(container_id = "per_object_stack_" + str(id(self)))
self._stack.setDirty(False) # This stack does not need to be saved.
@ -46,6 +46,10 @@ class SettingOverrideDecorator(SceneNodeDecorator):
self._is_non_printing_mesh = False
self._is_non_thumbnail_visible_mesh = False
self._is_support_mesh = False
self._is_cutting_mesh = False
self._is_infill_mesh = False
self._is_anti_overhang_mesh = False
self._stack.propertyChanged.connect(self._onSettingChanged)
@ -53,13 +57,14 @@ class SettingOverrideDecorator(SceneNodeDecorator):
Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack)
self.activeExtruderChanged.connect(self._updateNextStack)
self._updateNextStack()
if force_update:
self._updateNextStack()
def _generateUniqueName(self):
return "SettingOverrideInstanceContainer-%s" % uuid.uuid1()
def __deepcopy__(self, memo):
deep_copy = SettingOverrideDecorator()
deep_copy = SettingOverrideDecorator(force_update = False)
"""Create a fresh decorator object"""
instance_container = copy.deepcopy(self._stack.getContainer(0), memo)
@ -74,11 +79,6 @@ class SettingOverrideDecorator(SceneNodeDecorator):
# Properly set the right extruder on the copy
deep_copy.setActiveExtruder(self._extruder_stack)
# use value from the stack because there can be a delay in signal triggering and "_is_non_printing_mesh"
# has not been updated yet.
deep_copy._is_non_printing_mesh = self._evaluateIsNonPrintingMesh()
deep_copy._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh()
return deep_copy
def getActiveExtruder(self):
@ -104,7 +104,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
"""
# for support_meshes, always use the support_extruder
if self.getStack().getProperty("support_mesh", "value"):
if self._is_support_mesh:
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
return str(global_container_stack.getProperty("support_extruder_nr", "value"))
@ -114,6 +114,30 @@ class SettingOverrideDecorator(SceneNodeDecorator):
container_stack = containers[0]
return container_stack.getMetaDataEntry("position", default=None)
def isCuttingMesh(self):
return self._is_cutting_mesh
def isSupportMesh(self):
return self._is_support_mesh
def isInfillMesh(self):
return self._is_infill_mesh
def isAntiOverhangMesh(self):
return self._is_anti_overhang_mesh
def _evaluateAntiOverhangMesh(self):
return bool(self._stack.userChanges.getProperty("anti_overhang_mesh", "value"))
def _evaluateIsCuttingMesh(self):
return bool(self._stack.userChanges.getProperty("cutting_mesh", "value"))
def _evaluateIsSupportMesh(self):
return bool(self._stack.userChanges.getProperty("support_mesh", "value"))
def _evaluateInfillMesh(self):
return bool(self._stack.userChanges.getProperty("infill_mesh", "value"))
def isNonPrintingMesh(self):
return self._is_non_printing_mesh
@ -132,6 +156,16 @@ class SettingOverrideDecorator(SceneNodeDecorator):
# Trigger slice/need slicing if the value has changed.
self._is_non_printing_mesh = self._evaluateIsNonPrintingMesh()
self._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh()
if setting_key == "anti_overhang_mesh":
self._is_anti_overhang_mesh = self._evaluateAntiOverhangMesh()
elif setting_key == "support_mesh":
self._is_support_mesh = self._evaluateIsSupportMesh()
elif setting_key == "cutting_mesh":
self._is_cutting_mesh = self._evaluateIsCuttingMesh()
elif setting_key == "infill_mesh":
self._is_infill_mesh = self._evaluateInfillMesh()
Application.getInstance().getBackend().needsSlicing()
Application.getInstance().getBackend().tickle()

View file

@ -98,7 +98,8 @@ class ObjectsModel(ListModel):
return True
def _renameNodes(self, node_info_dict: Dict[str, _NodeInfo]) -> List[SceneNode]:
@staticmethod
def _renameNodes(node_info_dict: Dict[str, _NodeInfo]) -> List[SceneNode]:
# Go through all names and find out the names for all nodes that need to be renamed.
all_nodes = [] # type: List[SceneNode]
for name, node_info in node_info_dict.items():
@ -118,9 +119,7 @@ class ObjectsModel(ListModel):
else:
new_group_name = "{0}#{1}".format(name, current_index)
old_name = node.getName()
node.setName(new_group_name)
Logger.log("d", "Node [%s] renamed to [%s]", old_name, new_group_name)
all_nodes.append(node)
return all_nodes
@ -186,11 +185,18 @@ class ObjectsModel(ListModel):
if per_object_stack:
per_object_settings_count = per_object_stack.getTop().getNumInstances()
for mesh_type in ["anti_overhang_mesh", "infill_mesh", "cutting_mesh", "support_mesh"]:
if per_object_stack.getProperty(mesh_type, "value"):
node_mesh_type = mesh_type
per_object_settings_count -= 1 # do not count this mesh type setting
break
if node.callDecoration("isAntiOverhangMesh"):
node_mesh_type = "anti_overhang_mesh"
per_object_settings_count -= 1 # do not count this mesh type setting
elif node.callDecoration("isSupportMesh"):
node_mesh_type = "support_mesh"
per_object_settings_count -= 1 # do not count this mesh type setting
elif node.callDecoration("isCuttingMesh"):
node_mesh_type = "cutting_mesh"
per_object_settings_count -= 1 # do not count this mesh type setting
elif node.callDecoration("isInfillMesh"):
node_mesh_type = "infill_mesh"
per_object_settings_count -= 1 # do not count this mesh type setting
if per_object_settings_count > 0:
if node_mesh_type == "support_mesh":

View file

@ -29,7 +29,7 @@ class XRayPass(RenderPass):
batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, backface_cull = False, blend_mode = RenderBatch.BlendMode.Additive)
for node in DepthFirstIterator(self._scene.getRoot()):
if isinstance(node, CuraSceneNode) and node.getMeshData() and node.isVisible():
batch.addItem(node.getWorldTransformation(), node.getMeshData())
batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData())
self.bind()

View file

@ -8,12 +8,14 @@ import time
from typing import Any, cast, Dict, List, Optional, Set
import re
import Arcus #For typing.
from PyQt5.QtCore import QCoreApplication
from UM.Job import Job
from UM.Logger import Logger
from UM.Scene.SceneNode import SceneNode
from UM.Settings.ContainerStack import ContainerStack #For typing.
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.Interfaces import ContainerInterface
from UM.Settings.SettingDefinition import SettingDefinition
from UM.Settings.SettingRelation import SettingRelation #For typing.
@ -352,8 +354,7 @@ class StartSliceJob(Job):
result = {}
for key in stack.getAllKeys():
value = stack.getProperty(key, "value")
result[key] = value
result[key] = stack.getProperty(key, "value")
Job.yieldThread()
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
@ -373,9 +374,11 @@ class StartSliceJob(Job):
self._all_extruders_settings = {
"-1": self._buildReplacementTokens(global_stack)
}
QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str:
"""Replace setting tokens in a piece of g-code.
@ -420,10 +423,15 @@ class StartSliceJob(Job):
settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], extruder_nr)
settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], extruder_nr)
global_definition = cast(ContainerInterface, cast(ContainerStack, stack.getNextStack()).getBottom())
own_definition = cast(ContainerInterface, stack.getBottom())
for key, value in settings.items():
# Do not send settings that are not settable_per_extruder.
if not stack.getProperty(key, "settable_per_extruder"):
continue
# Since these can only be set in definition files, we only have to ask there.
if not global_definition.getProperty(key, "settable_per_extruder") and \
not own_definition.getProperty(key, "settable_per_extruder"):
continue
setting = message.getMessage("settings").addRepeatedMessage("settings")
setting.name = key
setting.value = str(value).encode("utf-8")
@ -454,11 +462,10 @@ class StartSliceJob(Job):
print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"]
pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) == None
# Replace the setting tokens in start and end g-code.
# Use values from the first used extruder by default so we get the expected temperatures
initial_extruder_stack = CuraApplication.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")
initial_extruder_nr = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()
settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], initial_extruder_nr)
settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], initial_extruder_nr)

View file

@ -141,52 +141,46 @@ class Script:
All other keyword parameters are put in the result in g-code's format.
For instance, if you put ``G=1`` in the parameters, it will output
``G1``. If you put ``G=1, X=100`` in the parameters, it will output
``G1 X100``. The parameters G and M will always be put first. The
parameters T and S will be put second (or first if there is no G or M).
The rest of the parameters will be put in arbitrary order.
``G1 X100``. The parameters will be added in order G M T S F X Y Z E.
Any other parameters will be added in arbitrary order.
:param line: The original g-code line that must be modified. If not
provided, an entirely new g-code line will be produced.
:return: A line of g-code with the desired parameters filled in.
"""
#Strip the comment.
comment = ""
# Strip the comment.
if ";" in line:
comment = line[line.find(";"):]
line = line[:line.find(";")] #Strip the comment.
line = line[:line.find(";")]
else:
comment = ""
#Parse the original g-code line.
# Parse the original g-code line and add them to kwargs.
for part in line.split(" "):
if part == "":
continue
parameter = part[0]
if parameter not in kwargs:
value = part[1:]
kwargs[parameter] = value
# Start writing the new g-code line.
line_parts = list()
# First add these parameters in order
for parameter in ["G", "M", "T", "S", "F", "X", "Y", "Z", "E"]:
if parameter in kwargs:
continue #Skip this one. The user-provided parameter overwrites the one in the line.
value = part[1:]
kwargs[parameter] = value
value = kwargs.pop(parameter) # get the corresponding value and remove the parameter from kwargs
line_parts.append(parameter + str(value))
# Then add the rest of the parameters
for parameter, value in kwargs.items():
line_parts.append(parameter + str(value))
#Write the new g-code line.
result = ""
priority_parameters = ["G", "M", "T", "S", "F", "X", "Y", "Z", "E"] #First some parameters that get priority. In order of priority!
for priority_key in priority_parameters:
if priority_key in kwargs:
if result != "":
result += " "
result += priority_key + str(kwargs[priority_key])
del kwargs[priority_key]
for key, value in kwargs.items():
if result != "":
result += " "
result += key + str(value)
#Put the comment back in.
# If there was a comment, put it at the end.
if comment != "":
if result != "":
result += " "
result += ";" + comment
line_parts.append(comment)
return result
# Add spaces and return the new line
return " ".join(line_parts)
def execute(self, data: List[str]) -> List[str]:
"""This is called when the script is executed.

View file

@ -199,7 +199,7 @@ class SliceInfo(QObject, Extension):
"maximum": {"x": bounding_box.maximum.x,
"y": bounding_box.maximum.y,
"z": bounding_box.maximum.z}}
model["transformation"] = {"data": str(node.getWorldTransformation().getData()).replace("\n", "")}
model["transformation"] = {"data": str(node.getWorldTransformation(copy = False).getData()).replace("\n", "")}
extruder_position = node.callDecoration("getActiveExtruderPosition")
model["extruder"] = 0 if extruder_position is None else int(extruder_position)

View file

@ -64,17 +64,23 @@ class SolidView(View):
self._old_layer_bindings = None
self._next_xray_checking_time = time.time()
self._xray_checking_update_time = 1.0 # seconds
self._xray_checking_update_time = 30.0 # seconds
self._xray_warning_cooldown = 60 * 10 # reshow Model error message every 10 minutes
self._xray_warning_message = Message(
catalog.i18nc("@info:status", "Your model is not manifold. The highlighted areas indicate either missing or extraneous surfaces."),
lifetime = 60 * 5, # leave message for 5 minutes
title = catalog.i18nc("@info:title", "Model errors"),
option_text = catalog.i18nc("@info:option_text", "Do not show this message again"),
option_state = False
)
self._xray_warning_message.optionToggled.connect(self._onDontAskMeAgain)
application.getPreferences().addPreference(self._show_xray_warning_preference, True)
application.engineCreatedSignal.connect(self._onGlobalContainerChanged)
def _onDontAskMeAgain(self, checked: bool) -> None:
Application.getInstance().getPreferences().setValue(self._show_xray_warning_preference, not checked)
def _onGlobalContainerChanged(self) -> None:
if self._global_stack:
try:
@ -103,7 +109,9 @@ class SolidView(View):
except IndexError:
pass
else:
self._support_angle = support_angle_stack.getProperty("support_angle", "value")
angle = support_angle_stack.getProperty("support_angle", "value")
if angle is not None:
self._support_angle = angle
def _checkSetup(self):
if not self._extruders_model:
@ -115,6 +123,7 @@ class SolidView(View):
if not self._enabled_shader:
self._enabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader"))
self._enabled_shader.setUniformValue("u_overhangColor", Color(*self._theme.getColor("model_overhang").getRgb()))
self._enabled_shader.setUniformValue("u_renderError", 0.0)
if not self._disabled_shader:
self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader"))
@ -140,6 +149,7 @@ class SolidView(View):
self._composite_pass.setCompositeShader(self._old_composite_shader)
self._old_layer_bindings = None
self._old_composite_shader = None
self._enabled_shader.setUniformValue("u_renderError", 0.0) # We don't want any error markers!.
self._xray_warning_message.hide()
else:
if not self._xray_shader:
@ -157,7 +167,7 @@ class SolidView(View):
# Currently the RenderPass constructor requires a size > 0
# This should be fixed in RenderPass's constructor.
self._xray_pass = XRayPass.XRayPass(1, 1)
self._enabled_shader.setUniformValue("u_renderError", 1.0) # We don't want any error markers!.
renderer.addRenderPass(self._xray_pass)
if not self._composite_pass:
@ -178,77 +188,77 @@ class SolidView(View):
if global_container_stack:
if Application.getInstance().getPreferences().getValue("view/show_overhang"):
# Make sure the overhang angle is valid before passing it to the shader
if self._support_angle is not None and self._support_angle >= 0 and self._support_angle <= 90:
if self._support_angle >= 0 and self._support_angle <= 90:
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - self._support_angle)))
else:
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang.
else:
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))
disabled_batch = renderer.createRenderBatch(shader = self._disabled_shader)
normal_object_batch = renderer.createRenderBatch(shader = self._enabled_shader)
renderer.addRenderBatch(disabled_batch)
renderer.addRenderBatch(normal_object_batch)
for node in DepthFirstIterator(scene.getRoot()):
if not node.render(renderer):
if node.getMeshData() and node.isVisible() and not node.callDecoration("getLayerData"):
uniforms = {}
shade_factor = 1.0
if node.render(renderer):
continue
per_mesh_stack = node.callDecoration("getStack")
if node.getMeshData() and node.isVisible():
uniforms = {}
shade_factor = 1.0
extruder_index = node.callDecoration("getActiveExtruderPosition")
if extruder_index is None:
extruder_index = "0"
extruder_index = int(extruder_index)
per_mesh_stack = node.callDecoration("getStack")
# Use the support extruder instead of the active extruder if this is a support_mesh
if per_mesh_stack:
if per_mesh_stack.getProperty("support_mesh", "value"):
extruder_index = int(global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr"))
extruder_index = node.callDecoration("getActiveExtruderPosition")
if extruder_index is None:
extruder_index = "0"
extruder_index = int(extruder_index)
try:
material_color = self._extruders_model.getItem(extruder_index)["color"]
except KeyError:
material_color = self._extruders_model.defaultColors[0]
try:
material_color = self._extruders_model.getItem(extruder_index)["color"]
except KeyError:
material_color = self._extruders_model.defaultColors[0]
if extruder_index != ExtruderManager.getInstance().activeExtruderIndex:
# Shade objects that are printed with the non-active extruder 25% darker
shade_factor = 0.6
if extruder_index != ExtruderManager.getInstance().activeExtruderIndex:
# Shade objects that are printed with the non-active extruder 25% darker
shade_factor = 0.6
try:
# Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
# an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
uniforms["diffuse_color"] = [
shade_factor * int(material_color[1:3], 16) / 255,
shade_factor * int(material_color[3:5], 16) / 255,
shade_factor * int(material_color[5:7], 16) / 255,
1.0
]
try:
# Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
# an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
uniforms["diffuse_color"] = [
shade_factor * int(material_color[1:3], 16) / 255,
shade_factor * int(material_color[3:5], 16) / 255,
shade_factor * int(material_color[5:7], 16) / 255,
1.0
]
# Color the currently selected face-id. (Disable for now.)
#face = Selection.getHoverFace()
uniforms["hover_face"] = -1 #if not face or node != face[0] else face[1]
except ValueError:
pass
# Color the currently selected face-id. (Disable for now.)
#face = Selection.getHoverFace()
uniforms["hover_face"] = -1 #if not face or node != face[0] else face[1]
except ValueError:
pass
if node.callDecoration("isNonPrintingMesh"):
if per_mesh_stack and (per_mesh_stack.getProperty("infill_mesh", "value") or per_mesh_stack.getProperty("cutting_mesh", "value")):
renderer.queueNode(node, shader = self._non_printing_shader, uniforms = uniforms, transparent = True)
else:
renderer.queueNode(node, shader = self._non_printing_shader, transparent = True)
elif getattr(node, "_outside_buildarea", False):
renderer.queueNode(node, shader = self._disabled_shader)
elif per_mesh_stack and per_mesh_stack.getProperty("support_mesh", "value"):
# Render support meshes with a vertical stripe that is darker
shade_factor = 0.6
uniforms["diffuse_color_2"] = [
uniforms["diffuse_color"][0] * shade_factor,
uniforms["diffuse_color"][1] * shade_factor,
uniforms["diffuse_color"][2] * shade_factor,
1.0
]
renderer.queueNode(node, shader = self._support_mesh_shader, uniforms = uniforms)
if node.callDecoration("isNonPrintingMesh"):
if per_mesh_stack and (node.callDecoration("isInfillMesh") or node.callDecoration("isCuttingMesh")):
renderer.queueNode(node, shader = self._non_printing_shader, uniforms = uniforms, transparent = True)
else:
renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms)
if node.callDecoration("isGroup") and Selection.isSelected(node):
renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = RenderBatch.RenderMode.LineLoop)
renderer.queueNode(node, shader = self._non_printing_shader, transparent = True)
elif getattr(node, "_outside_buildarea", False):
disabled_batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData())
elif per_mesh_stack and node.callDecoration("isSupportMesh"):
# Render support meshes with a vertical stripe that is darker
shade_factor = 0.6
uniforms["diffuse_color_2"] = [
uniforms["diffuse_color"][0] * shade_factor,
uniforms["diffuse_color"][1] * shade_factor,
uniforms["diffuse_color"][2] * shade_factor,
1.0
]
renderer.queueNode(node, shader = self._support_mesh_shader, uniforms = uniforms)
else:
normal_object_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), uniforms=uniforms)
if node.callDecoration("isGroup") and Selection.isSelected(node):
renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = RenderBatch.RenderMode.LineLoop)
def endRendering(self):
# check whether the xray overlay is showing badness

View file

@ -0,0 +1,58 @@
{
"version": 2,
"name": "BeamUp L",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "BeamUp",
"manufacturer": "BeamUp",
"file_formats": "text/x-gcode",
"platform": "beamup_l.3mf",
"platform_offset": [0, -2.5, -2.5],
"has_machine_quality": true,
"has_materials": true,
"machine_extruder_trains":
{
"0": "beamup_l_extruder_0"
}
},
"overrides": {
"machine_name": {
"default_value": "BeamUp L"
},
"machine_width": {
"default_value": 320
},
"machine_depth": {
"default_value": 320
},
"machine_height": {
"default_value": 300
},
"machine_heated_bed": {
"default_value": false
},
"machine_center_is_zero": {
"default_value": false
},
"machine_nozzle_heat_up_speed": {
"default_value": 2
},
"machine_nozzle_cool_down_speed": {
"default_value": 2
},
"gantry_height": {
"value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
"default_value": "G28 ; home\nG29 ; level\nM80 ; led\nG1 Z15.0 F6000\nT0\nG92 E0.0000\nG1 E-1.4500 F1800\nG1 X50 Y0 Z0.300 F6000\nM300 S3000 P300\nG1 E1.0000 F1800\nG92 E0.0000\nG1 X250 Y0 E15 F662"
},
"machine_end_gcode": {
"default_value": "G28 ; home\nM104 S0 ; turn off\n M140 S0 ; turn off\nM84 ; disable motors\nM107 ; fan off"
}
}
}

View file

@ -6290,7 +6290,7 @@
"slicing_tolerance":
{
"label": "Slicing Tolerance",
"description": "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process.",
"description": "Vertical tolerance in the sliced layers. The contours of a layer are normally generated by taking cross sections through the middle of each layer's thickness (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the entire thickness of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Inclusive retains the most details, Exclusive makes for the best fit and Middle stays closest to the original surface.",
"type": "enum",
"options":
{

View file

@ -81,9 +81,6 @@
"layer_height": {"maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"layer_height_0": {"maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"line_width": {"value": "(machine_nozzle_size + 0.2)" },
"wall_line_width_0": {"value": "(machine_nozzle_size)" },
"infill_line_width": {"value": "(line_width)" },
"initial_layer_line_width_factor": {"value": 110 },
"wall_thickness": {"value": "(line_width * 3) if infill_sparse_density < 95 else line_width" },
@ -111,17 +108,24 @@
"infill_pattern": {"value": "'lines'"},
"infill_before_walls": {"value": true},
"material_print_temperature_layer_0": {"value": "material_print_temperature"},
"material_initial_print_temperature": {"value": "material_print_temperature",
"maximum_value_warning": "material_print_temperature + 15"},
"material_final_print_temperature": {"value": "material_print_temperature"},
"material_bed_temperature_layer_0": {"value": "material_bed_temperature"},
"material_flow_layer_0": {"value": "material_flow"},
"retraction_enable": {"value": true },
"retract_at_layer_change": {"value": false },
"retraction_min_travel": {"value": "(round(line_width * 10))"},
"switch_extruder_retraction_speeds": {"value": "(retraction_speed)"},
"switch_extruder_prime_speed": {"value": "(retraction_prime_speed)"},
"default_material_print_temperature": {"maximum_value": "401" },
"material_print_temperature": {"maximum_value": "401" },
"material_print_temperature_layer_0": {"value": "material_print_temperature",
"maximum_value": "401" },
"material_initial_print_temperature": {"value": "material_print_temperature",
"maximum_value_warning": "material_print_temperature + 15",
"maximum_value": "401" },
"material_initial_print_temperature": {"maximum_value": "401" },
"material_final_print_temperature": {"value": "material_print_temperature",
"maximum_value": "401" },
"material_break_preparation_temperature": {"maximum_value": "401" },
"material_bed_temperature_layer_0": {"value": "material_bed_temperature"},
"material_flow_layer_0": {"value": "material_flow"},
"retraction_enable": {"value": true },
"retract_at_layer_change": {"value": false },
"retraction_min_travel": {"value": "(round(line_width * 10))"},
"switch_extruder_retraction_speeds": {"value": "(retraction_speed)"},
"switch_extruder_prime_speed": {"value": "(retraction_prime_speed)"},
"speed_print": {"value": "50"},
"speed_infill": {"value": "speed_print"},

View file

@ -0,0 +1,15 @@
{
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "beamup_l",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.8 },
"material_diameter": { "default_value": 1.75 }
}
}

View file

@ -16,7 +16,7 @@
"machine_nozzle_offset_y": { "default_value": 0.0 },
"material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "\n;changing to tool1\nM83\nM109 T0 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
"default_value": "\n;changing to tool1\nT0\nM83\nM109 T0 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
},
"machine_extruder_end_code": {
"default_value": "\nG1 X10 Y40 F12000\nG1 X-25 F12000\nM109 T0 R{material_standby_temperature}\nG1 Y20 F3000\n; ending tool1\n\n"

View file

@ -16,7 +16,7 @@
"machine_nozzle_offset_y": { "default_value": 0.0 },
"material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "\n;changing to tool2\nM83\nM109 T1 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
"default_value": "\n;changing to tool2\nT1\nM83\nM109 T1 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
},
"machine_extruder_end_code": {
"default_value": "\nG1 X10 Y40 F12000\nG1 X-25 F12000\nM109 T1 R{material_standby_temperature}\nG1 Y20 F3000\n; ending tool2\n\n"

Binary file not shown.

View file

@ -90,7 +90,7 @@ UM.PreferencesPage
UM.Preferences.resetPreference("view/show_overhang");
showOverhangCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_overhang"))
UM.Preferences.resetPreference("view/show_xray_warning");
showXrayErrorCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_warning"))
showXrayErrorCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_xray_warning"))
UM.Preferences.resetPreference("view/center_on_select");
centerOnSelectCheckbox.checked = boolCheck(UM.Preferences.getValue("view/center_on_select"))
UM.Preferences.resetPreference("view/invert_zoom");
@ -336,7 +336,7 @@ UM.PreferencesPage
id: showOverhangCheckbox
checked: boolCheck(UM.Preferences.getValue("view/show_overhang"))
onClicked: UM.Preferences.setValue("view/show_overhang", checked)
onClicked: UM.Preferences.setValue("view/show_overhang", checked)
text: catalog.i18nc("@option:check", "Display overhang");
}

View file

@ -0,0 +1,40 @@
[general]
version = 4
name = BeamUp L Coarse
definition = beamup_l
[metadata]
setting_version = 15
type = quality
quality_type = coarse
weight = -3
material = generic_pla
[values]
layer_height = 0.30
adhesion_type = brim
brim_line_count = 8
infill_before_walls = False
initial_layer_line_width_factor = 120.0
material_print_temperature = 215
material_print_temperature_layer_0 = 235
retraction_amount = 2
retraction_speed = 30
speed_infill = 55
speed_layer_0 = 25
speed_print = 55
speed_support_interface = 55
speed_topbottom = 55
speed_wall_0 = 45
speed_wall_x = 55
support_enable = True
support_angle = 60
support_infill_rate = 20
support_interface_enable = True
support_interface_height = 0.60
support_interface_pattern = zigzag
support_interface_skip_height = 0.30
support_offset = 0.8
support_z_distance = 0.4
wall_thickness = 1.6
zig_zaggify_infill = True

View file

@ -0,0 +1,40 @@
[general]
version = 4
name = BeamUp L Draft
definition = beamup_l
[metadata]
setting_version = 15
type = quality
quality_type = draft
weight = -2
material = generic_pla
[values]
layer_height = 0.2
adhesion_type = brim
brim_line_count = 8
infill_before_walls = False
initial_layer_line_width_factor = 120.0
material_print_temperature = 210
material_print_temperature_layer_0 = 235
retraction_amount = 2
retraction_speed = 30
speed_infill = 55
speed_layer_0 = 25
speed_print = 55
speed_support_interface = 55
speed_topbottom = 55
speed_wall_0 = 45
speed_wall_x = 55
support_enable = True
support_angle = 60
support_infill_rate = 20
support_interface_enable = True
support_interface_height = 0.60
support_interface_pattern = zigzag
support_interface_skip_height = 0.20
support_offset = 0.8
support_z_distance = 0.3
wall_thickness = 1.6
zig_zaggify_infill = True

View file

@ -0,0 +1,40 @@
[general]
version = 4
name = BeamUp L Extra Fine
definition = beamup_l
[metadata]
setting_version = 15
type = quality
quality_type = high
weight = 1
material = generic_pla
[values]
layer_height = 0.06
adhesion_type = brim
brim_line_count = 8
infill_before_walls = False
initial_layer_line_width_factor = 120.0
material_print_temperature = 195
material_print_temperature_layer_0 = 235
retraction_amount = 2
retraction_speed = 30
speed_infill = 45
speed_layer_0 = 25
speed_print = 45
speed_support_interface = 45
speed_topbottom = 45
speed_wall_0 = 35
speed_wall_x = 45
support_enable = True
support_angle = 60
support_infill_rate = 20
support_interface_enable = True
support_interface_height = 0.30
support_interface_pattern = zigzag
support_interface_skip_height = 0.06
support_offset = 0.8
support_z_distance = 0.12
wall_thickness = 1.6
zig_zaggify_infill = True

View file

@ -0,0 +1,40 @@
[general]
version = 4
name = BeamUp L Fine
definition = beamup_l
[metadata]
setting_version = 15
type = quality
quality_type = normal
weight = 0
material = generic_pla
[values]
layer_height = 0.1
adhesion_type = brim
brim_line_count = 8
infill_before_walls = False
initial_layer_line_width_factor = 120.0
material_print_temperature = 200
material_print_temperature_layer_0 = 235
retraction_amount = 2
retraction_speed = 30
speed_infill = 50
speed_layer_0 = 25
speed_print = 50
speed_support_interface = 50
speed_topbottom = 50
speed_wall_0 = 40
speed_wall_x = 50
support_enable = True
support_angle = 60
support_infill_rate = 20
support_interface_enable = True
support_interface_height = 0.30
support_interface_pattern = zigzag
support_interface_skip_height = 0.10
support_offset = 0.8
support_z_distance = 0.2
wall_thickness = 1.6
zig_zaggify_infill = True

View file

@ -0,0 +1,40 @@
[general]
version = 4
name = BeamUp L Normal
definition = beamup_l
[metadata]
setting_version = 15
type = quality
quality_type = fast
weight = -1
material = generic_pla
[values]
layer_height = 0.15
adhesion_type = brim
brim_line_count = 8
infill_before_walls = False
initial_layer_line_width_factor = 120.0
material_print_temperature = 205
material_print_temperature_layer_0 = 235
retraction_amount = 2
retraction_speed = 30
speed_infill = 50
speed_layer_0 = 25
speed_print = 50
speed_support_interface = 50
speed_topbottom = 50
speed_wall_0 = 40
speed_wall_x = 50
support_enable = True
support_angle = 60
support_infill_rate = 20
support_interface_enable = True
support_interface_height = 0.45
support_interface_pattern = zigzag
support_interface_skip_height = 0.15
support_offset = 0.8
support_z_distance = 0.25
wall_thickness = 1.6
zig_zaggify_infill = True

View file

@ -32,7 +32,6 @@ material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_enable = True
prime_tower_wipe_enabled = True
retraction_combing = off
retraction_extrusion_window = 1
retraction_hop = 0.2
retraction_hop_enabled = False

View file

@ -32,7 +32,6 @@ material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_enable = True
prime_tower_wipe_enabled = True
retraction_combing = off
retraction_extrusion_window = 1
retraction_hop = 0.2
retraction_hop_enabled = False

View file

@ -34,7 +34,6 @@ material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_enable = True
prime_tower_wipe_enabled = True
retraction_combing = off
retraction_extrusion_window = 1
retraction_hop = 0.2
retraction_hop_enabled = False

View file

@ -33,7 +33,6 @@ material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_enable = True
prime_tower_wipe_enabled = True
retraction_combing = off
retraction_extrusion_window = 1
retraction_hop = 0.2
retraction_hop_enabled = False

View file

@ -23,7 +23,6 @@ material_print_temperature = =default_material_print_temperature - 10
material_print_temperature_layer_0 = =material_print_temperature
material_standby_temperature = 100
prime_tower_enable = True
retraction_combing = off
retraction_hop = 0.1
retraction_hop_enabled = False
skin_overlap = 0

View file

@ -24,7 +24,6 @@ material_print_temperature = =default_material_print_temperature - 5
material_print_temperature_layer_0 = =material_print_temperature
material_standby_temperature = 100
prime_tower_enable = True
retraction_combing = off
retraction_hop = 0.1
retraction_hop_enabled = False
skin_overlap = 0

View file

@ -24,7 +24,6 @@ material_print_temperature = =default_material_print_temperature - 7
material_print_temperature_layer_0 = =material_print_temperature
material_standby_temperature = 100
prime_tower_enable = True
retraction_combing = off
retraction_hop = 0.1
retraction_hop_enabled = False
skin_overlap = 0

View file

@ -252,7 +252,7 @@ class TestCalculateExtraZClearance:
return properties.get(args[2])
def test_noContainerStack(self, build_volume: BuildVolume):
assert build_volume._calculateExtraZClearance([]) is 0
assert build_volume._calculateExtraZClearance([]) == 0
def test_withRetractionHop(self, build_volume: BuildVolume):
mocked_global_stack = MagicMock(name="mocked_global_stack")