Merge branch 'master' into graphics_buffer_update

This commit is contained in:
Remco Burema 2021-07-25 22:30:39 +02:00
commit 458fbd35f1
4327 changed files with 77905 additions and 22116 deletions

View file

@ -65,7 +65,7 @@ class SimulationPass(RenderPass):
self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex)))
if not self._compatibility_mode:
self._layer_shader.setUniformValue("u_starts_color", Color(*Application.getInstance().getTheme().getColor("layerview_starts").getRgb()))
if self._layer_view:
self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate())
self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate())
@ -73,6 +73,8 @@ class SimulationPass(RenderPass):
self._layer_shader.setUniformValue("u_min_thickness", self._layer_view.getMinThickness())
self._layer_shader.setUniformValue("u_max_line_width", self._layer_view.getMaxLineWidth())
self._layer_shader.setUniformValue("u_min_line_width", self._layer_view.getMinLineWidth())
self._layer_shader.setUniformValue("u_max_flow_rate", self._layer_view.getMaxFlowRate())
self._layer_shader.setUniformValue("u_min_flow_rate", self._layer_view.getMinFlowRate())
self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getSimulationViewType())
self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities())
self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves())
@ -86,6 +88,8 @@ class SimulationPass(RenderPass):
self._layer_shader.setUniformValue("u_min_feedrate", 0)
self._layer_shader.setUniformValue("u_max_thickness", 1)
self._layer_shader.setUniformValue("u_min_thickness", 0)
self._layer_shader.setUniformValue("u_max_flow_rate", 1)
self._layer_shader.setUniformValue("u_min_flow_rate", 0)
self._layer_shader.setUniformValue("u_max_line_width", 1)
self._layer_shader.setUniformValue("u_min_line_width", 0)
self._layer_shader.setUniformValue("u_layer_view_type", 1)
@ -177,9 +181,9 @@ class SimulationPass(RenderPass):
self._switching_layers = True
# The first line does not have a previous line: add a MoveCombingType in front for start detection
# this way the first start of the layer can also be drawn
# this way the first start of the layer can also be drawn
prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]])
# Remove the last element
# Remove the last element
prev_line_types = prev_line_types[0:layer_data._attributes["line_types"]["value"].size]
layer_data._attributes["prev_line_types"] = {'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type'}

View file

