mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-07 14:04:03 -06:00
Merge branch 'master' of github.com:Ultimaker/Cura into network_rewrite
This commit is contained in:
commit
083eee2e9d
22 changed files with 129 additions and 80 deletions
|
@ -751,12 +751,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
|
||||
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
|
||||
|
||||
extruder_stacks.append(stack)
|
||||
if stack.getMetaDataEntry("type") == "extruder_train":
|
||||
extruder_stacks.append(stack)
|
||||
|
||||
# If not extruder stacks were saved in the project file (pre 3.1) create one manually
|
||||
# We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this
|
||||
if not extruder_stacks:
|
||||
extruder_stacks.append(self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder"))
|
||||
stack = self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")
|
||||
if stack:
|
||||
extruder_stacks.append(stack)
|
||||
|
||||
except:
|
||||
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||
|
@ -790,6 +793,46 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
for stack in [global_stack] + extruder_stacks:
|
||||
stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container)
|
||||
|
||||
# Fix quality:
|
||||
# The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal"
|
||||
# but instead it was "normal". This should be fixed by setting it to the correct quality.
|
||||
# Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the
|
||||
# fix for that
|
||||
quality = global_stack.quality
|
||||
if quality.getId() not in ("empty", "empty_quality"):
|
||||
quality_type = quality.getMetaDataEntry("quality_type")
|
||||
quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(),
|
||||
type = "quality",
|
||||
quality_type = quality_type)
|
||||
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
|
||||
if quality_containers:
|
||||
global_stack.quality = quality_containers[0]
|
||||
else:
|
||||
# look for "fdmprinter" qualities if the machine-specific qualities cannot be found
|
||||
quality_containers = self._container_registry.findInstanceContainers(definition = "fdmprinter",
|
||||
type = "quality",
|
||||
quality_type = quality_type)
|
||||
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
|
||||
if quality_containers:
|
||||
global_stack.quality = quality_containers[0]
|
||||
else:
|
||||
# the quality_type of the quality profile cannot be found.
|
||||
# this can happen if a quality_type has been removed in a newer version, for example:
|
||||
# "extra_coarse" is removed from 2.7 to 3.0
|
||||
# in this case, the quality will be reset to "normal"
|
||||
quality_containers = self._container_registry.findInstanceContainers(
|
||||
definition = global_stack.definition.getId(),
|
||||
type = "quality",
|
||||
quality_type = "normal")
|
||||
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
|
||||
if quality_containers:
|
||||
global_stack.quality = quality_containers[0]
|
||||
else:
|
||||
# This should not happen!
|
||||
Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]",
|
||||
global_stack.getId(), global_stack.definition.getId())
|
||||
global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0]
|
||||
|
||||
# Replacing the old containers if resolve is "new".
|
||||
# When resolve is "new", some containers will get renamed, so all the other containers that reference to those
|
||||
# MUST get updated too.
|
||||
|
|
|
@ -256,14 +256,8 @@ class WorkspaceDialog(QObject):
|
|||
return self._result
|
||||
|
||||
def _createViewFromQML(self):
|
||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url))
|
||||
self._component = QQmlComponent(Application.getInstance()._engine, path)
|
||||
self._context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||
self._context.setContextProperty("manager", self)
|
||||
self._view = self._component.create(self._context)
|
||||
if self._view is None:
|
||||
Logger.log("c", "QQmlComponent status %s", self._component.status())
|
||||
Logger.log("c", "QQmlComponent error string %s", self._component.errorString())
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url)
|
||||
self._view = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
||||
def show(self):
|
||||
# Emit signal so the right thread actually shows the view.
|
||||
|
|
|
@ -106,9 +106,5 @@ class ChangeLog(Extension, QObject,):
|
|||
self._changelog_window.hide()
|
||||
|
||||
def createChangelogWindow(self):
|
||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml"))
|
||||
|
||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||
self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||
self._changelog_context.setContextProperty("manager", self)
|
||||
self._changelog_window = component.create(self._changelog_context)
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml")
|
||||
self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
|
|
@ -95,22 +95,22 @@ class ProcessSlicedLayersJob(Job):
|
|||
|
||||
# Find the minimum layer number
|
||||
# When using a raft, the raft layers are sent as layers < 0. Instead of allowing layers < 0, we
|
||||
# instead simply offset all other layers so the lowest layer is always 0.
|
||||
# instead simply offset all other layers so the lowest layer is always 0. It could happens that
|
||||
# the first raft layer has value -8 but there are just 4 raft (negative) layers.
|
||||
min_layer_number = 0
|
||||
negative_layers = 0
|
||||
for layer in self._layers:
|
||||
if layer.id < min_layer_number:
|
||||
min_layer_number = layer.id
|
||||
if layer.id < 0:
|
||||
negative_layers += 1
|
||||
|
||||
current_layer = 0
|
||||
|
||||
for layer in self._layers:
|
||||
abs_layer_number = layer.id + abs(min_layer_number)
|
||||
|
||||
# Workaround when the last layer doesn't have paths, this layer is skipped because this was generating
|
||||
# some glitches when rendering.
|
||||
if layer.id == len(self._layers)-1 and layer.repeatedMessageCount("path_segment") == 0:
|
||||
Logger.log("i", "No sliced data in the layer", layer.id)
|
||||
continue
|
||||
# Negative layers are offset by the minimum layer number, but the positive layers are just
|
||||
# offset by the number of negative layers so there is no layer gap between raft and model
|
||||
abs_layer_number = layer.id + abs(min_layer_number) if layer.id < 0 else layer.id + negative_layers
|
||||
|
||||
layer_data.addLayer(abs_layer_number)
|
||||
this_layer = layer_data.getLayer(abs_layer_number)
|
||||
|
|
|
@ -144,6 +144,11 @@ class GCodeReader(MeshReader):
|
|||
this_layer.polygons.append(this_poly)
|
||||
return True
|
||||
|
||||
def _createEmptyLayer(self, layer_number):
|
||||
self._layer_data_builder.addLayer(layer_number)
|
||||
self._layer_data_builder.setLayerHeight(layer_number, 0)
|
||||
self._layer_data_builder.setLayerThickness(layer_number, 0)
|
||||
|
||||
def _calculateLineWidth(self, current_point, previous_point, current_extrusion, previous_extrusion, layer_thickness):
|
||||
# Area of the filament
|
||||
Af = (self._filament_diameter / 2) ** 2 * numpy.pi
|
||||
|
@ -206,7 +211,6 @@ class GCodeReader(MeshReader):
|
|||
return self._position(
|
||||
params.x if params.x is not None else position.x,
|
||||
params.y if params.y is not None else position.y,
|
||||
|
||||
0,
|
||||
position.f,
|
||||
position.e)
|
||||
|
@ -269,11 +273,11 @@ class GCodeReader(MeshReader):
|
|||
position.e.extend([0] * (self._extruder_number - len(position.e) + 1))
|
||||
return position
|
||||
|
||||
def _processMCode(self, m):
|
||||
if m == 82:
|
||||
def _processMCode(self, M):
|
||||
if M == 82:
|
||||
# Set absolute extrusion mode
|
||||
self._is_absolute_extrusion = True
|
||||
elif m == 83:
|
||||
elif M == 83:
|
||||
# Set relative extrusion mode
|
||||
self._is_absolute_extrusion = False
|
||||
|
||||
|
@ -333,6 +337,9 @@ class GCodeReader(MeshReader):
|
|||
|
||||
current_position = self._position(0, 0, 0, 0, [0])
|
||||
current_path = []
|
||||
min_layer_number = 0
|
||||
negative_layers = 0
|
||||
previous_layer = 0
|
||||
|
||||
for line in file:
|
||||
if self._cancelled:
|
||||
|
@ -370,7 +377,23 @@ class GCodeReader(MeshReader):
|
|||
layer_number = int(line[len(self._layer_keyword):])
|
||||
self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0]))
|
||||
current_path.clear()
|
||||
|
||||
# When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior
|
||||
# as in ProcessSlicedLayersJob
|
||||
if layer_number < min_layer_number:
|
||||
min_layer_number = layer_number
|
||||
if layer_number < 0:
|
||||
layer_number += abs(min_layer_number)
|
||||
negative_layers += 1
|
||||
else:
|
||||
layer_number += negative_layers
|
||||
|
||||
# In case there is a gap in the layer count, empty layers are created
|
||||
for empty_layer in range(previous_layer + 1, layer_number):
|
||||
self._createEmptyLayer(empty_layer)
|
||||
|
||||
self._layer_number = layer_number
|
||||
previous_layer = layer_number
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ class SimulationView(View):
|
|||
if layer is None:
|
||||
return
|
||||
new_max_paths = layer.lineMeshElementCount()
|
||||
if new_max_paths > 0 and new_max_paths != self._max_paths:
|
||||
if new_max_paths >= 0 and new_max_paths != self._max_paths:
|
||||
self._max_paths = new_max_paths
|
||||
self.maxPathsChanged.emit()
|
||||
|
||||
|
|
|
@ -138,11 +138,10 @@ Item
|
|||
text: catalog.i18nc("@label:listbox", "Feedrate"),
|
||||
type_id: 2
|
||||
})
|
||||
// TODO DON'T DELETE!!!! This part must be enabled when adaptive layer height feature is available
|
||||
// layerViewTypes.append({
|
||||
// text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
||||
// type_id: 3 // these ids match the switching in the shader
|
||||
// })
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
||||
type_id: 3 // these ids match the switching in the shader
|
||||
})
|
||||
}
|
||||
|
||||
ComboBox
|
||||
|
|
|
@ -486,7 +486,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
|
|||
|
||||
printer_name = self.__getPrinterNameFromUuid(print_job["printer_uuid"])
|
||||
if printer_name is None:
|
||||
printer_name = i18n_catalog.i18nc("@label", "Unknown")
|
||||
printer_name = i18n_catalog.i18nc("@label Printer name", "Unknown")
|
||||
|
||||
message_text = (i18n_catalog.i18nc("@info:status",
|
||||
"Printer '{printer_name}' has finished printing '{job_name}'.")
|
||||
|
|
|
@ -44,7 +44,7 @@ Rectangle
|
|||
case "maintenance": // TODO: new string
|
||||
case "unknown":
|
||||
default:
|
||||
return catalog.i18nc("@label", "Unknown");
|
||||
return catalog.i18nc("@label Printer status", "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,12 +91,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
|||
# This will create the view if its not already created.
|
||||
def spawnFirmwareInterface(self, serial_port):
|
||||
if self._firmware_view is None:
|
||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml"))
|
||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||
|
||||
self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||
self._firmware_context.setContextProperty("manager", self)
|
||||
self._firmware_view = component.create(self._firmware_context)
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")
|
||||
self._firmware_view = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
||||
self._firmware_view.show()
|
||||
|
||||
|
|
|
@ -45,9 +45,5 @@ class UserAgreement(QObject, Extension):
|
|||
CuraApplication.getInstance().setNeedToShowUserAgreement(False)
|
||||
|
||||
def createUserAgreementWindow(self):
|
||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml"))
|
||||
|
||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||
self._user_agreement_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||
self._user_agreement_context.setContextProperty("manager", self)
|
||||
self._user_agreement_window = component.create(self._user_agreement_context)
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml")
|
||||
self._user_agreement_window = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue