Merge branch 'master' into mb-infill-line-angles

This commit is contained in:
Mark Burton 2017-01-24 15:02:50 +00:00
commit eebd0862cc
8 changed files with 92 additions and 32 deletions

View File

@ -96,8 +96,9 @@ class ExtruderManager(QObject):
# \param index The index of the new active extruder. # \param index The index of the new active extruder.
@pyqtSlot(int) @pyqtSlot(int)
def setActiveExtruderIndex(self, index): def setActiveExtruderIndex(self, index):
self._active_extruder_index = index if self._active_extruder_index != index:
self.activeExtruderChanged.emit() self._active_extruder_index = index
self.activeExtruderChanged.emit()
@pyqtProperty(int, notify = activeExtruderChanged) @pyqtProperty(int, notify = activeExtruderChanged)
def activeExtruderIndex(self): def activeExtruderIndex(self):

View File

@ -0,0 +1,37 @@
How to Profile Cura and See What It is Doing
============================================
Cura has a simple flame graph profiler available as a plugin which can be used to see what Cura is doing as it runs and how much time it takes. A flame graph profile shows its output as a timeline and stacks of "blocks" which represent parts of the code and are stacked up to show call depth. These often form little peaks which look like flames. It is a simple yet powerful way to visualise the activity of a program.
Setting up and installing the profiler
--------------------------------------
The profiler plugin is kept outside of the Cura source code here: https://github.com/sedwards2009/cura-big-flame-graph
To install it do:
* Use `git clone https://github.com/sedwards2009/cura-big-flame-graph.git` to grab a copy of the code.
* Copy the `BigFlameGraph` directory into the `plugins` directory in your local Cura.
* Set the `URANIUM_FLAME_PROFILER` environment variable to something before starting Cura. This flags to the profiler code in Cura to activate and insert the needed hooks into the code.
Using the profiler
------------------
To open the profiler go to the Extensions menu and select "Start BFG" from the "Big Flame Graph" menu. A page will open up in your default browser. This is the profiler UI. Click on "Record" to start recording, go to Cura and perform an action and then back in the profiler click on "Stop". The results should now load in.
The time scale is at the top of the window. The blocks should be read as meaning the blocks at the bottom call the blocks which are stacked on top of them. Hover the mouse to get more detailed information about a block such as the name of the code involved and its duration. Use the zoom buttons or mouse wheel to zoom in. The display can be panned by dragging with the left mouse button.
Note: The profiler front-end itself is quite "heavy" (ok, not optimised). It runs much better in Google Chrome or Chromium than Firefox. It is also a good idea to keep recording sessions short for the same reason.
What the Profiler Sees
----------------------
The profiler doesn't capture every function call in Cura. It hooks into a number of important systems which give a good picture of activity without too much run time overhead. The most important system is Uranium's signal mechanism and PyQt5 slots. Functions which are called via the signal mechanism are recorded and thier names appear in the results. PyQt5 slots appear in the results with the prefix `[SLOT]`.
Note that not all slots are captured. Only those slots which belong to classes which use the `pyqtSlot` decorator from the `UM.FlameProfiler` module.
Manually adding profiling code to more detail
---------------------------------------------
It is also possible to manually add decorators to methods to make them appear in the profiler results. The `UM.FlameProfiler` module contains the `profile` decorator which can be applied to methods. There is also a `profileCall` context manager which can be used with Python's `with` statement to measure a block of code. `profileCall` takes one argument, a label to use in the results.

View File