@ -1,4 +1,4 @@
# Copyright (c) 2020 Ultimaker B.V.
# Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import sys
@ -30,6 +30,7 @@ from UM.View.GL.ShaderProgram import ShaderProgram
from UM.i18n import i18nCatalog
from cura.CuraView import CuraView
from cura.LayerPolygon import LayerPolygon # To distinguish line types.
from cura.Scene.ConvexHullNode import ConvexHullNode
from cura.CuraApplication import CuraApplication
@ -93,6 +94,8 @@ class SimulationView(CuraView):
self._min_thickness = sys.float_info.max
self._max_line_width = sys.float_info.min
self._min_line_width = sys.float_info.max
self._min_flow_rate = sys.float_info.max
self._max_flow_rate = sys.float_info.min
self._global_container_stack = None # type: Optional[ContainerStack]
self._proxy = None
@ -115,6 +118,7 @@ class SimulationView(CuraView):
Application.getInstance().getPreferences().addPreference("layerview/show_infill", True)
Application.getInstance().getPreferences().addPreference("layerview/show_starts", True)
self.visibleStructuresChanged.connect(self.calculateColorSchemeLimits)
self._updateWithPreferences()
self._solid_layers = int(Application.getInstance().getPreferences().getValue("view/top_layer_count"))
@ -198,6 +202,7 @@ class SimulationView(CuraView):
if node.getMeshData() is None:
return
self.setActivity(False)
self.calculateColorSchemeLimits()
self.calculateMaxLayers()
self.calculateMaxPathsOnLayer(self._current_layer_num)
@ -218,12 +223,6 @@ class SimulationView(CuraView):
def resetLayerData(self) -> None:
self._current_layer_mesh = None
self._current_layer_jumps = None
self._max_feedrate = sys.float_info.min
self._min_feedrate = sys.float_info.max
self._max_thickness = sys.float_info.min
self._min_thickness = sys.float_info.max
self._max_line_width = sys.float_info.min
self._min_line_width = sys.float_info.max
def beginRendering(self) -> None:
scene = self.getController().getScene()
@ -248,58 +247,59 @@ class SimulationView(CuraView):
renderer.queueNode(node, transparent = True, shader = self._ghost_shader)
def setLayer(self, value: int) -> None:
"""
Set the upper end of the range of visible layers.
If setting it below the lower end of the range, the lower end is lowered so that 1 layer stays visible.
:param value: The new layer number to show, 0-indexed.
"""
if self._current_layer_num != value:
self._current_layer_num = value
if self._current_layer_num < 0:
self._current_layer_num = 0
if self._current_layer_num > self._max_layers:
self._current_layer_num = self._max_layers
if self._current_layer_num < self._minimum_layer_num:
self._minimum_layer_num = self._current_layer_num
self._current_layer_num = min(max(value, 0), self._max_layers)
self._minimum_layer_num = min(self._current_layer_num, self._minimum_layer_num)
self._startUpdateTopLayers()
self.currentLayerNumChanged.emit()
def setMinimumLayer(self, value: int) -> None:
"""
Set the lower end of the range of visible layers.
If setting it above the upper end of the range, the upper end is increased so that 1 layer stays visible.
:param value: The new lower end of the range of visible layers, 0-indexed.
"""
if self._minimum_layer_num != value:
self._minimum_layer_num = value
if self._minimum_layer_num < 0:
self._minimum_layer_num = 0
if self._minimum_layer_num > self._max_layers:
self._minimum_layer_num = self._max_layers
if self._minimum_layer_num > self._current_layer_num:
self._current_layer_num = self._minimum_layer_num
self._minimum_layer_num = min(max(value, 0), self._max_layers)
self._current_layer_num = max(self._current_layer_num, self._minimum_layer_num)
self._startUpdateTopLayers()
self.currentLayerNumChanged.emit()
def setPath(self, value: int) -> None:
"""
Set the upper end of the range of visible paths on the current layer.
If setting it below the lower end of the range, the lower end is lowered so that 1 path stays visible.
:param value: The new path index to show, 0-indexed.
"""
if self._current_path_num != value:
self._current_path_num = value
if self._current_path_num < 0:
self._current_path_num = 0
if self._current_path_num > self._max_paths:
self._current_path_num = self._max_paths
if self._current_path_num < self._minimum_path_num:
self._minimum_path_num = self._current_path_num
self._current_path_num = min(max(value, 0), self._max_paths)
self._minimum_path_num = min(self._minimum_path_num, self._current_path_num)
self._startUpdateTopLayers()
self.currentPathNumChanged.emit()
def setMinimumPath(self, value: int) -> None:
"""
Set the lower end of the range of visible paths on the current layer.
If setting it above the upper end of the range, the upper end is increased so that 1 path stays visible.
:param value: The new lower end of the range of visible paths, 0-indexed.
"""
if self._minimum_path_num != value:
self._minimum_path_num = value
if self._minimum_path_num < 0:
self._minimum_path_num = 0
if self._minimum_path_num > self._max_layers:
self._minimum_path_num = self._max_layers
if self._minimum_path_num > self._current_path_num:
self._current_path_num = self._minimum_path_num
self._minimum_path_num = min(max(value, 0), self._max_paths)
self._current_path_num = max(self._current_path_num, self._minimum_path_num)
self._startUpdateTopLayers()
self.currentPathNumChanged.emit()
def setSimulationViewType(self, layer_view_type: int) -> None:
@ -333,37 +333,52 @@ class SimulationView(CuraView):
# If more than 16 extruders are called for, this should be converted to a sampler1d.
return Matrix(self._extruder_opacity)
def setShowTravelMoves(self, show):
def setShowTravelMoves(self, show: bool) -> None:
if show == self._show_travel_moves:
return
self._show_travel_moves = show
self.currentLayerNumChanged.emit()
self.visibleStructuresChanged.emit()
def getShowTravelMoves(self):
def getShowTravelMoves(self) -> bool:
return self._show_travel_moves
def setShowHelpers(self, show: bool) -> None:
if show == self._show_helpers:
return
self._show_helpers = show
self.currentLayerNumChanged.emit()
self.visibleStructuresChanged.emit()
def getShowHelpers(self) -> bool:
return self._show_helpers
def setShowSkin(self, show: bool) -> None:
if show == self._show_skin:
return
self._show_skin = show
self.currentLayerNumChanged.emit()
self.visibleStructuresChanged.emit()
def getShowSkin(self) -> bool:
return self._show_skin
def setShowInfill(self, show: bool) -> None:
if show == self._show_infill:
return
self._show_infill = show
self.currentLayerNumChanged.emit()
self.visibleStructuresChanged.emit()
def getShowInfill(self) -> bool:
return self._show_infill
def setShowStarts(self, show: bool) -> None:
if show == self._show_starts:
return
self._show_starts = show
self.currentLayerNumChanged.emit()
self.visibleStructuresChanged.emit()
def getShowStarts(self) -> bool:
return self._show_starts
@ -398,12 +413,23 @@ class SimulationView(CuraView):
return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
return self._min_line_width
def getMaxFlowRate(self) -> float:
return self._max_flow_rate
def getMinFlowRate(self) -> float:
if abs(self._min_flow_rate - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
return self._min_flow_rate
def calculateMaxLayers(self) -> None:
"""
Calculates number of layers, triggers signals if the number of layers changed and makes sure the top layers are
recalculated for legacy layer view.
"""
scene = self.getController().getScene()
self._old_max_layers = self._max_layers
new_max_layers = -1
"""Recalculate num max layers"""
for node in DepthFirstIterator(scene.getRoot()): # type: ignore
layer_data = node.callDecoration("getLayerData")
if not layer_data:
@ -418,19 +444,6 @@ class SimulationView(CuraView):
if len(layer_data.getLayer(layer_id).polygons) < 1:
continue
# Store the max and min feedrates and thicknesses for display purposes
for p in layer_data.getLayer(layer_id).polygons:
self._max_feedrate = max(float(p.lineFeedrates.max()), self._max_feedrate)
self._min_feedrate = min(float(p.lineFeedrates.min()), self._min_feedrate)
self._max_line_width = max(float(p.lineWidths.max()), self._max_line_width)
self._min_line_width = min(float(p.lineWidths.min()), self._min_line_width)
self._max_thickness = max(float(p.lineThicknesses.max()), self._max_thickness)
try:
self._min_thickness = min(float(p.lineThicknesses[numpy.nonzero(p.lineThicknesses)].min()), self._min_thickness)
except ValueError:
# Sometimes, when importing a GCode the line thicknesses are zero and so the minimum (avoiding
# the zero) can't be calculated
Logger.log("i", "Min thickness can't be calculated because all the values are zero")
if max_layer_number < layer_id:
max_layer_number = layer_id
if min_layer_number > layer_id:
@ -454,6 +467,87 @@ class SimulationView(CuraView):
self.maxLayersChanged.emit()
self._startUpdateTopLayers()
def calculateColorSchemeLimits(self) -> None:
"""
Calculates the limits of the colour schemes, depending on the layer view data that is visible to the user.
"""
# Before we start, save the old values so that we can tell if any of the spectrums need to change.
old_min_feedrate = self._min_feedrate
old_max_feedrate = self._max_feedrate
old_min_linewidth = self._min_line_width
old_max_linewidth = self._max_line_width
old_min_thickness = self._min_thickness
old_max_thickness = self._max_thickness
old_min_flow_rate = self._min_flow_rate
old_max_flow_rate = self._max_flow_rate
self._min_feedrate = sys.float_info.max
self._max_feedrate = sys.float_info.min
self._min_line_width = sys.float_info.max
self._max_line_width = sys.float_info.min
self._min_thickness = sys.float_info.max
self._max_thickness = sys.float_info.min
self._min_flow_rate = sys.float_info.max
self._max_flow_rate = sys.float_info.min
# The colour scheme is only influenced by the visible lines, so filter the lines by if they should be visible.
visible_line_types = []
if self.getShowSkin(): # Actually "shell".
visible_line_types.append(LayerPolygon.SkinType)
visible_line_types.append(LayerPolygon.Inset0Type)
visible_line_types.append(LayerPolygon.InsetXType)
if self.getShowInfill():
visible_line_types.append(LayerPolygon.InfillType)
if self.getShowHelpers():
visible_line_types.append(LayerPolygon.PrimeTowerType)
visible_line_types.append(LayerPolygon.SkirtType)
visible_line_types.append(LayerPolygon.SupportType)
visible_line_types.append(LayerPolygon.SupportInfillType)
visible_line_types.append(LayerPolygon.SupportInterfaceType)
visible_line_types_with_extrusion = visible_line_types.copy() # Copy before travel moves are added
if self.getShowTravelMoves():
visible_line_types.append(LayerPolygon.MoveCombingType)
visible_line_types.append(LayerPolygon.MoveRetractionType)
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
layer_data = node.callDecoration("getLayerData")
if not layer_data:
continue
for layer_index in layer_data.getLayers():
for polyline in layer_data.getLayer(layer_index).polygons:
is_visible = numpy.isin(polyline.types, visible_line_types)
visible_indices = numpy.where(is_visible)[0]
visible_indicies_with_extrusion = numpy.where(numpy.isin(polyline.types, visible_line_types_with_extrusion))[0]
if visible_indices.size == 0: # No items to take maximum or minimum of.
continue
visible_feedrates = numpy.take(polyline.lineFeedrates, visible_indices)
visible_feedrates_with_extrusion = numpy.take(polyline.lineFeedrates, visible_indicies_with_extrusion)
visible_linewidths = numpy.take(polyline.lineWidths, visible_indices)
visible_linewidths_with_extrusion = numpy.take(polyline.lineWidths, visible_indicies_with_extrusion)
visible_thicknesses = numpy.take(polyline.lineThicknesses, visible_indices)
visible_thicknesses_with_extrusion = numpy.take(polyline.lineThicknesses, visible_indicies_with_extrusion)
self._max_feedrate = max(float(visible_feedrates.max()), self._max_feedrate)
if visible_feedrates_with_extrusion.size != 0:
flow_rates = visible_feedrates_with_extrusion * visible_linewidths_with_extrusion * visible_thicknesses_with_extrusion
self._min_flow_rate = min(float(flow_rates.min()), self._min_flow_rate)
self._max_flow_rate = max(float(flow_rates.max()), self._max_flow_rate)
self._min_feedrate = min(float(visible_feedrates.min()), self._min_feedrate)
self._max_line_width = max(float(visible_linewidths.max()), self._max_line_width)
self._min_line_width = min(float(visible_linewidths.min()), self._min_line_width)
self._max_thickness = max(float(visible_thicknesses.max()), self._max_thickness)
try:
self._min_thickness = min(float(visible_thicknesses[numpy.nonzero(visible_thicknesses)].min()), self._min_thickness)
except ValueError:
# Sometimes, when importing a GCode the line thicknesses are zero and so the minimum (avoiding the zero) can't be calculated.
Logger.log("w", "Min thickness can't be calculated because all the values are zero")
if old_min_feedrate != self._min_feedrate or old_max_feedrate != self._max_feedrate \
or old_min_linewidth != self._min_line_width or old_max_linewidth != self._max_line_width \
or old_min_thickness != self._min_thickness or old_max_thickness != self._max_thickness \
or old_min_flow_rate != self._min_flow_rate or old_max_flow_rate != self._max_flow_rate:
self.colorSchemeLimitsChanged.emit()
def calculateMaxPathsOnLayer(self, layer_num: int) -> None:
# Update the currentPath
scene = self.getController().getScene()
@ -480,6 +574,8 @@ class SimulationView(CuraView):
preferencesChanged = Signal()
busyChanged = Signal()
activityChanged = Signal()
visibleStructuresChanged = Signal()
colorSchemeLimitsChanged = Signal()
def getProxy(self, engine, script_engine):
"""Hackish way to ensure the proxy is already created
@ -511,6 +607,7 @@ class SimulationView(CuraView):
Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged)
self.calculateColorSchemeLimits()
self.calculateMaxLayers()
self.calculateMaxPathsOnLayer(self._current_layer_num)

View file

@ -55,8 +55,8 @@ Item
Connections
{
target: UM.SimulationView
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
onCurrentPathChanged:
function onMaxPathsChanged() { pathSlider.setHandleValue(UM.SimulationView.currentPath) }
function onCurrentPathChanged()
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (pathSlider.manuallyChanged)
@ -78,7 +78,7 @@ Item
UM.SimpleButton
{
id: playButton
iconSource: !isSimulationPlaying ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
iconSource: !isSimulationPlaying ? "./resources/Play.svg": "./resources/Pause.svg"
width: UM.Theme.getSize("small_button").width
height: UM.Theme.getSize("small_button").height
hoverColor: UM.Theme.getColor("slider_handle_active")
@ -89,7 +89,7 @@ Item
Connections
{
target: UM.Preferences
onPreferenceChanged:
function onPreferenceChanged(preference)
{
if (preference !== "view/only_show_top_layers" && preference !== "view/top_layer_count" && ! preference.match("layerview/"))
{
@ -221,9 +221,9 @@ Item
Connections
{
target: UM.SimulationView
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
onCurrentLayerChanged:
function onMaxLayersChanged() { layerSlider.setUpperValue(UM.SimulationView.currentLayer) }
function onMinimumLayerChanged() { layerSlider.setLowerValue(UM.SimulationView.minimumLayer) }
function onCurrentLayerChanged()
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (layerSlider.manuallyChanged)
@ -241,4 +241,4 @@ Item
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
}
}
}
}

View file

@ -22,7 +22,7 @@ Cura.ExpandableComponent
Connections
{
target: UM.Preferences
onPreferenceChanged:
function onPreferenceChanged(preference)
{
if (preference !== "view/only_show_top_layers" && preference !== "view/top_layer_count" && ! preference.match("layerview/"))
{
@ -90,6 +90,7 @@ Cura.ExpandableComponent
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
property bool show_line_width_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 4
property bool show_flow_rate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 5
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
@ -125,6 +126,10 @@ Cura.ExpandableComponent
text: catalog.i18nc("@label:listbox", "Line Width"),
type_id: 4
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Flow"),
type_id: 5
})
}
ComboBox
@ -150,10 +155,13 @@ Cura.ExpandableComponent
{
// Update the visibility of the legends.
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3 || type_id == 4);
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode &&
(type_id == 2 || type_id == 3 || type_id == 4 || type_id == 5) ;
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
viewSettings.show_line_width_gradient = viewSettings.show_gradient && (type_id == 4);
viewSettings.show_flow_rate_gradient = viewSettings.show_gradient && (type_id == 5);
}
}
@ -195,16 +203,16 @@ Cura.ExpandableComponent
style: UM.Theme.styles.checkbox
UM.RecolorImage
Rectangle
{
id: swatch
anchors.verticalCenter: parent.verticalCenter
anchors.right: extrudersModelCheckBox.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
source: UM.Theme.getIcon("extruder_button")
color: model.color
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
}
Label
@ -389,18 +397,24 @@ Cura.ExpandableComponent
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
return parseFloat(UM.SimulationView.minFeedrate).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
return parseFloat(UM.SimulationView.minThickness).toFixed(2)
}
//Line width selected
// Line width selected
if(UM.Preferences.getValue("layerview/layer_view_type") == 4)
{
return parseFloat(UM.SimulationView.getMinLineWidth()).toFixed(2);
return parseFloat(UM.SimulationView.minLineWidth).toFixed(2);
}
// Flow Rate selected
if(UM.Preferences.getValue("layerview/layer_view_type") == 5)
{
return parseFloat(UM.SimulationView.minFlowRate).toFixed(2);
}
}
return catalog.i18nc("@label","min")
}
@ -431,6 +445,11 @@ Cura.ExpandableComponent
{
return "mm"
}
// Flow Rate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 5)
{
return "mm³/s"
}
}
return ""
}
@ -448,17 +467,22 @@ Cura.ExpandableComponent
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
return parseFloat(UM.SimulationView.maxFeedrate).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
return parseFloat(UM.SimulationView.maxThickness).toFixed(2)
}
//Line width selected
if(UM.Preferences.getValue("layerview/layer_view_type") == 4)
{
return parseFloat(UM.SimulationView.getMaxLineWidth()).toFixed(2);
return parseFloat(UM.SimulationView.maxLineWidth).toFixed(2);
}
// Flow rate selected
if(UM.Preferences.getValue("layerview/layer_view_type") == 5)
{
return parseFloat(UM.SimulationView.maxFlowRate).toFixed(2);
}
}
return catalog.i18nc("@label","max")
@ -474,7 +498,10 @@ Cura.ExpandableComponent
Rectangle
{
id: feedrateGradient
visible: viewSettings.show_feedrate_gradient || viewSettings.show_line_width_gradient
visible: (
viewSettings.show_feedrate_gradient ||
viewSettings.show_line_width_gradient
)
anchors.left: parent.left
anchors.right: parent.right
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
@ -526,7 +553,9 @@ Cura.ExpandableComponent
Rectangle
{
id: thicknessGradient
visible: viewSettings.show_thickness_gradient
visible: (
viewSettings.show_thickness_gradient
)
anchors.left: parent.left
anchors.right: parent.right
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
@ -578,6 +607,85 @@ Cura.ExpandableComponent
}
}
}
// Gradient colors for flow (similar to jet colormap)
Rectangle
{
id: jetGradient
visible: (
viewSettings.show_flow_rate_gradient
)
anchors.left: parent.left
anchors.right: parent.right
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
LinearGradient
{
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_lining").width
right: parent.right
rightMargin: UM.Theme.getSize("default_lining").width
top: parent.top
topMargin: UM.Theme.getSize("default_lining").width
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_lining").width
}
start: Qt.point(0, 0)
end: Qt.point(parent.width, 0)
gradient: Gradient
{
GradientStop
{
position: 0.0
color: Qt.rgba(0, 0, 0.5, 1)
}
GradientStop
{
position: 0.125
color: Qt.rgba(0, 0.0, 1.0, 1)
}
GradientStop
{
position: 0.25
color: Qt.rgba(0, 0.5, 1.0, 1)
}
GradientStop
{
position: 0.375
color: Qt.rgba(0.0, 1.0, 1.0, 1)
}
GradientStop
{
position: 0.5
color: Qt.rgba(0.5, 1.0, 0.5, 1)
}
GradientStop
{
position: 0.625
color: Qt.rgba(1.0, 1.0, 0.0, 1)
}
GradientStop
{
position: 0.75
color: Qt.rgba(1.0, 0.5, 0, 1)
}
GradientStop
{
position: 0.875
color: Qt.rgba(1.0, 0.0, 0, 1)
}
GradientStop
{
position: 1.0
color: Qt.rgba(0.5, 0, 0, 1)
}
}
}
}
}
FontMetrics

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import TYPE_CHECKING
@ -28,6 +28,7 @@ class SimulationViewProxy(QObject):
globalStackChanged = pyqtSignal()
preferencesChanged = pyqtSignal()
busyChanged = pyqtSignal()
colorSchemeLimitsChanged = pyqtSignal()
@pyqtProperty(bool, notify=activityChanged)
def layerActivity(self):
@ -101,30 +102,38 @@ class SimulationViewProxy(QObject):
def getSimulationRunning(self):
return self._simulation_view.isSimulationRunning()
@pyqtSlot(result=float)
def getMinFeedrate(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def minFeedrate(self):
return self._simulation_view.getMinFeedrate()
@pyqtSlot(result=float)
def getMaxFeedrate(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def maxFeedrate(self):
return self._simulation_view.getMaxFeedrate()
@pyqtSlot(result=float)
def getMinThickness(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def minThickness(self):
return self._simulation_view.getMinThickness()
@pyqtSlot(result=float)
def getMaxThickness(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def maxThickness(self):
return self._simulation_view.getMaxThickness()
@pyqtSlot(result=float)
def getMaxLineWidth(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def maxLineWidth(self):
return self._simulation_view.getMaxLineWidth()
@pyqtSlot(result=float)
def getMinLineWidth(self):
@pyqtProperty(float, notify = colorSchemeLimitsChanged)
def minLineWidth(self):
return self._simulation_view.getMinLineWidth()
@pyqtProperty(float, notify=colorSchemeLimitsChanged)
def maxFlowRate(self):
return self._simulation_view.getMaxFlowRate()
@pyqtProperty(float, notify=colorSchemeLimitsChanged)
def minFlowRate(self):
return self._simulation_view.getMinFlowRate()
# Opacity 0..1
@pyqtSlot(int, float)
def setExtruderOpacity(self, extruder_nr, opacity):
@ -153,6 +162,9 @@ class SimulationViewProxy(QObject):
self.currentLayerChanged.emit()
self._layerActivityChanged()
def _onColorSchemeLimitsChanged(self):
self.colorSchemeLimitsChanged.emit()
def _onPathChanged(self):
self.currentPathChanged.emit()
self._layerActivityChanged()
@ -182,6 +194,7 @@ class SimulationViewProxy(QObject):
active_view = self._controller.getActiveView()
if active_view == self._simulation_view:
self._simulation_view.currentLayerNumChanged.connect(self._onLayerChanged)
self._simulation_view.colorSchemeLimitsChanged.connect(self._onColorSchemeLimitsChanged)
self._simulation_view.currentPathNumChanged.connect(self._onPathChanged)
self._simulation_view.maxLayersChanged.connect(self._onMaxLayersChanged)
self._simulation_view.maxPathsChanged.connect(self._onMaxPathsChanged)
@ -194,6 +207,7 @@ class SimulationViewProxy(QObject):
# Disconnect all of em again.
self.is_simulationView_selected = False
self._simulation_view.currentLayerNumChanged.disconnect(self._onLayerChanged)
self._simulation_view.colorSchemeLimitsChanged.connect(self._onColorSchemeLimitsChanged)
self._simulation_view.currentPathNumChanged.disconnect(self._onPathChanged)
self._simulation_view.maxLayersChanged.disconnect(self._onMaxLayersChanged)
self._simulation_view.maxPathsChanged.disconnect(self._onMaxPathsChanged)

View file

@ -12,6 +12,8 @@ vertex41core =
uniform lowp float u_min_thickness;
uniform lowp float u_max_line_width;
uniform lowp float u_min_line_width;
uniform lowp float u_max_flow_rate;
uniform lowp float u_min_flow_rate;
uniform lowp int u_layer_view_type;
uniform lowp mat4 u_extruder_opacity; // currently only for max 16 extruders, others always visible
@ -46,7 +48,15 @@ vertex41core =
vec4 feedrateGradientColor(float abs_value, float min_value, float max_value)
{
float value = (abs_value - min_value)/(max_value - min_value);
float value;
if(abs(max_value - min_value) < 0.0001) //Max and min are equal (barring floating point rounding errors).
{
value = 0.5; //Pick a colour in exactly the middle of the range.
}
else
{
value = (abs_value - min_value) / (max_value - min_value);
}
float red = value;
float green = 1-abs(1-4*value);
if (value > 0.375)
@ -59,7 +69,15 @@ vertex41core =
vec4 layerThicknessGradientColor(float abs_value, float min_value, float max_value)
{
float value = (abs_value - min_value)/(max_value - min_value);
float value;
if(abs(max_value - min_value) < 0.0001) //Max and min are equal (barring floating point rounding errors).
{
value = 0.5; //Pick a colour in exactly the middle of the range.
}
else
{
value = (abs_value - min_value) / (max_value - min_value);
}
float red = min(max(4*value-2, 0), 1);
float green = min(1.5*value, 0.75);
if (value > 0.75)
@ -72,7 +90,15 @@ vertex41core =
vec4 lineWidthGradientColor(float abs_value, float min_value, float max_value)
{
float value = (abs_value - min_value) / (max_value - min_value);
float value;
if(abs(max_value - min_value) < 0.0001) //Max and min are equal (barring floating point rounding errors).
{
value = 0.5; //Pick a colour in exactly the middle of the range.
}
else
{
value = (abs_value - min_value) / (max_value - min_value);
}
float red = value;
float green = 1 - abs(1 - 4 * value);
if(value > 0.375)
@ -83,6 +109,30 @@ vertex41core =
return vec4(red, green, blue, 1.0);
}
float clamp(float v)
{
float t = v < 0 ? 0 : v;
return t > 1.0 ? 1.0 : t;
}
// Inspired by https://stackoverflow.com/a/46628410
vec4 flowRateGradientColor(float abs_value, float min_value, float max_value)
{
float t;
if(abs(min_value - max_value) < 0.0001)
{
t = 0;
}
else
{
t = 2.0 * ((abs_value - min_value) / (max_value - min_value)) - 1;
}
float red = clamp(1.5 - abs(2.0 * t - 1.0));
float green = clamp(1.5 - abs(2.0 * t));
float blue = clamp(1.5 - abs(2.0 * t + 1.0));
return vec4(red, green, blue, 1.0);
}
void main()
{
vec4 v1_vertex = a_vertex;
@ -108,6 +158,10 @@ vertex41core =
case 4: // "Line width"
v_color = lineWidthGradientColor(a_line_dim.x, u_min_line_width, u_max_line_width);
break;
case 5: // "Flow"
float flow_rate = a_line_dim.x * a_line_dim.y * a_feedrate;
v_color = flowRateGradientColor(flow_rate, u_min_flow_rate, u_max_flow_rate);
break;
}
v_vertex = world_space_vert.xyz;
@ -148,7 +202,7 @@ geometry41core =
in vec4 v_color[];
in vec3 v_vertex[];
in vec3 v_normal[];
in vec2 v_line_dim[];
in lowp vec2 v_line_dim[];
in int v_extruder[];
in mat4 v_extruder_opacity[];
in float v_prev_line_type[];
@ -212,17 +266,17 @@ geometry41core =
}
size_y = v_line_dim[1].y / 2 + 0.01;
g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position;
g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z));
g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0);
g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; //Actual movement exhibited by the line.
g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); //Lengthwise normal vector pointing backwards.
g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector pointing backwards.
g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x));
g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); //Normal vector pointing right.
g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right.
g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz;
g_vertex_normal_vert = vec3(0.0, 1.0, 0.0);
g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0);
g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector.
g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); //Upwards offset vector. Goes up by half the layer thickness.
if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) {
if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { //Travel or retraction moves.
vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert);
vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert);
@ -231,60 +285,60 @@ geometry41core =
vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
// Travels: flat plane with pointy ends
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_head);
//And reverse so that the line is also visible from the back side.
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up);
EndPrimitive();
} else {
vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz);
vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz);
vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert);
vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert);
vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz);
vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz);
vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert);
vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert);
vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head);
vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head);
vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); //Line start, left vertex.
vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); //Line end, left vertex.
vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); //Line start, top vertex.
vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); //Line end, top vertex.
vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); //Line start, right vertex.
vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); //Line end, right vertex.
vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); //Line start, bottom vertex.
vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); //Line end, bottom vertex.
vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); //Line start, tip.
vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); //Line end, tip.
// All normal lines are rendered as 3d tubes.
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz);
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert);
myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert);
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
EndPrimitive();
// left side
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz);
EndPrimitive();
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert);
myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head);
myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz);
EndPrimitive();
@ -304,10 +358,9 @@ geometry41core =
EndPrimitive();
}
if ((u_show_starts == 1) && (v_prev_line_type[0] != 1) && (v_line_type[0] == 1)) {
float w = v_line_dim[0].x / 2;
float h = v_line_dim[0].y / 2;
float w = size_x;
float h = size_y;
myEmitVertex(v_vertex[0] + vec3( w, h, w), u_starts_color, normalize(vec3( 1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, w, 0.0))); // Front-top-left
myEmitVertex(v_vertex[0] + vec3(-w, h, w), u_starts_color, normalize(vec3(-1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, w, 0.0))); // Front-top-right
@ -323,7 +376,7 @@ geometry41core =
myEmitVertex(v_vertex[0] + vec3(-w, -h, -w), u_starts_color, normalize(vec3(-1.0, -1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, -h, -w, 0.0))); // Back-bottom-right
myEmitVertex(v_vertex[0] + vec3( w, h, -w), u_starts_color, normalize(vec3( 1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, -w, 0.0))); // Back-top-left
myEmitVertex(v_vertex[0] + vec3(-w, h, -w), u_starts_color, normalize(vec3(-1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, -w, 0.0))); // Back-top-right
EndPrimitive();
}
}

View file

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides the Simulation view.",
"api": "7.4.0",
"api": 7,
"i18n-catalog": "cura"
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M8,21H6V3h2V21z M18,3h-2v18h2V3z" />
</svg>

After

Width:  |  Height:  |  Size: 167 B

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M5,20V4c0-0.8,0.9-1.3,1.5-0.9l13,8c0.6,0.4,0.6,1.3,0,1.7l-13,8C5.9,21.3,5,20.8,5,20z M7,5.8v12.4
L17.1,12L7,5.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 247 B

View file

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6mm"
height="6mm"
viewBox="0 0 5.9999999 6"
version="1.1"
id="svg877"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="simulation_pause2.svg">
<defs
id="defs871" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="-5.3551409"
inkscape:cy="17.386031"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2880"
inkscape:window-height="1675"
inkscape:window-x="-13"
inkscape:window-y="-13"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata874">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-11.163774,-122.8006)">
<g
id="g825"
transform="matrix(0.26458333,0,0,0.26458333,10.185689,121.85192)">
<rect
y="5"
x="19"
height="20"
width="2.7552757"
id="rect5192"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.34745646;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="5"
x="9"
height="20"
width="2.7552757"
id="rect5192-5"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.34745646;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6mm"
height="6mm"
viewBox="0 0 6 6"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="simulation_resume2.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="-32.404712"
inkscape:cy="14.267522"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2880"
inkscape:window-height="1675"
inkscape:window-x="-13"
inkscape:window-y="-13"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(81.024887,-389.647)">
<path
sodipodi:type="star"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.50520164;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path847"
sodipodi:sides="3"
sodipodi:cx="-78.732257"
sodipodi:cy="392.65222"
sodipodi:r1="3.0592039"
sodipodi:r2="1.5296021"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m -75.67305,392.65222 -4.588806,2.64935 v -5.2987 z"
inkscape:transform-center-x="0.75529536"
inkscape:transform-center-y="0.40090429" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB