Merge remote-tracking branch 'origin/master' into CURA-6460_remove_square_tower

This commit is contained in:
Lipu Fei 2019-06-17 13:11:07 +02:00
commit 1d85e60a6b
23 changed files with 856 additions and 345 deletions

View file

@ -21,7 +21,7 @@ To upload a project, try changing the extension to e.g. .curaproject.3mf.zip so
Thank you for using Cura!
-->
**Application Version**
**Application version**
<!-- The version of the application this issue occurs with -->
**Platform**
@ -30,11 +30,14 @@ Thank you for using Cura!
**Printer**
<!-- Which printer was selected in Cura? If possible, please attach project file as .curaproject.3mf.zip -->
**Actual Results**
**Reproduction steps**
<!-- How did you encounter the bug? -->
**Actual results**
<!-- What happens after the above steps have been followed -->
**Expected results**
<!-- What should happen after the above steps have been followed -->
**Additional Information**
**Additional information**
<!-- Extra information relevant to the issue, like screenshots -->

View file

@ -1,6 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Mesh.MeshData import MeshData
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Settings.ExtruderManager import ExtruderManager
from UM.Application import Application #To modify the maximum zoom level.
@ -20,13 +20,20 @@ from UM.Signal import Signal
from PyQt5.QtCore import QTimer
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
from cura.Settings.GlobalStack import GlobalStack
catalog = i18nCatalog("cura")
import numpy
import math
import copy
from typing import List, Optional
from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable, Dict
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderStack import ExtruderStack
from UM.Settings.ContainerStack import ContainerStack
# Radius of disallowed area in mm around prime. I.e. how much distance to keep from prime position.
PRIME_CLEARANCE = 6.5
@ -36,45 +43,46 @@ PRIME_CLEARANCE = 6.5
class BuildVolume(SceneNode):
raftThicknessChanged = Signal()
def __init__(self, application, parent = None):
def __init__(self, application: "CuraApplication", parent: Optional[SceneNode] = None) -> None:
super().__init__(parent)
self._application = application
self._machine_manager = self._application.getMachineManager()
self._volume_outline_color = None
self._x_axis_color = None
self._y_axis_color = None
self._z_axis_color = None
self._disallowed_area_color = None
self._error_area_color = None
self._volume_outline_color = None # type: Optional[Color]
self._x_axis_color = None # type: Optional[Color]
self._y_axis_color = None # type: Optional[Color]
self._z_axis_color = None # type: Optional[Color]
self._disallowed_area_color = None # type: Optional[Color]
self._error_area_color = None # type: Optional[Color]
self._width = 0 #type: float
self._height = 0 #type: float
self._depth = 0 #type: float
self._shape = "" #type: str
self._width = 0 # type: float
self._height = 0 # type: float
self._depth = 0 # type: float
self._shape = "" # type: str
self._shader = None
self._origin_mesh = None
self._origin_mesh = None # type: Optional[MeshData]
self._origin_line_length = 20
self._origin_line_width = 0.5
self._grid_mesh = None
self._grid_mesh = None # type: Optional[MeshData]
self._grid_shader = None
self._disallowed_areas = []
self._disallowed_areas_no_brim = []
self._disallowed_area_mesh = None
self._disallowed_areas = [] # type: List[Polygon]
self._disallowed_areas_no_brim = [] # type: List[Polygon]
self._disallowed_area_mesh = None # type: Optional[MeshData]
self._disallowed_area_size = 0.
self._error_areas = []
self._error_mesh = None
self._error_areas = [] # type: List[Polygon]
self._error_mesh = None # type: Optional[MeshData]
self.setCalculateBoundingBox(False)
self._volume_aabb = None
self._volume_aabb = None # type: Optional[AxisAlignedBox]
self._raft_thickness = 0.0
self._extra_z_clearance = 0.0
self._adhesion_type = None
self._adhesion_type = None # type: Any
self._platform = Platform(self)
self._build_volume_message = Message(catalog.i18nc("@info:status",
@ -82,7 +90,7 @@ class BuildVolume(SceneNode):
" \"Print Sequence\" setting to prevent the gantry from colliding"
" with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
self._global_container_stack = None
self._global_container_stack = None # type: Optional[GlobalStack]
self._stack_change_timer = QTimer()
self._stack_change_timer.setInterval(100)
@ -100,7 +108,7 @@ class BuildVolume(SceneNode):
self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged)
#Objects loaded at the moment. We are connected to the property changed events of these objects.
self._scene_objects = set()
self._scene_objects = set() # type: Set[SceneNode]
self._scene_change_timer = QTimer()
self._scene_change_timer.setInterval(100)
@ -124,8 +132,8 @@ class BuildVolume(SceneNode):
# Enable and disable extruder
self._machine_manager.extruderChanged.connect(self.updateNodeBoundaryCheck)
# list of settings which were updated
self._changed_settings_since_last_rebuild = []
# List of settings which were updated
self._changed_settings_since_last_rebuild = [] # type: List[str]
def _onSceneChanged(self, source):
if self._global_container_stack:
@ -219,9 +227,12 @@ class BuildVolume(SceneNode):
## For every sliceable node, update node._outside_buildarea
#
def updateNodeBoundaryCheck(self):
if not self._global_container_stack:
return
root = self._application.getController().getScene().getRoot()
nodes = list(BreadthFirstIterator(root))
group_nodes = []
nodes = cast(List[SceneNode], list(cast(Iterable, BreadthFirstIterator(root))))
group_nodes = [] # type: List[SceneNode]
build_volume_bounding_box = self.getBoundingBox()
if build_volume_bounding_box:
@ -240,6 +251,9 @@ class BuildVolume(SceneNode):
group_nodes.append(node) # Keep list of affected group_nodes
if node.callDecoration("isSliceable") or node.callDecoration("isGroup"):
if not isinstance(node, CuraSceneNode):
continue
if node.collidesWithBbox(build_volume_bounding_box):
node.setOutsideBuildArea(True)
continue
@ -277,8 +291,8 @@ class BuildVolume(SceneNode):
child_node.setOutsideBuildArea(group_node.isOutsideBuildArea())
## Update the outsideBuildArea of a single node, given bounds or current build volume
def checkBoundsAndUpdate(self, node: CuraSceneNode, bounds: Optional[AxisAlignedBox] = None):
if not isinstance(node, CuraSceneNode):
def checkBoundsAndUpdate(self, node: CuraSceneNode, bounds: Optional[AxisAlignedBox] = None) -> None:
if not isinstance(node, CuraSceneNode) or self._global_container_stack is None:
return
if bounds is None:
@ -310,7 +324,7 @@ class BuildVolume(SceneNode):
node.setOutsideBuildArea(False)
def _buildGridMesh(self, min_w, max_w, min_h, max_h, min_d, max_d, z_fight_distance):
def _buildGridMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d:float, z_fight_distance: float) -> MeshData:
mb = MeshBuilder()
if self._shape != "elliptic":
# Build plate grid mesh
@ -346,7 +360,7 @@ class BuildVolume(SceneNode):
mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
return mb.build().getTransformed(scale_matrix)
def _buildMesh(self, min_w, max_w, min_h, max_h, min_d, max_d, z_fight_distance):
def _buildMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d:float, z_fight_distance: float) -> MeshData:
if self._shape != "elliptic":
# Outline 'cube' of the build volume
mb = MeshBuilder()
@ -379,7 +393,7 @@ class BuildVolume(SceneNode):
mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self._volume_outline_color)
return mb.build().getTransformed(scale_matrix)
def _buildOriginMesh(self, origin):
def _buildOriginMesh(self, origin: Vector) -> MeshData:
mb = MeshBuilder()
mb.addCube(
width=self._origin_line_length,
@ -404,22 +418,80 @@ class BuildVolume(SceneNode):
)
return mb.build()
def _updateColors(self):
theme = self._application.getTheme()
if theme is None:
return
self._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
self._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
self._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
self._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
self._error_area_color = Color(*theme.getColor("error_area").getRgb())
def _buildErrorMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d: float, disallowed_area_height: float) -> Optional[MeshData]:
if not self._error_areas:
return None
mb = MeshBuilder()
for error_area in self._error_areas:
color = self._error_area_color
points = error_area.getPoints()
first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
self._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color=color)
previous_point = new_point
return mb.build()
def _buildDisallowedAreaMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d: float, disallowed_area_height: float) -> Optional[MeshData]:
if not self._disallowed_areas:
return None
mb = MeshBuilder()
color = self._disallowed_area_color
for polygon in self._disallowed_areas:
points = polygon.getPoints()
if len(points) == 0:
continue
first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
self._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color=color)
previous_point = new_point
# Find the largest disallowed area to exclude it from the maximum scale bounds.
# This is a very nasty hack. This pretty much only works for UM machines.
# This disallowed area_size needs a -lot- of rework at some point in the future: TODO
if numpy.min(points[:,
1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
else:
size = 0
self._disallowed_area_size = max(size, self._disallowed_area_size)
return mb.build()
## Recalculates the build volume & disallowed areas.
def rebuild(self):
def rebuild(self) -> None:
if not self._width or not self._height or not self._depth:
return
if not self._engine_ready:
return
if not self._global_container_stack:
return
if not self._volume_outline_color:
theme = self._application.getTheme()
self._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
self._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
self._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
self._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
self._error_area_color = Color(*theme.getColor("error_area").getRgb())
self._updateColors()
min_w = -self._width / 2
max_w = self._width / 2
@ -442,52 +514,10 @@ class BuildVolume(SceneNode):
self._origin_mesh = self._buildOriginMesh(origin)
disallowed_area_height = 0.1
disallowed_area_size = 0
if self._disallowed_areas:
mb = MeshBuilder()
color = self._disallowed_area_color
for polygon in self._disallowed_areas:
points = polygon.getPoints()
if len(points) == 0:
continue
self._disallowed_area_size = 0.
self._disallowed_area_mesh = self._buildDisallowedAreaMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height)
first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color = color)
previous_point = new_point
# Find the largest disallowed area to exclude it from the maximum scale bounds.
# This is a very nasty hack. This pretty much only works for UM machines.
# This disallowed area_size needs a -lot- of rework at some point in the future: TODO
if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
else:
size = 0
disallowed_area_size = max(size, disallowed_area_size)
self._disallowed_area_mesh = mb.build()
else:
self._disallowed_area_mesh = None
if self._error_areas:
mb = MeshBuilder()
for error_area in self._error_areas:
color = self._error_area_color
points = error_area.getPoints()
first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
self._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color=color)
previous_point = new_point
self._error_mesh = mb.build()
else:
self._error_mesh = None
self._error_mesh = self._buildErrorMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height)
self._volume_aabb = AxisAlignedBox(
minimum = Vector(min_w, min_h - 1.0, min_d),
@ -499,21 +529,24 @@ class BuildVolume(SceneNode):
# This is probably wrong in all other cases. TODO!
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
scale_to_max_bounds = AxisAlignedBox(
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1),
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1)
)
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore
self.updateNodeBoundaryCheck()
def getBoundingBox(self) -> AxisAlignedBox:
def getBoundingBox(self):
return self._volume_aabb
def getRaftThickness(self) -> float:
return self._raft_thickness
def _updateRaftThickness(self):
def _updateRaftThickness(self) -> None:
if not self._global_container_stack:
return
old_raft_thickness = self._raft_thickness
if self._global_container_stack.extruders:
# This might be called before the extruder stacks have initialised, in which case getting the adhesion_type fails
@ -524,7 +557,7 @@ class BuildVolume(SceneNode):
self._global_container_stack.getProperty("raft_base_thickness", "value") +
self._global_container_stack.getProperty("raft_interface_thickness", "value") +
self._global_container_stack.getProperty("raft_surface_layers", "value") *
self._global_container_stack.getProperty("raft_surface_thickness", "value") +
self._global_container_stack.getProperty("raft_surface_thickness", "value") +
self._global_container_stack.getProperty("raft_airgap", "value") -
self._global_container_stack.getProperty("layer_0_z_overlap", "value"))
@ -533,28 +566,23 @@ class BuildVolume(SceneNode):
self.setPosition(Vector(0, -self._raft_thickness, 0), SceneNode.TransformSpace.World)
self.raftThicknessChanged.emit()
def _updateExtraZClearance(self) -> None:
def _calculateExtraZClearance(self, extruders: List["ContainerStack"]) -> float:
if not self._global_container_stack:
return 0
extra_z = 0.0
extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
use_extruders = False
for extruder in extruders:
if extruder.getProperty("retraction_hop_enabled", "value"):
retraction_hop = extruder.getProperty("retraction_hop", "value")
if extra_z is None or retraction_hop > extra_z:
extra_z = retraction_hop
use_extruders = True
if not use_extruders:
# If no extruders, take global value.
if self._global_container_stack.getProperty("retraction_hop_enabled", "value"):
extra_z = self._global_container_stack.getProperty("retraction_hop", "value")
if extra_z != self._extra_z_clearance:
self._extra_z_clearance = extra_z
return extra_z
def _onStackChanged(self):
self._stack_change_timer.start()
## Update the build volume visualization
def _onStackChangeTimerFinished(self):
def _onStackChangeTimerFinished(self) -> None:
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
@ -585,7 +613,7 @@ class BuildVolume(SceneNode):
self._updateDisallowedAreas()
self._updateRaftThickness()
self._updateExtraZClearance()
self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
if self._engine_ready:
self.rebuild()
@ -594,20 +622,23 @@ class BuildVolume(SceneNode):
if camera:
diagonal = self.getDiagonalSize()
if diagonal > 1:
camera.setZoomRange(min = 0.1, max = diagonal * 5) #You can zoom out up to 5 times the diagonal. This gives some space around the volume.
# You can zoom out up to 5 times the diagonal. This gives some space around the volume.
camera.setZoomRange(min = 0.1, max = diagonal * 5) # type: ignore
def _onEngineCreated(self):
def _onEngineCreated(self) -> None:
self._engine_ready = True
self.rebuild()
def _onSettingChangeTimerFinished(self):
def _onSettingChangeTimerFinished(self) -> None:
if not self._global_container_stack:
return
rebuild_me = False
update_disallowed_areas = False
update_raft_thickness = False
update_extra_z_clearance = True
for setting_key in self._changed_settings_since_last_rebuild:
if setting_key == "print_sequence":
machine_height = self._global_container_stack.getProperty("machine_height", "value")
if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
@ -620,33 +651,26 @@ class BuildVolume(SceneNode):
self._height = self._global_container_stack.getProperty("machine_height", "value")
self._build_volume_message.hide()
update_disallowed_areas = True
rebuild_me = True
# sometimes the machine size or shape settings are adjusted on the active machine, we should reflect this
if setting_key in self._machine_settings:
self._height = self._global_container_stack.getProperty("machine_height", "value")
self._width = self._global_container_stack.getProperty("machine_width", "value")
self._depth = self._global_container_stack.getProperty("machine_depth", "value")
self._shape = self._global_container_stack.getProperty("machine_shape", "value")
self._updateMachineSizeProperties()
update_extra_z_clearance = True
update_disallowed_areas = True
rebuild_me = True
if setting_key in self._skirt_settings + self._prime_settings + self._tower_settings + self._ooze_shield_settings + self._distance_settings + self._extruder_settings:
if setting_key in self._disallowed_area_settings:
update_disallowed_areas = True
rebuild_me = True
if setting_key in self._raft_settings:
update_raft_thickness = True
rebuild_me = True
if setting_key in self._extra_z_settings:
update_extra_z_clearance = True
rebuild_me = True
if setting_key in self._limit_to_extruder_settings:
update_disallowed_areas = True
rebuild_me = True
rebuild_me = update_extra_z_clearance or update_disallowed_areas or update_raft_thickness
# We only want to update all of them once.
if update_disallowed_areas:
@ -656,7 +680,7 @@ class BuildVolume(SceneNode):
self._updateRaftThickness()
if update_extra_z_clearance:
self._updateExtraZClearance()
self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
if rebuild_me:
self.rebuild()
@ -664,7 +688,7 @@ class BuildVolume(SceneNode):
# We just did a rebuild, reset the list.
self._changed_settings_since_last_rebuild = []
def _onSettingPropertyChanged(self, setting_key: str, property_name: str):
def _onSettingPropertyChanged(self, setting_key: str, property_name: str) -> None:
if property_name != "value":
return
@ -675,6 +699,14 @@ class BuildVolume(SceneNode):
def hasErrors(self) -> bool:
return self._has_errors
def _updateMachineSizeProperties(self) -> None:
if not self._global_container_stack:
return
self._height = self._global_container_stack.getProperty("machine_height", "value")
self._width = self._global_container_stack.getProperty("machine_width", "value")
self._depth = self._global_container_stack.getProperty("machine_depth", "value")
self._shape = self._global_container_stack.getProperty("machine_shape", "value")
## Calls _updateDisallowedAreas and makes sure the changes appear in the
# scene.
#
@ -686,10 +718,10 @@ class BuildVolume(SceneNode):
def _updateDisallowedAreasAndRebuild(self):
self._updateDisallowedAreas()
self._updateRaftThickness()
self._updateExtraZClearance()
self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
self.rebuild()
def _updateDisallowedAreas(self):
def _updateDisallowedAreas(self) -> None:
if not self._global_container_stack:
return
@ -836,9 +868,10 @@ class BuildVolume(SceneNode):
# \param used_extruders The extruder stacks to generate disallowed areas
# for.
# \return A dictionary with for each used extruder ID the prime areas.
def _computeDisallowedAreasPrimeBlob(self, border_size, used_extruders):
result = {}
def _computeDisallowedAreasPrimeBlob(self, border_size: float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]:
result = {} # type: Dict[str, List[Polygon]]
if not self._global_container_stack:
return result
machine_width = self._global_container_stack.getProperty("machine_width", "value")
machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
for extruder in used_extruders:
@ -846,13 +879,13 @@ class BuildVolume(SceneNode):
prime_x = extruder.getProperty("extruder_prime_pos_x", "value")
prime_y = -extruder.getProperty("extruder_prime_pos_y", "value")
#Ignore extruder prime position if it is not set or if blob is disabled
# Ignore extruder prime position if it is not set or if blob is disabled
if (prime_x == 0 and prime_y == 0) or not prime_blob_enabled:
result[extruder.getId()] = []
continue
if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
prime_x = prime_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
prime_x = prime_x - machine_width / 2 # Offset by half machine_width and _depth to put the origin in the front-left.
prime_y = prime_y + machine_depth / 2
prime_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE)
@ -1008,14 +1041,86 @@ class BuildVolume(SceneNode):
# stack.
#
# \return A sequence of setting values, one for each extruder.
def _getSettingFromAllExtruders(self, setting_key):
def _getSettingFromAllExtruders(self, setting_key: str) -> List[Any]:
all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "value")
all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type")
for i in range(len(all_values)):
if not all_values[i] and (all_types[i] == "int" or all_types[i] == "float"):
for i, (setting_value, setting_type) in enumerate(zip(all_values, all_types)):
if not setting_value and (setting_type == "int" or setting_type == "float"):
all_values[i] = 0
return all_values
def _calculateBedAdhesionSize(self, used_extruders):
if self._global_container_stack is None:
return
container_stack = self._global_container_stack
adhesion_type = container_stack.getProperty("adhesion_type", "value")
skirt_brim_line_width = self._global_container_stack.getProperty("skirt_brim_line_width", "value")
initial_layer_line_width_factor = self._global_container_stack.getProperty("initial_layer_line_width_factor", "value")
# Use brim width if brim is enabled OR the prime tower has a brim.
if adhesion_type == "brim" or (self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and adhesion_type != "raft"):
brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value")
bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0
for extruder_stack in used_extruders:
bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
# We don't create an additional line for the extruder we're printing the brim with.
bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
elif adhesion_type == "skirt": # No brim? Also not on prime tower? Then use whatever the adhesion type is saying: Skirt, raft or none.
skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value")
skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value")
bed_adhesion_size = skirt_distance + (
skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
for extruder_stack in used_extruders:
bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
# We don't create an additional line for the extruder we're printing the skirt with.
bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
elif adhesion_type == "raft":
bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value")
elif adhesion_type == "none":
bed_adhesion_size = 0
else:
raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?")
max_length_available = 0.5 * min(
self._global_container_stack.getProperty("machine_width", "value"),
self._global_container_stack.getProperty("machine_depth", "value")
)
bed_adhesion_size = min(bed_adhesion_size, max_length_available)
return bed_adhesion_size
def _calculateFarthestShieldDistance(self, container_stack):
farthest_shield_distance = 0
if container_stack.getProperty("draft_shield_enabled", "value"):
farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value"))
if container_stack.getProperty("ooze_shield_enabled", "value"):
farthest_shield_distance = max(farthest_shield_distance,container_stack.getProperty("ooze_shield_dist", "value"))
return farthest_shield_distance
def _calculateSupportExpansion(self, container_stack):
support_expansion = 0
support_enabled = self._global_container_stack.getProperty("support_enable", "value")
support_offset = self._global_container_stack.getProperty("support_offset", "value")
if support_enabled and support_offset:
support_expansion += support_offset
return support_expansion
def _calculateMoveFromWallRadius(self, used_extruders):
move_from_wall_radius = 0 # Moves that start from outer wall.
all_values = [move_from_wall_radius]
all_values.extend(self._getSettingFromAllExtruders("infill_wipe_dist"))
move_from_wall_radius = max(all_values)
avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts", "value") for stack in used_extruders]
travel_avoid_distance_per_extruder = [stack.getProperty("travel_avoid_distance", "value") for stack in used_extruders]
for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): # For each extruder (or just global).
if avoid_other_parts_enabled:
move_from_wall_radius = max(move_from_wall_radius, avoid_distance)
return move_from_wall_radius
## Calculate the disallowed radius around the edge.
#
# This disallowed radius is to allow for space around the models that is
@ -1032,65 +1137,10 @@ class BuildVolume(SceneNode):
if container_stack.getProperty("print_sequence", "value") == "one_at_a_time":
return 0.1 # Return a very small value, so we do draw disallowed area's near the edges.
adhesion_type = container_stack.getProperty("adhesion_type", "value")
skirt_brim_line_width = self._global_container_stack.getProperty("skirt_brim_line_width", "value")
initial_layer_line_width_factor = self._global_container_stack.getProperty("initial_layer_line_width_factor", "value")
#Use brim width if brim is enabled OR the prime tower has a brim.
if adhesion_type == "brim" or (self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and
adhesion_type != "raft"):
brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value")
bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0
for extruder_stack in used_extruders:
bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
# We don't create an additional line for the extruder we're printing the brim with.
bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
elif adhesion_type == "skirt": #No brim? Also not on prime tower? Then use whatever the adhesion type is saying: Skirt, raft or none.
skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value")
skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value")
bed_adhesion_size = skirt_distance + (skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
for extruder_stack in used_extruders:
bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
# We don't create an additional line for the extruder we're printing the skirt with.
bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
elif adhesion_type == "raft":
bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value")
elif adhesion_type == "none":
bed_adhesion_size = 0
else:
raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?")
max_length_available = 0.5 * min(
self._global_container_stack.getProperty("machine_width", "value"),
self._global_container_stack.getProperty("machine_depth", "value")
)
bed_adhesion_size = min(bed_adhesion_size, max_length_available)
support_expansion = 0
support_enabled = self._global_container_stack.getProperty("support_enable", "value")
support_offset = self._global_container_stack.getProperty("support_offset", "value")
if support_enabled and support_offset:
support_expansion += support_offset
farthest_shield_distance = 0
if container_stack.getProperty("draft_shield_enabled", "value"):
farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value"))
if container_stack.getProperty("ooze_shield_enabled", "value"):
farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("ooze_shield_dist", "value"))
move_from_wall_radius = 0 # Moves that start from outer wall.
move_from_wall_radius = max(move_from_wall_radius, max(self._getSettingFromAllExtruders("infill_wipe_dist")))
avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts","value") for stack in used_extruders]
travel_avoid_distance_per_extruder = [stack.getProperty("travel_avoid_distance", "value") for stack in used_extruders]
for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): #For each extruder (or just global).
if avoid_other_parts_enabled:
move_from_wall_radius = max(move_from_wall_radius, avoid_distance)
bed_adhesion_size = self._calculateBedAdhesionSize(used_extruders)
support_expansion = self._calculateSupportExpansion(self._global_container_stack)
farthest_shield_distance = self._calculateFarthestShieldDistance(self._global_container_stack)
move_from_wall_radius = self._calculateMoveFromWallRadius(used_extruders)
# 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.
@ -1111,3 +1161,4 @@ class BuildVolume(SceneNode):
_distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports"]
_extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
_limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"]
_disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings

View file

@ -839,7 +839,6 @@ class CuraApplication(QtApplication):
if diagonal < 1: #No printer added yet. Set a default camera distance for normal-sized printers.
diagonal = 375
camera.setPosition(Vector(-80, 250, 700) * diagonal / 375)
camera.setPerspective(True)
camera.lookAt(Vector(0, 0, 0))
controller.getScene().setActiveCamera("3d")

View file

@ -62,6 +62,14 @@ class DiscoveredPrinter(QObject):
self._machine_type = machine_type
self.machineTypeChanged.emit()
# Checks if the given machine type name in the available machine list.
# The machine type is a code name such as "ultimaker_3", while the machine type name is the human-readable name of
# the machine type, which is "Ultimaker 3" for "ultimaker_3".
def _hasHumanReadableMachineTypeName(self, machine_type_name: str) -> bool:
from cura.CuraApplication import CuraApplication
results = CuraApplication.getInstance().getContainerRegistry().findDefinitionContainersMetadata(name = machine_type_name)
return len(results) > 0
# Human readable machine type string
@pyqtProperty(str, notify = machineTypeChanged)
def readableMachineType(self) -> str:
@ -70,24 +78,30 @@ class DiscoveredPrinter(QObject):
# In ClusterUM3OutputDevice, when it updates a printer information, it updates the machine type using the field
# "machine_variant", and for some reason, it's not the machine type ID/codename/... but a human-readable string
# like "Ultimaker 3". The code below handles this case.
if machine_manager.hasHumanReadableMachineTypeName(self._machine_type):
if self._hasHumanReadableMachineTypeName(self._machine_type):
readable_type = self._machine_type
else:
readable_type = machine_manager.getMachineTypeNameFromId(self._machine_type)
readable_type = self._getMachineTypeNameFromId(self._machine_type)
if not readable_type:
readable_type = catalog.i18nc("@label", "Unknown")
return readable_type
@pyqtProperty(bool, notify = machineTypeChanged)
def isUnknownMachineType(self) -> bool:
from cura.CuraApplication import CuraApplication
machine_manager = CuraApplication.getInstance().getMachineManager()
if machine_manager.hasHumanReadableMachineTypeName(self._machine_type):
if self._hasHumanReadableMachineTypeName(self._machine_type):
readable_type = self._machine_type
else:
readable_type = machine_manager.getMachineTypeNameFromId(self._machine_type)
readable_type = self._getMachineTypeNameFromId(self._machine_type)
return not readable_type
def _getMachineTypeNameFromId(self, machine_type_id: str) -> str:
machine_type_name = ""
from cura.CuraApplication import CuraApplication
results = CuraApplication.getInstance().getContainerRegistry().findDefinitionContainersMetadata(id = machine_type_id)
if results:
machine_type_name = results[0]["name"]
return machine_type_name
@pyqtProperty(QObject, constant = True)
def device(self) -> "NetworkedPrinterOutputDevice":
return self._device

View file

@ -202,9 +202,6 @@ class QualityManager(QObject):
def getQualityGroups(self, machine: "GlobalStack") -> Dict[str, QualityGroup]:
machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
# This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks
has_machine_specific_qualities = machine.getHasMachineQuality()
# To find the quality container for the GlobalStack, check in the following fall-back manner:
# (1) the machine-specific node
# (2) the generic node

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from copy import deepcopy
@ -14,6 +14,7 @@ import cura.CuraApplication #To get the build plate.
from cura.Settings.ExtruderStack import ExtruderStack #For typing.
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator #For per-object settings.
## Scene nodes that are models are only seen when selecting the corresponding build plate
# Note that many other nodes can just be UM SceneNode objects.
class CuraSceneNode(SceneNode):
@ -85,16 +86,6 @@ class CuraSceneNode(SceneNode):
1.0
]
## Return if the provided bbox collides with the bbox of this scene node
def collidesWithBbox(self, check_bbox: AxisAlignedBox) -> bool:
bbox = self.getBoundingBox()
if bbox is not None:
# Mark the node as outside the build volume if the bounding box test fails.
if check_bbox.intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
return True
return False
## Return if any area collides with the convex hull of this scene node
def collidesWithArea(self, areas: List[Polygon]) -> bool:
convex_hull = self.callDecoration("getConvexHull")

View file

@ -180,7 +180,7 @@ class ExtruderManager(QObject):
# \param setting_key \type{str} The setting to get the property of.
# \param property \type{str} The property to get.
# \return \type{List} the list of results
def getAllExtruderSettings(self, setting_key: str, prop: str) -> List:
def getAllExtruderSettings(self, setting_key: str, prop: str) -> List[Any]:
result = []
for extruder_stack in self.getActiveExtruderStacks():

View file

@ -264,18 +264,18 @@ class GlobalStack(CuraContainerStack):
def getHeadAndFansCoordinates(self):
return self.getProperty("machine_head_with_fans_polygon", "value")
def getHasMaterials(self) -> bool:
@pyqtProperty(int, constant=True)
def hasMaterials(self):
return parseBool(self.getMetaDataEntry("has_materials", False))
def getHasVariants(self) -> bool:
@pyqtProperty(int, constant=True)
def hasVariants(self):
return parseBool(self.getMetaDataEntry("has_variants", False))
def getHasVariantsBuildPlates(self) -> bool:
@pyqtProperty(int, constant=True)
def hasVariantBuildplates(self) -> bool:
return parseBool(self.getMetaDataEntry("has_variant_buildplates", False))
def getHasMachineQuality(self) -> bool:
return parseBool(self.getMetaDataEntry("has_machine_quality", False))
## Get default firmware file name if one is specified in the firmware
@pyqtSlot(result = str)
def getDefaultFirmwareName(self) -> str:

View file

@ -538,6 +538,7 @@ class MachineManager(QObject):
return bool(self._printer_output_devices)
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
@deprecated("use Cura.MachineManager.activeMachine.configuredConnectionTypes instead", "4.2")
def activeMachineHasRemoteConnection(self) -> bool:
if self._global_container_stack:
has_remote_connection = False
@ -816,21 +817,24 @@ class MachineManager(QObject):
self.removeMachine(hidden_containers[0].getId())
@pyqtProperty(bool, notify = globalContainerChanged)
@deprecated("use Cura.MachineManager.activeMachine.hasMaterials instead", "4.2")
def hasMaterials(self) -> bool:
if self._global_container_stack:
return self._global_container_stack.getHasMaterials()
return self._global_container_stack.hasMaterials
return False
@pyqtProperty(bool, notify = globalContainerChanged)
@deprecated("use Cura.MachineManager.activeMachine.hasVariants instead", "4.2")
def hasVariants(self) -> bool:
if self._global_container_stack:
return self._global_container_stack.getHasVariants()
return self._global_container_stack.hasVariants
return False
@pyqtProperty(bool, notify = globalContainerChanged)
@deprecated("use Cura.MachineManager.activeMachine.hasVariantBuildplates instead", "4.2")
def hasVariantBuildplates(self) -> bool:
if self._global_container_stack:
return self._global_container_stack.getHasVariantsBuildPlates()
return self._global_container_stack.hasVariantBuildplates
return False
## The selected buildplate is compatible if it is compatible with all the materials in all the extruders
@ -917,9 +921,8 @@ class MachineManager(QObject):
# Apply quality changes that are incompatible to user changes, so we do not change the quality changes itself.
self._global_container_stack.userChanges.setProperty(setting_key, "value", self._default_extruder_position)
if add_user_changes:
caution_message = Message(catalog.i18nc(
"@info:generic",
"Settings have been changed to match the current availability of extruders: [%s]" % ", ".join(add_user_changes)),
caution_message = Message(
catalog.i18nc("@info:message Followed by a list of settings.", "Settings have been changed to match the current availability of extruders:") + " [{settings_list}]".format(settings_list = ", ".join(add_user_changes)),
lifetime = 0,
title = catalog.i18nc("@info:title", "Settings updated"))
caution_message.show()
@ -984,6 +987,7 @@ class MachineManager(QObject):
self.forceUpdateAllSettings()
@pyqtSlot(int, result = QObject)
@deprecated("use Cura.MachineManager.activeMachine.extruders instead", "4.2")
def getExtruder(self, position: int) -> Optional[ExtruderStack]:
if self._global_container_stack:
return self._global_container_stack.extruders.get(str(position))
@ -1097,6 +1101,7 @@ class MachineManager(QObject):
container.removeInstance(setting_name)
@pyqtProperty("QVariantList", notify = globalContainerChanged)
@deprecated("use Cura.MachineManager.activeMachine.extruders instead", "4.2")
def currentExtruderPositions(self) -> List[str]:
if self._global_container_stack is None:
return []
@ -1642,21 +1647,6 @@ class MachineManager(QObject):
return abbr_machine
# Checks if the given machine type name in the available machine list.
# The machine type is a code name such as "ultimaker_3", while the machine type name is the human-readable name of
# the machine type, which is "Ultimaker 3" for "ultimaker_3".
def hasHumanReadableMachineTypeName(self, machine_type_name: str) -> bool:
results = self._container_registry.findDefinitionContainersMetadata(name = machine_type_name)
return len(results) > 0
@pyqtSlot(str, result = str)
def getMachineTypeNameFromId(self, machine_type_id: str) -> str:
machine_type_name = ""
results = self._container_registry.findDefinitionContainersMetadata(id = machine_type_id)
if results:
machine_type_name = results[0]["name"]
return machine_type_name
# Gets all machines that belong to the given group_id.
def getMachinesInGroup(self, group_id: str) -> List["GlobalStack"]:
return self._container_registry.findContainerStacks(type = "machine", group_id = group_id)

View file

@ -32,7 +32,8 @@ if not known_args["debug"]:
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/" + CuraAppName)
if hasattr(sys, "frozen"):
# Do not redirect stdout and stderr to files if we are running CLI.
if hasattr(sys, "frozen") and "cli" not in os.path.basename(sys.argv[0]).lower():
dirpath = get_cura_dir_path()
os.makedirs(dirpath, exist_ok = True)
sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8")

View file

@ -0,0 +1,121 @@
{
"name": "Erzay3D",
"version": 2,
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Alexander Kirsanov",
"manufacturer": "Robokinetika",
"category": "Other",
"file_formats": "text/x-gcode",
"machine_extruder_trains":
{
"0": "erzay3d_extruder_0"
}
},
"overrides": {
"machine_start_gcode" : { "default_value": "G28\nG1 Z15.0 F6000\nG92 E0" },
"machine_shape": { "default_value": "elliptic"},
"machine_name": { "default_value": "Erzay3D" },
"machine_depth": { "default_value": 210 },
"machine_width": { "default_value": 210 },
"machine_height": { "default_value": 230 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_center_is_zero": { "default_value": true },
"machine_extruder_count": { "default_value": 1 },
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 },
"machine_heated_bed": { "default_value": true },
"material_bed_temp_wait": { "default_value": true },
"material_print_temp_wait": { "default_value": true },
"material_print_temp_prepend": { "default_value": true },
"machine_buildplate_type": { "default_value": "glass" },
"machine_nozzle_head_distance": { "default_value": 2.5 },
"machine_heat_zone_length": { "default_value": 12.5 },
"machine_max_feedrate_x": { "default_value": 200 },
"machine_max_feedrate_y": { "default_value": 200 },
"machine_max_feedrate_z": { "default_value": 200 },
"machine_max_feedrate_e": { "default_value": 50 },
"machine_max_acceleration_x": { "default_value": 3000 },
"machine_max_acceleration_y": { "default_value": 3000 },
"machine_max_acceleration_z": { "default_value": 3000 },
"machine_max_acceleration_e": { "default_value": 3000 },
"machine_acceleration": { "default_value": 1000 },
"machine_max_jerk_xy": { "default_value": 10 },
"machine_max_jerk_z": { "default_value": 10 },
"machine_max_jerk_e": { "default_value": 10 },
"machine_steps_per_mm_x": { "default_value": 1600 },
"machine_steps_per_mm_y": { "default_value": 1600 },
"machine_steps_per_mm_z": { "default_value": 1600 },
"machine_steps_per_mm_e": { "default_value": 174 },
"machine_feeder_wheel_diameter": { "default_value": 12 },
"layer_height": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.2 },
"ironing_pattern": { "default_value": "concentric" },
"ironing_flow": { "default_value": 7.0 },
"roofing_pattern": { "default_value": "concentric" },
"infill_sparse_density": { "default_value": 20 },
"infill_line_distance": { "default_value": 4 },
"default_material_print_temperature": { "default_value": 220 },
"material_print_temperature": { "default_value": 220 },
"material_print_temperature_layer_0": { "default_value": 220 },
"material_initial_print_temperature": { "default_value": 220 },
"material_final_print_temperature": { "default_value": 220 },
"retraction_amount": { "default_value": 4 },
"speed_print": { "default_value": 40 },
"speed_infill": { "default_value": 60 },
"speed_wall": { "default_value": 20 },
"speed_wall_0": { "default_value": 20 },
"speed_wall_x": { "default_value": 40 },
"speed_roofing": { "default_value": 20 },
"speed_topbottom": { "default_value": 20 },
"speed_support": { "default_value": 40 },
"speed_support_infill": { "default_value": 40 },
"speed_support_interface": { "default_value": 25 },
"speed_support_roof": { "default_value": 25 },
"speed_support_bottom": { "default_value": 25 },
"speed_prime_tower": { "default_value": 40 },
"speed_travel": { "default_value": 100 },
"speed_layer_0": { "default_value": 20 },
"speed_print_layer_0": { "default_value": 20 },
"speed_travel_layer_0": { "default_value": 80 },
"skirt_brim_speed": { "default_value": 20 },
"speed_equalize_flow_enabled": { "default_value": true },
"speed_equalize_flow_max": { "default_value": 100 },
"acceleration_print": { "default_value": 1000 },
"acceleration_infill": { "default_value": 3000 },
"acceleration_wall": { "default_value": 1000 },
"acceleration_wall_0": { "default_value": 1000 },
"acceleration_wall_x": { "default_value": 1000 },
"acceleration_roofing": { "default_value": 1000 },
"acceleration_topbottom": { "default_value": 1000 },
"acceleration_support": { "default_value": 1000 },
"acceleration_support_infill": { "default_value": 1000 },
"acceleration_support_interface": { "default_value": 1000 },
"acceleration_support_roof": { "default_value": 1000 },
"acceleration_support_bottom": { "default_value": 1000 },
"acceleration_prime_tower": { "default_value": 1000 },
"acceleration_travel": { "default_value": 1500 },
"acceleration_layer_0": { "default_value": 1000 },
"acceleration_print_layer_0": { "default_value": 1000 },
"acceleration_travel_layer_0": { "default_value": 1000 },
"acceleration_skirt_brim": { "default_value": 1000 },
"jerk_print": { "default_value": 10 },
"support_angle": { "default_value": 65 },
"support_brim_enable": { "default_value": true },
"adhesion_type": { "default_value": "skirt" },
"brim_outside_only": { "default_value": false },
"meshfix_maximum_resolution": { "default_value": 0.05 }
}
}

View file

@ -892,7 +892,7 @@
"maximum_value_warning": "3 * machine_nozzle_size",
"default_value": 0.4,
"type": "float",
"enabled": "support_enable",
"enabled": "(support_enable or support_tree_enable)",
"value": "line_width",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
@ -908,7 +908,7 @@
"minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
"enabled": "support_enable and support_interface_enable",
"enabled": "(support_enable or support_tree_enable) and support_interface_enable",
"limit_to_extruder": "support_interface_extruder_nr",
"value": "line_width",
"settable_per_mesh": false,
@ -925,7 +925,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
"enabled": "support_enable and support_roof_enable",
"enabled": "(support_enable or support_tree_enable) and support_roof_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false,
@ -941,7 +941,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
"enabled": "support_enable and support_bottom_enable",
"enabled": "(support_enable or support_tree_enable) and support_bottom_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false,
@ -2070,7 +2070,7 @@
"maximum_value_warning": "285",
"enabled": true,
"settable_per_mesh": false,
"settable_per_extruder": true
"settable_per_extruder": false
},
"material_print_temperature":
{
@ -2401,7 +2401,7 @@
"description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure.",
"type": "bool",
"default_value": true,
"enabled": "retraction_enable and support_enable",
"enabled": "retraction_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@ -2619,7 +2619,7 @@
"maximum_value_warning": "150",
"default_value": 60,
"value": "speed_print",
"enabled": "support_enable",
"enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true,
@ -2636,7 +2636,7 @@
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"value": "speed_support",
"enabled": "support_enable",
"enabled": "support_enable or support_tree_enable",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -2651,7 +2651,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"enabled": "support_interface_enable and support_enable",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"value": "speed_support / 1.5",
"settable_per_mesh": false,
@ -2668,7 +2668,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"enabled": "support_roof_enable and support_enable",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false,
@ -2684,7 +2684,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"enabled": "support_bottom_enable and support_enable",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false,
@ -2972,7 +2972,7 @@
"maximum_value_warning": "10000",
"default_value": 3000,
"value": "acceleration_print",
"enabled": "resolveOrValue('acceleration_enabled') and support_enable",
"enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true,
@ -2989,7 +2989,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and support_enable",
"enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3005,7 +3005,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and support_enable",
"enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
@ -3022,7 +3022,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "acceleration_enabled and support_roof_enable and support_enable",
"enabled": "acceleration_enabled and support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3038,7 +3038,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "acceleration_enabled and support_bottom_enable and support_enable",
"enabled": "acceleration_enabled and support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3257,7 +3257,7 @@
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
"enabled": "resolveOrValue('jerk_enabled') and support_enable",
"enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_extruder_nr",
@ -3273,7 +3273,7 @@
"value": "jerk_support",
"minimum_value": "0",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_enable",
"enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3288,7 +3288,7 @@
"value": "jerk_support",
"minimum_value": "0",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and support_enable",
"enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
@ -3304,7 +3304,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and support_enable",
"enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3319,7 +3319,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and support_enable",
"enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3970,7 +3970,7 @@
"minimum_value": "-180",
"maximum_value": "180",
"default_value": 0,
"enabled": "support_enable and support_pattern != 'concentric' and support_infill_rate > 0",
"enabled": "(support_enable or support_tree_enable) and support_pattern != 'concentric' and support_infill_rate > 0",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@ -3995,7 +3995,7 @@
"default_value": 8.0,
"minimum_value": "0.0",
"maximum_value_warning": "50.0",
"enabled": "support_enable",
"enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr",
@ -4010,7 +4010,7 @@
"minimum_value": "0",
"maximum_value_warning": "50 / skirt_brim_line_width",
"value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))",
"enabled": "support_enable",
"enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr"
@ -4132,7 +4132,7 @@
"support_join_distance":
{
"label": "Support Join Distance",
"description": "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one.",
"description": "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one.",
"unit": "mm",
"type": "float",
"default_value": 2.0,
@ -4299,7 +4299,7 @@
"minimum_value": "0",
"maximum_value_warning": "support_interface_height",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and support_enable",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
},
"support_interface_density":
@ -4457,7 +4457,7 @@
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and support_enable",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true,
"children":
{
@ -4472,7 +4472,7 @@
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and support_enable",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
},
"minimum_bottom_area":
@ -4486,7 +4486,7 @@
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and support_enable",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
}
}
@ -4541,7 +4541,7 @@
"description": "When enabled, the print cooling fan speed is altered for the skin regions immediately above the support.",
"type": "bool",
"default_value": false,
"enabled": "support_enable",
"enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false
},
"support_supported_skin_fan_speed":
@ -4553,7 +4553,7 @@
"maximum_value": "100",
"default_value": 100,
"type": "float",
"enabled": "support_enable and support_fan_enable",
"enabled": "(support_enable or support_tree_enable) and support_fan_enable",
"settable_per_mesh": false
},
"support_use_towers":
@ -4775,7 +4775,7 @@
"description": "Enforce brim to be printed around the model even if that space would otherwise be occupied by support. This replaces some regions of the first layer of support by brim regions.",
"type": "bool",
"default_value": true,
"enabled": "resolveOrValue('adhesion_type') == 'brim' and support_enable",
"enabled": "resolveOrValue('adhesion_type') == 'brim' and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr"
@ -5496,7 +5496,7 @@
"description": "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle.",
"type": "bool",
"default_value": true,
"enabled": "not support_enable",
"enabled": "not (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": false
}
@ -6229,7 +6229,7 @@
"support_conical_enabled":
{
"label": "Enable Conical Support",
"description": "Experimental feature: Make support areas smaller at the bottom than at the overhang.",
"description": "Make support areas smaller at the bottom than at the overhang.",
"type": "bool",
"default_value": false,
"enabled": "support_enable",

View file

@ -13,7 +13,7 @@
}
},
"overrides": {
"machine_name": {
"machine_name": {
"default_value": "Tevo Tornado"
},
"machine_width": {
@ -25,8 +25,8 @@
"machine_depth": {
"default_value": 300
},
"machine_center_is_zero": {
"default_value": false
"machine_center_is_zero": {
"default_value": false
},
"machine_head_polygon": {
"default_value": [
@ -73,18 +73,36 @@
"value": "30"
},
"acceleration_enabled": {
"default_value": false
"default_value": true
},
"machine_acceleration": {
"default_value": 1500
"acceleration_print": {
"default_value": 500
},
"acceleration_travel": {
"value": 500
},
"acceleration_travel_layer_0": {
"value": 500
},
"machine_acceleration": {
"default_value": 1500
},
"jerk_enabled": {
"default_value": false
"default_value": true
},
"machine_max_jerk_xy": {
"default_value": 6
"jerk_print": {
"default_value": 8
},
"machine_gcode_flavor": {
"jerk_travel": {
"value": 8
},
"jerk_travel_layer_0": {
"value": 8
},
"machine_max_jerk_xy": {
"default_value": 6
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {

View file

@ -0,0 +1,16 @@
{
"id": "erzay3d_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "erzay3d",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }
}
}

View file

@ -67,6 +67,15 @@ Button
anchors.verticalCenter: parent.verticalCenter
}
TextMetrics
{
id: buttonTextMetrics
text: buttonText.text
font: buttonText.font
elide: buttonText.elide
elideWidth: buttonText.width
}
Label
{
id: buttonText
@ -124,7 +133,7 @@ Button
Cura.ToolTip
{
id: tooltip
visible: button.hovered
visible: button.hovered && buttonTextMetrics.elidedText != buttonText.text
}
BusyIndicator

View file

@ -101,7 +101,7 @@ Item
Action
{
id: redoAction;
text: catalog.i18nc("@action:inmenu menubar:edit","&Redo");
text: catalog.i18nc("@action:inmenu menubar:edit", "&Redo");
iconName: "edit-redo";
shortcut: StandardKey.Redo;
onTriggered: UM.OperationStack.redo();
@ -110,65 +110,65 @@ Item
Action
{
id: quitAction;
text: catalog.i18nc("@action:inmenu menubar:file","&Quit");
iconName: "application-exit";
shortcut: StandardKey.Quit;
id: quitAction
text: catalog.i18nc("@action:inmenu menubar:file","&Quit")
iconName: "application-exit"
shortcut: StandardKey.Quit
}
Action
{
id: view3DCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","3D View");
onTriggered: UM.Controller.rotateView("3d", 0);
id: view3DCameraAction
text: catalog.i18nc("@action:inmenu menubar:view", "3D View")
onTriggered: UM.Controller.setCameraRotation("3d", 0)
}
Action
{
id: viewFrontCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","Front View");
onTriggered: UM.Controller.rotateView("home", 0);
id: viewFrontCameraAction
text: catalog.i18nc("@action:inmenu menubar:view", "Front View")
onTriggered: UM.Controller.setCameraRotation("home", 0)
}
Action
{
id: viewTopCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","Top View");
onTriggered: UM.Controller.rotateView("y", 90);
id: viewTopCameraAction
text: catalog.i18nc("@action:inmenu menubar:view", "Top View")
onTriggered: UM.Controller.setCameraRotation("y", 90)
}
Action
{
id: viewLeftSideCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","Left Side View");
onTriggered: UM.Controller.rotateView("x", 90);
id: viewLeftSideCameraAction
text: catalog.i18nc("@action:inmenu menubar:view", "Left Side View")
onTriggered: UM.Controller.setCameraRotation("x", 90)
}
Action
{
id: viewRightSideCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","Right Side View");
onTriggered: UM.Controller.rotateView("x", -90);
id: viewRightSideCameraAction
text: catalog.i18nc("@action:inmenu menubar:view", "Right Side View")
onTriggered: UM.Controller.setCameraRotation("x", -90)
}
Action
{
id: preferencesAction;
text: catalog.i18nc("@action:inmenu","Configure Cura...");
iconName: "configure";
id: preferencesAction
text: catalog.i18nc("@action:inmenu", "Configure Cura...")
iconName: "configure"
}
Action
{
id: addMachineAction;
text: catalog.i18nc("@action:inmenu menubar:printer","&Add Printer...");
id: addMachineAction
text: catalog.i18nc("@action:inmenu menubar:printer", "&Add Printer...")
}
Action
{
id: settingsAction;
text: catalog.i18nc("@action:inmenu menubar:printer","Manage Pr&inters...");
iconName: "configure";
id: settingsAction
text: catalog.i18nc("@action:inmenu menubar:printer", "Manage Pr&inters...")
iconName: "configure"
}
Action

View file

@ -95,6 +95,10 @@ UM.PreferencesPage
UM.Preferences.resetPreference("view/top_layer_count");
topLayerCountCheckbox.checked = boolCheck(UM.Preferences.getValue("view/top_layer_count"))
UM.Preferences.resetPreference("general/camera_perspective_mode")
var defaultCameraMode = UM.Preferences.getValue("general/camera_perspective_mode")
setDefaultCameraMode(defaultCameraMode)
UM.Preferences.resetPreference("cura/choice_on_profile_override")
setDefaultDiscardOrKeepProfile(UM.Preferences.getValue("cura/choice_on_profile_override"))
@ -330,7 +334,8 @@ UM.PreferencesPage
}
}
UM.TooltipArea {
UM.TooltipArea
{
width: childrenRect.width;
height: childrenRect.height;
text: catalog.i18nc("@info:tooltip", "Moves the camera so the model is in the center of the view when a model is selected")
@ -344,7 +349,8 @@ UM.PreferencesPage
}
}
UM.TooltipArea {
UM.TooltipArea
{
width: childrenRect.width;
height: childrenRect.height;
text: catalog.i18nc("@info:tooltip", "Should the default zoom behavior of cura be inverted?")
@ -436,6 +442,50 @@ UM.PreferencesPage
}
}
UM.TooltipArea
{
width: childrenRect.width
height: childrenRect.height
text: catalog.i18nc("@info:tooltip", "What type of camera rendering should be used?")
Column
{
spacing: 4 * screenScaleFactor
Label
{
text: catalog.i18nc("@window:text", "Camera rendering: ")
}
ComboBox
{
id: cameraComboBox
model: ListModel
{
id: comboBoxList
Component.onCompleted: {
append({ text: catalog.i18n("Perspective"), code: "perspective" })
append({ text: catalog.i18n("Orthogonal"), code: "orthogonal" })
}
}
currentIndex:
{
var code = UM.Preferences.getValue("general/camera_perspective_mode");
for(var i = 0; i < comboBoxList.count; ++i)
{
if(model.get(i).code == code)
{
return i
}
}
return 0
}
onActivated: UM.Preferences.setValue("general/camera_perspective_mode", model.get(index).code)
}
}
}
Item
{
//: Spacer

View file

@ -6,7 +6,7 @@ import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.4 as UM
import Cura 1.1 as Cura
// A row of buttons that control the view direction
Row
{
@ -19,30 +19,30 @@ Row
ViewOrientationButton
{
iconSource: UM.Theme.getIcon("view_3d")
onClicked: UM.Controller.rotateView("3d", 0)
onClicked: Cura.Actions.view3DCamera.trigger()
}
ViewOrientationButton
{
iconSource: UM.Theme.getIcon("view_front")
onClicked: UM.Controller.rotateView("home", 0)
onClicked: Cura.Actions.viewFrontCamera.trigger()
}
ViewOrientationButton
{
iconSource: UM.Theme.getIcon("view_top")
onClicked: UM.Controller.rotateView("y", 90)
onClicked: Cura.Actions.viewTopCamera.trigger()
}
ViewOrientationButton
{
iconSource: UM.Theme.getIcon("view_left")
onClicked: UM.Controller.rotateView("x", 90)
onClicked: Cura.Actions.viewLeftSideCamera.trigger()
}
ViewOrientationButton
{
iconSource: UM.Theme.getIcon("view_right")
onClicked: UM.Controller.rotateView("x", -90)
onClicked: Cura.Actions.viewRightSideCamera.trigger()
}
}

View file

@ -193,19 +193,20 @@
"xray": [26, 26, 62, 255],
"xray_error": [255, 0, 0, 255],
"layerview_ghost": [32, 32, 32, 96],
"layerview_none": [255, 255, 255, 255],
"layerview_inset_0": [255, 0, 0, 255],
"layerview_inset_x": [0, 255, 0, 255],
"layerview_skin": [255, 255, 0, 255],
"layerview_support": [0, 255, 255, 255],
"layerview_skirt": [0, 255, 255, 255],
"layerview_infill": [255, 192, 0, 255],
"layerview_support_infill": [0, 255, 255, 255],
"layerview_move_combing": [0, 0, 255, 255],
"layerview_move_retraction": [128, 128, 255, 255],
"layerview_support_interface": [64, 192, 255, 255],
"layerview_nozzle": [181, 166, 66, 120],
"layerview_ghost": [31, 31, 31, 95],
"layerview_none": [255, 255, 255, 255],
"layerview_inset_0": [255, 0, 0, 255],
"layerview_inset_x": [0, 255, 0, 255],
"layerview_skin": [255, 255, 0, 255],
"layerview_support": [0, 255, 255, 255],
"layerview_skirt": [0, 255, 255, 255],
"layerview_infill": [255, 127, 0, 255],
"layerview_support_infill": [0, 255, 255, 255],
"layerview_move_combing": [0, 0, 255, 255],
"layerview_move_retraction": [128, 127, 255, 255],
"layerview_support_interface": [63, 127, 255, 255],
"layerview_prime_tower": [0, 255, 255, 255],
"layerview_nozzle": [181, 166, 66, 50],
"material_compatibility_warning": [255, 255, 255, 255],

View file

@ -372,18 +372,18 @@
"xray": [26, 26, 62, 255],
"xray_error": [255, 0, 0, 255],
"layerview_ghost": [32, 32, 32, 96],
"layerview_ghost": [31, 31, 31, 95],
"layerview_none": [255, 255, 255, 255],
"layerview_inset_0": [255, 0, 0, 255],
"layerview_inset_x": [0, 255, 0, 255],
"layerview_skin": [255, 255, 0, 255],
"layerview_support": [0, 255, 255, 255],
"layerview_skirt": [0, 255, 255, 255],
"layerview_infill": [255, 192, 0, 255],
"layerview_infill": [255, 127, 0, 255],
"layerview_support_infill": [0, 255, 255, 255],
"layerview_move_combing": [0, 0, 255, 255],
"layerview_move_retraction": [128, 128, 255, 255],
"layerview_support_interface": [64, 192, 255, 255],
"layerview_move_retraction": [128, 127, 255, 255],
"layerview_support_interface": [63, 127, 255, 255],
"layerview_prime_tower": [0, 255, 255, 255],
"layerview_nozzle": [181, 166, 66, 50],
@ -544,7 +544,7 @@
"slider_groove": [0.5, 0.5],
"slider_groove_radius": [0.15, 0.15],
"slider_handle": [1.5, 1.5],
"slider_layerview_size": [1.0, 26.0],
"slider_layerview_size": [1.0, 34.0],
"layerview_menu_size": [16.0, 4.0],
"layerview_legend_size": [1.0, 1.0],

View file

@ -2,10 +2,16 @@ from unittest.mock import MagicMock, patch
import pytest
from cura.BuildVolume import BuildVolume
from UM.Math.Polygon import Polygon
from UM.Settings.SettingInstance import InstanceState
from cura.BuildVolume import BuildVolume, PRIME_CLEARANCE
import numpy
@pytest.fixture
def build_volume():
def build_volume() -> BuildVolume:
mocked_application = MagicMock()
mocked_platform = MagicMock(name="platform")
with patch("cura.BuildVolume.Platform", mocked_platform):
@ -25,3 +31,238 @@ def test_buildVolumeSetSizes(build_volume):
assert build_volume.getDiagonalSize() == 200
def test_buildMesh(build_volume):
mesh = build_volume._buildMesh(0, 100, 0, 100, 0, 100, 1)
result_vertices = numpy.array([[0., 0., 0.], [100., 0., 0.], [0., 0., 0.], [0., 100., 0.], [0., 100., 0.], [100., 100., 0.], [100., 0., 0.], [100., 100., 0.], [0., 0., 100.], [100., 0., 100.], [0., 0., 100.], [0., 100., 100.], [0., 100., 100.], [100., 100., 100.], [100., 0., 100.], [100., 100., 100.], [0., 0., 0.], [0., 0., 100.], [100., 0., 0.], [100., 0., 100.], [0., 100., 0.], [0., 100., 100.], [100., 100., 0.], [100., 100., 100.]], dtype=numpy.float32)
assert numpy.array_equal(result_vertices, mesh.getVertices())
def test_buildGridMesh(build_volume):
mesh = build_volume._buildGridMesh(0, 100, 0, 100, 0, 100, 1)
result_vertices = numpy.array([[0., -1., 0.], [100., -1., 100.], [100., -1., 0.], [0., -1., 0.], [0., -1., 100.], [100., -1., 100.]])
assert numpy.array_equal(result_vertices, mesh.getVertices())
class TestUpdateRaftThickness:
setting_property_dict = {"raft_base_thickness": {"value": 1},
"raft_interface_thickness": {"value": 1},
"raft_surface_layers": {"value": 1},
"raft_surface_thickness": {"value": 1},
"raft_airgap": {"value": 1},
"layer_0_z_overlap": {"value": 1},
"adhesion_type": {"value": "raft"}}
def getPropertySideEffect(*args, **kwargs):
properties = TestUpdateRaftThickness.setting_property_dict.get(args[1])
if properties:
return properties.get(args[2])
def createMockedStack(self):
mocked_global_stack = MagicMock(name="mocked_global_stack")
mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
extruder_stack = MagicMock()
mocked_global_stack.extruders = {"0": extruder_stack}
return mocked_global_stack
def test_simple(self, build_volume: BuildVolume):
build_volume.raftThicknessChanged = MagicMock()
mocked_global_stack = self.createMockedStack()
build_volume._global_container_stack = mocked_global_stack
assert build_volume.getRaftThickness() == 0
build_volume._updateRaftThickness()
assert build_volume.getRaftThickness() == 3
assert build_volume.raftThicknessChanged.emit.call_count == 1
def test_adhesionIsNotRaft(self, build_volume: BuildVolume):
patched_dictionary = self.setting_property_dict.copy()
patched_dictionary["adhesion_type"] = {"value": "not_raft"}
mocked_global_stack = self.createMockedStack()
build_volume._global_container_stack = mocked_global_stack
assert build_volume.getRaftThickness() == 0
with patch.dict(self.setting_property_dict, patched_dictionary):
build_volume._updateRaftThickness()
assert build_volume.getRaftThickness() == 0
def test_noGlobalStack(self, build_volume: BuildVolume):
build_volume.raftThicknessChanged = MagicMock()
assert build_volume.getRaftThickness() == 0
build_volume._updateRaftThickness()
assert build_volume.getRaftThickness() == 0
assert build_volume.raftThicknessChanged.emit.call_count == 0
class TestComputeDisallowedAreasPrimeBlob:
setting_property_dict = {"machine_width": {"value": 50},
"machine_depth": {"value": 100},
"prime_blob_enable": {"value": True},
"extruder_prime_pos_x": {"value": 25},
"extruder_prime_pos_y": {"value": 50},
"machine_center_is_zero": {"value": True},
}
def getPropertySideEffect(*args, **kwargs):
properties = TestComputeDisallowedAreasPrimeBlob.setting_property_dict.get(args[1])
if properties:
return properties.get(args[2])
def test_noGlobalContainer(self, build_volume: BuildVolume):
# No global container and no extruders, so we expect no blob areas
assert build_volume._computeDisallowedAreasPrimeBlob(12, []) == {}
def test_noExtruders(self, build_volume: BuildVolume):
mocked_stack = MagicMock()
mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
build_volume._global_container_stack = mocked_stack
# No extruders, so still expect that we get no area
assert build_volume._computeDisallowedAreasPrimeBlob(12, []) == {}
def test_singleExtruder(self, build_volume: BuildVolume):
mocked_global_stack = MagicMock(name = "mocked_global_stack")
mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
mocked_extruder_stack = MagicMock(name = "mocked_extruder_stack")
mocked_extruder_stack.getId = MagicMock(return_value = "0")
mocked_extruder_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
build_volume._global_container_stack = mocked_global_stack
# Create a polygon that should be the result
resulting_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE)
# Since we want a blob of size 12;
resulting_polygon = resulting_polygon.getMinkowskiHull(Polygon.approximatedCircle(12))
# In the The translation result is 25, -50 (due to the settings used)
resulting_polygon = resulting_polygon.translate(25, -50)
assert build_volume._computeDisallowedAreasPrimeBlob(12, [mocked_extruder_stack]) == {"0": [resulting_polygon]}
class TestCalculateExtraZClearance:
setting_property_dict = {"retraction_hop": {"value": 12},
"retraction_hop_enabled": {"value": True}}
def getPropertySideEffect(*args, **kwargs):
properties = TestCalculateExtraZClearance.setting_property_dict.get(args[1])
if properties:
return properties.get(args[2])
def test_noContainerStack(self, build_volume: BuildVolume):
assert build_volume._calculateExtraZClearance([]) is 0
def test_withRetractionHop(self, build_volume: BuildVolume):
mocked_global_stack = MagicMock(name="mocked_global_stack")
mocked_extruder = MagicMock()
mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
build_volume._global_container_stack = mocked_global_stack
# It should be 12 because we have the hop enabled and the hop distance is set to 12
assert build_volume._calculateExtraZClearance([mocked_extruder]) == 12
def test_withoutRetractionHop(self, build_volume: BuildVolume):
mocked_global_stack = MagicMock(name="mocked_global_stack")
mocked_extruder = MagicMock()
mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
build_volume._global_container_stack = mocked_global_stack
patched_dictionary = self.setting_property_dict.copy()
patched_dictionary["retraction_hop_enabled"] = {"value": False}
with patch.dict(self.setting_property_dict, patched_dictionary):
# It should be 12 because we have the hop enabled and the hop distance is set to 12
assert build_volume._calculateExtraZClearance([mocked_extruder]) == 0
class TestRebuild:
def test_zeroWidthHeightDepth(self, build_volume: BuildVolume):
build_volume.rebuild()
assert build_volume.getMeshData() is None
def test_engineIsNotRead(self, build_volume: BuildVolume):
build_volume.setWidth(10)
build_volume.setHeight(10)
build_volume.setDepth(10)
build_volume.rebuild()
assert build_volume.getMeshData() is None
def test_noGlobalStack(self, build_volume: BuildVolume):
build_volume.setWidth(10)
build_volume.setHeight(10)
build_volume.setDepth(10)
# Fake the the "engine is created callback"
build_volume._onEngineCreated()
build_volume.rebuild()
assert build_volume.getMeshData() is None
class TestUpdateMachineSizeProperties:
setting_property_dict = {"machine_width": {"value": 50},
"machine_depth": {"value": 100},
"machine_height": {"value": 200},
"machine_shape": {"value": "DERP!"}}
def getPropertySideEffect(*args, **kwargs):
properties = TestUpdateMachineSizeProperties.setting_property_dict.get(args[1])
if properties:
return properties.get(args[2])
def test_noGlobalStack(self, build_volume: BuildVolume):
build_volume._updateMachineSizeProperties()
assert build_volume._width == 0
assert build_volume._height == 0
assert build_volume._depth == 0
assert build_volume._shape == ""
def test_happy(self, build_volume: BuildVolume):
mocked_global_stack = MagicMock(name="mocked_global_stack")
mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
build_volume._global_container_stack = mocked_global_stack
build_volume._updateMachineSizeProperties()
assert build_volume._width == 50
assert build_volume._height == 200
assert build_volume._depth == 100
assert build_volume._shape == "DERP!"
class TestGetEdgeDisallowedSize:
setting_property_dict = {}
bed_adhesion_size = 1
@pytest.fixture()
def build_volume(self, build_volume):
build_volume._calculateBedAdhesionSize = MagicMock(return_value = 1)
return build_volume
def getPropertySideEffect(*args, **kwargs):
properties = TestGetEdgeDisallowedSize.setting_property_dict.get(args[1])
if properties:
return properties.get(args[2])
def createMockedStack(self):
mocked_global_stack = MagicMock(name="mocked_global_stack")
mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
return mocked_global_stack
def test_noGlobalContainer(self, build_volume: BuildVolume):
assert build_volume.getEdgeDisallowedSize() == 0
def test_unknownAdhesion(self, build_volume: BuildVolume):
build_volume._global_container_stack = self.createMockedStack()
with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
#with pytest.raises(Exception):
# Since we don't have any adhesion set, this should break.
build_volume.getEdgeDisallowedSize()
def test_oneAtATime(self, build_volume: BuildVolume):
build_volume._global_container_stack = self.createMockedStack()
with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
with patch.dict(self.setting_property_dict, {"print_sequence": {"value": "one_at_a_time"}}):
assert build_volume.getEdgeDisallowedSize() == 0.1

View file

@ -62,3 +62,12 @@ def test_hasUserSettings(machine_manager, application):
assert machine_manager.numUserSettings == 12
assert machine_manager.hasUserSettings
def test_totalNumberOfSettings(machine_manager):
registry = MagicMock()
mocked_definition = MagicMock()
mocked_definition.getAllKeys = MagicMock(return_value = ["omg", "zomg", "foo"])
registry.findDefinitionContainers = MagicMock(return_value = [mocked_definition])
with patch("cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance", MagicMock(return_value=registry)):
assert machine_manager.totalNumberOfSettings == 3

View file

@ -101,7 +101,7 @@ def test_initialize():
initialize_preferences = MagicMock()
authorization_service = AuthorizationService(OAUTH_SETTINGS, original_preference)
authorization_service.initialize(initialize_preferences)
assert initialize_preferences.addPreference.called
initialize_preferences.addPreference.assert_called_once_with("test/auth_data", "{}")
original_preference.addPreference.assert_not_called()