@ -70,8 +70,9 @@ class WorkspaceDialog(QObject):
return self._variant_type return self._variant_type
def setVariantType(self, variant_type): def setVariantType(self, variant_type):
self._variant_type = variant_type if self._variant_type != variant_type:
self.variantTypeChanged.emit() self._variant_type = variant_type
self.variantTypeChanged.emit()
@pyqtProperty(str, notify=machineTypeChanged) @pyqtProperty(str, notify=machineTypeChanged)
def machineType(self): def machineType(self):
@ -82,8 +83,9 @@ class WorkspaceDialog(QObject):
self.machineTypeChanged.emit() self.machineTypeChanged.emit()
def setNumUserSettings(self, num_user_settings): def setNumUserSettings(self, num_user_settings):
self._num_user_settings = num_user_settings if self._num_user_settings != num_user_settings:
self.numVisibleSettingsChanged.emit() self._num_user_settings = num_user_settings
self.numVisibleSettingsChanged.emit()
@pyqtProperty(int, notify=numUserSettingsChanged) @pyqtProperty(int, notify=numUserSettingsChanged)
def numUserSettings(self): def numUserSettings(self):
@ -94,40 +96,45 @@ class WorkspaceDialog(QObject):
return self._objects_on_plate return self._objects_on_plate
def setHasObjectsOnPlate(self, objects_on_plate): def setHasObjectsOnPlate(self, objects_on_plate):
self._objects_on_plate = objects_on_plate if self._objects_on_plate != objects_on_plate:
self.objectsOnPlateChanged.emit() self._objects_on_plate = objects_on_plate
self.objectsOnPlateChanged.emit()
@pyqtProperty("QVariantList", notify = materialLabelsChanged) @pyqtProperty("QVariantList", notify = materialLabelsChanged)
def materialLabels(self): def materialLabels(self):
return self._material_labels return self._material_labels
def setMaterialLabels(self, material_labels): def setMaterialLabels(self, material_labels):
self._material_labels = material_labels if self._material_labels != material_labels:
self.materialLabelsChanged.emit() self._material_labels = material_labels
self.materialLabelsChanged.emit()
@pyqtProperty("QVariantList", notify=extrudersChanged) @pyqtProperty("QVariantList", notify=extrudersChanged)
def extruders(self): def extruders(self):
return self._extruders return self._extruders
def setExtruders(self, extruders): def setExtruders(self, extruders):
self._extruders = extruders if self._extruders != extruders:
self.extrudersChanged.emit() self._extruders = extruders
self.extrudersChanged.emit()
@pyqtProperty(str, notify = machineNameChanged) @pyqtProperty(str, notify = machineNameChanged)
def machineName(self): def machineName(self):
return self._machine_name return self._machine_name
def setMachineName(self, machine_name): def setMachineName(self, machine_name):
self._machine_name = machine_name if self._machine_name != machine_name:
self.machineNameChanged.emit() self._machine_name = machine_name
self.machineNameChanged.emit()
@pyqtProperty(str, notify=qualityTypeChanged) @pyqtProperty(str, notify=qualityTypeChanged)
def qualityType(self): def qualityType(self):
return self._quality_type return self._quality_type
def setQualityType(self, quality_type): def setQualityType(self, quality_type):
self._quality_type = quality_type if self._quality_type != quality_type:
self.qualityTypeChanged.emit() self._quality_type = quality_type
self.qualityTypeChanged.emit()
@pyqtProperty(int, notify=numSettingsOverridenByQualityChangesChanged) @pyqtProperty(int, notify=numSettingsOverridenByQualityChangesChanged)
def numSettingsOverridenByQualityChanges(self): def numSettingsOverridenByQualityChanges(self):
@ -142,8 +149,9 @@ class WorkspaceDialog(QObject):
return self._quality_name return self._quality_name
def setQualityName(self, quality_name): def setQualityName(self, quality_name):
self._quality_name = quality_name if self._quality_name != quality_name:
self.qualityNameChanged.emit() self._quality_name = quality_name
self.qualityNameChanged.emit()
@pyqtProperty(str, notify=activeModeChanged) @pyqtProperty(str, notify=activeModeChanged)
def activeMode(self): def activeMode(self):
@ -165,8 +173,9 @@ class WorkspaceDialog(QObject):
return self._num_visible_settings return self._num_visible_settings
def setNumVisibleSettings(self, num_visible_settings): def setNumVisibleSettings(self, num_visible_settings):
self._num_visible_settings = num_visible_settings if self._num_visible_settings != num_visible_settings:
self.numVisibleSettingsChanged.emit() self._num_visible_settings = num_visible_settings
self.numVisibleSettingsChanged.emit()
@pyqtProperty(bool, notify = machineConflictChanged) @pyqtProperty(bool, notify = machineConflictChanged)
def machineConflict(self): def machineConflict(self):
@ -191,16 +200,19 @@ class WorkspaceDialog(QObject):
Application.getInstance().getBackend().close() Application.getInstance().getBackend().close()
def setMaterialConflict(self, material_conflict): def setMaterialConflict(self, material_conflict):
self._has_material_conflict = material_conflict if self._has_material_conflict != material_conflict:
self.materialConflictChanged.emit() self._has_material_conflict = material_conflict
self.materialConflictChanged.emit()
def setMachineConflict(self, machine_conflict): def setMachineConflict(self, machine_conflict):
self._has_machine_conflict = machine_conflict if self._has_machine_conflict != machine_conflict:
self.machineConflictChanged.emit() self._has_machine_conflict = machine_conflict
self.machineConflictChanged.emit()
def setQualityChangesConflict(self, quality_changes_conflict): def setQualityChangesConflict(self, quality_changes_conflict):
self._has_quality_changes_conflict = quality_changes_conflict if self._has_quality_changes_conflict != quality_changes_conflict:
self.qualityChangesConflictChanged.emit() self._has_quality_changes_conflict = quality_changes_conflict
self.qualityChangesConflictChanged.emit()
def getResult(self): def getResult(self):
if "machine" in self._result and not self._has_machine_conflict: if "machine" in self._result and not self._has_machine_conflict:

View File

@ -98,6 +98,9 @@ Use a mesh to specify a volume within which to classify nothing as overhang for
*Delta printer support *Delta printer support
This release adds support for printers with elliptic buildplates. This feature has not been extensively tested so please let us know if it works or get involved in improving it. This release adds support for printers with elliptic buildplates. This feature has not been extensively tested so please let us know if it works or get involved in improving it.
*AppImage for Linux
The Linux distribution is now in AppImage format, which makes Cura easier to install.
*bugfixes *bugfixes
The user is now notified when a new version of Cura is available. The user is now notified when a new version of Cura is available.
When searching in the setting visibility preferences, the category for each setting is always displayed. When searching in the setting visibility preferences, the category for each setting is always displayed.

View File

@ -12,11 +12,9 @@ UM.Dialog
{ {
width: 350 * Screen.devicePixelRatio; width: 350 * Screen.devicePixelRatio;
minimumWidth: 350 * Screen.devicePixelRatio; minimumWidth: 350 * Screen.devicePixelRatio;
maximumWidth: 350 * Screen.devicePixelRatio;
height: 250 * Screen.devicePixelRatio; height: 250 * Screen.devicePixelRatio;
minimumHeight: 250 * Screen.devicePixelRatio; minimumHeight: 250 * Screen.devicePixelRatio;
maximumHeight: 250 * Screen.devicePixelRatio;
title: catalog.i18nc("@title:window", "Convert Image...") title: catalog.i18nc("@title:window", "Convert Image...")

View File

@ -1239,6 +1239,16 @@
"default_value": true, "default_value": true,
"enabled": "infill_sparse_density > 0", "enabled": "infill_sparse_density > 0",
"settable_per_mesh": true "settable_per_mesh": true
},
"min_infill_area":
{
"label": "Minimum Infill Area",
"description": "Don't generate areas of infill smaller than this (use skin instead).",
"unit": "mm²",
"type": "float",
"minimum_value": "0",
"default_value": 0,
"settable_per_mesh": true
} }
} }
}, },

View File

@ -45,7 +45,7 @@
"default_value": "RepRap (Marlin/Sprinter)" "default_value": "RepRap (Marlin/Sprinter)"
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "; info: M303 E0 S200 C8 ; Pid auto-tune \n\nM140 S{{material_bed_temperature}}; Start heating up the base\nG28 ; Home to top 3 endstops\n; Autolevel and adjust first layer\n; Adjust this value to fit your own printer! (positive is thicker)\n; This default value is intentionally very high to accommodate the\n; variety of print heads used with this printer. Many of you will\n; need tiny values like Z0 or Z0.1. Use feeler gauges to dial this\n; in as accurately as possible.\nG29 Z10\n\n; Squirt and wipe ;\nM109 S220 ; Wait for the temp to hit 220\nG00 X125 Y-60 Z0.1 ;\nG92 E0 ;\nG01 E25 F100 ; Extrude a little bit to replace oozage from auto levelling\nG01 X90 Y-50 F6000 ;\nG01 Z5 ;\n\n; Set the extruder to the requested print temperature\nM104 S{{material_print_temperature}}\n" "default_value": "; info: M303 E0 S200 C8 ; Pid auto-tune \n\nM140 S{material_bed_temperature}; Start heating up the base\nG28 ; Home to top 3 endstops\n; Autolevel and adjust first layer\n; Adjust this value to fit your own printer! (positive is thicker)\n; This default value is intentionally very high to accommodate the\n; variety of print heads used with this printer. Many of you will\n; need tiny values like Z0 or Z0.1. Use feeler gauges to dial this\n; in as accurately as possible.\nG29 Z10\n\n; Squirt and wipe ;\nM109 S220 ; Wait for the temp to hit 220\nG00 X125 Y-60 Z0.1 ;\nG92 E0 ;\nG01 E25 F100 ; Extrude a little bit to replace oozage from auto levelling\nG01 X90 Y-50 F6000 ;\nG01 Z5 ;\n\n; Set the extruder to the requested print temperature\nM104 S{material_print_temperature}\n"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0 ; turn off temperature\nM140 S0 ; turn off bed\nG28 ; home all axes\nM84 ; disable motors\n" "default_value": "M104 S0 ; turn off temperature\nM140 S0 ; turn off bed\nG28 ; home all axes\nM84 ; disable motors\n"
@ -54,4 +54,4 @@
"default_value": "elliptic" "default_value": "elliptic"
} }
} }
} }

View File

@ -15,11 +15,10 @@ UM.Dialog
width: 550 width: 550
minimumWidth: 550 minimumWidth: 550
maximumWidth: 550
height: 350 height: 350
minimumHeight: 350 minimumHeight: 350
maximumHeight: 350
property int spacerHeight: 10 property int spacerHeight: 10
property bool dontShowAgain: true property bool dontShowAgain: true