CURA-4525 solved merge conflicts

This commit is contained in:
Jack Ha 2018-01-03 13:52:55 +01:00
commit bfa33c721c
39 changed files with 11005 additions and 337 deletions

View file

@ -682,12 +682,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
file_name = global_stack_file)
# Ensure a unique ID and name
stack._id = global_stack_id_new
# Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the
# bound machine also needs to change.
if stack.getMetaDataEntry("machine", None):
stack.setMetaDataEntry("machine", global_stack_id_new)
stack.setMetaDataEntry("id", global_stack_id_new)
# Only machines need a new name, stacks may be non-unique
stack.setName(global_stack_name_new)
@ -741,7 +736,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
stack.deserialize(extruder_file_content, file_name = extruder_stack_file)
# Ensure a unique ID and name
stack._id = new_id
stack.setMetaDataEntry("id", new_id)
self._container_registry.addContainer(stack)
extruder_stacks_added.append(stack)

View file

@ -153,10 +153,11 @@ class StartSliceJob(Job):
is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
if (node.callDecoration("getBuildPlateNumber") == self._build_plate_number):
if not getattr(node, "_outside_buildarea", False) or not is_non_printing_mesh:
if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh:
temp_list.append(node)
if not is_non_printing_mesh:
has_printing_mesh = True
Job.yieldThread()
#If the list doesn't have any model with suitable settings then clean the list

View file

@ -7,14 +7,11 @@ from UM.FlameProfiler import pyqtSlot
from cura.MachineAction import MachineAction
from UM.Application import Application
from UM.Preferences import Preferences
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Logger import Logger
from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.CuraStackBuilder import CuraStackBuilder
@ -36,7 +33,6 @@ class MachineSettingsAction(MachineAction):
self._container_registry.containerAdded.connect(self._onContainerAdded)
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
self._empty_container = self._container_registry.getEmptyInstanceContainer()
@ -67,7 +63,9 @@ class MachineSettingsAction(MachineAction):
self._global_container_stack, self._global_container_stack.getName() + "_settings")
# Notify the UI in which container to store the machine settings data
container_index = self._global_container_stack.getContainerIndex(definition_changes_container)
from cura.Settings.CuraContainerStack import CuraContainerStack, _ContainerIndexes
container_index = _ContainerIndexes.DefinitionChanges
if container_index != self._container_index:
self._container_index = container_index
self.containerIndexChanged.emit()
@ -82,17 +80,6 @@ class MachineSettingsAction(MachineAction):
if self._backend and self._backend.determineAutoSlicing():
self._backend.tickle()
def _onActiveExtruderStackChanged(self):
extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
if not self._global_container_stack or not extruder_container_stack:
return
# Make sure there is a definition_changes container to store the machine settings
definition_changes_container = extruder_container_stack.definitionChanges
if definition_changes_container == self._empty_container:
definition_changes_container = CuraStackBuilder.createDefinitionChangesContainer(
extruder_container_stack, extruder_container_stack.getId() + "_settings")
containerIndexChanged = pyqtSignal()
@pyqtProperty(int, notify = containerIndexChanged)
@ -217,8 +204,8 @@ class MachineSettingsAction(MachineAction):
Application.getInstance().globalContainerStackChanged.emit()
@pyqtSlot()
def updateMaterialForDiameter(self):
@pyqtSlot(int)
def updateMaterialForDiameter(self, extruder_position: int):
# Updates the material container to a material that matches the material diameter set for the printer
if not self._global_container_stack:
return
@ -226,24 +213,22 @@ class MachineSettingsAction(MachineAction):
if not self._global_container_stack.getMetaDataEntry("has_materials", False):
return
material = ExtruderManager.getInstance().getActiveExtruderStack().material
material_diameter = material.getProperty("material_diameter", "value")
extruder_stack = self._global_container_stack.extruders[str(extruder_position)]
material_diameter = extruder_stack.material.getProperty("material_diameter", "value")
if not material_diameter:
# in case of "empty" material
material_diameter = 0
material_approximate_diameter = str(round(material_diameter))
definition_changes = self._global_container_stack.definitionChanges
machine_diameter = definition_changes.getProperty("material_diameter", "value")
machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
if not machine_diameter:
machine_diameter = self._global_container_stack.definition.getProperty("material_diameter", "value")
machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
machine_approximate_diameter = str(round(machine_diameter))
if material_approximate_diameter != machine_approximate_diameter:
Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
stacks = ExtruderManager.getInstance().getExtruderStacks()
if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
materials_definition = self._global_container_stack.definition.getId()
has_material_variants = self._global_container_stack.getMetaDataEntry("has_variants", False)
@ -251,45 +236,44 @@ class MachineSettingsAction(MachineAction):
materials_definition = "fdmprinter"
has_material_variants = False
for stack in stacks:
old_material = stack.material
search_criteria = {
"type": "material",
"approximate_diameter": machine_approximate_diameter,
"material": old_material.getMetaDataEntry("material", "value"),
"supplier": old_material.getMetaDataEntry("supplier", "value"),
"color_name": old_material.getMetaDataEntry("color_name", "value"),
"definition": materials_definition
}
if has_material_variants:
search_criteria["variant"] = stack.variant.getId()
old_material = extruder_stack.material
search_criteria = {
"type": "material",
"approximate_diameter": machine_approximate_diameter,
"material": old_material.getMetaDataEntry("material", "value"),
"supplier": old_material.getMetaDataEntry("supplier", "value"),
"color_name": old_material.getMetaDataEntry("color_name", "value"),
"definition": materials_definition
}
if has_material_variants:
search_criteria["variant"] = extruder_stack.variant.getId()
if old_material == self._empty_container:
search_criteria.pop("material", None)
search_criteria.pop("supplier", None)
search_criteria.pop("definition", None)
search_criteria["id"] = stack.getMetaDataEntry("preferred_material")
if old_material == self._empty_container:
search_criteria.pop("material", None)
search_criteria.pop("supplier", None)
search_criteria.pop("definition", None)
search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Same material with new diameter is not found, search for generic version of the same material type
search_criteria.pop("supplier", None)
search_criteria["color_name"] = "Generic"
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Same material with new diameter is not found, search for generic version of the same material type
search_criteria.pop("supplier", None)
search_criteria["color_name"] = "Generic"
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Generic material with new diameter is not found, search for preferred material
search_criteria.pop("color_name", None)
search_criteria.pop("material", None)
search_criteria["id"] = stack.getMetaDataEntry("preferred_material")
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Preferred material with new diameter is not found, search for any material
search_criteria.pop("id", None)
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Just use empty material as a final fallback
materials = [self._empty_container]
if not materials:
# Generic material with new diameter is not found, search for preferred material
search_criteria.pop("color_name", None)
search_criteria.pop("material", None)
search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Preferred material with new diameter is not found, search for any material
search_criteria.pop("id", None)
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Just use empty material as a final fallback
materials = [self._empty_container]
Logger.log("i", "Selecting new material: %s" % materials[0].getId())
Logger.log("i", "Selecting new material: %s" % materials[0].getId())
stack.material = materials[0]
extruder_stack.material = materials[0]

View file

@ -292,18 +292,6 @@ Cura.MachineAction
}
}
}
Loader
{
id: materialDiameterField
visible: Cura.MachineManager.hasMaterials
sourceComponent: numericTextFieldWithUnit
property string settingKey: "material_diameter"
property string unit: catalog.i18nc("@label", "mm")
property string tooltip: catalog.i18nc("@tooltip", "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile.")
property var afterOnEditingFinished: manager.updateMaterialForDiameter
property string label: catalog.i18nc("@label", "Material diameter")
}
}
}
@ -360,7 +348,6 @@ Cura.MachineAction
if(currentIndex > 0)
{
contentItem.forceActiveFocus();
Cura.ExtruderManager.setActiveExtruderIndex(currentIndex - 1);
}
}
@ -397,6 +384,25 @@ Cura.MachineAction
property bool isExtruderSetting: true
}
Loader
{
id: materialDiameterField
visible: Cura.MachineManager.hasMaterials
sourceComponent: numericTextFieldWithUnit
property string settingKey: "material_diameter"
property string label: catalog.i18nc("@label", "Material diameter")
property string unit: catalog.i18nc("@label", "mm")
property string tooltip: catalog.i18nc("@tooltip", "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile.")
property var afterOnEditingFinished:
{
if (settingsTabs.currentIndex > 0)
{
manager.updateMaterialForDiameter(settingsTabs.currentIndex - 1);
}
}
property bool isExtruderSetting: true
}
Loader
{
id: extruderOffsetXField
@ -495,7 +501,7 @@ Cura.MachineAction
{
if(settingsTabs.currentIndex > 0)
{
return Cura.MachineManager.activeStackId;
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
}
return "";
}
@ -513,11 +519,11 @@ Cura.MachineAction
checked: String(propertyProvider.properties.value).toLowerCase() != 'false'
onClicked:
{
propertyProvider.setPropertyValue("value", checked);
if(_forceUpdateOnChange)
{
manager.forceUpdate();
}
propertyProvider.setPropertyValue("value", checked);
if(_forceUpdateOnChange)
{
manager.forceUpdate();
}
}
}
}
@ -548,7 +554,7 @@ Cura.MachineAction
{
if(settingsTabs.currentIndex > 0)
{
return Cura.MachineManager.activeStackId;
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
}
return "";
}
@ -581,7 +587,10 @@ Cura.MachineAction
TextField
{
id: textField
text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
text: {
const value = propertyProvider.properties.value;
return value ? value : "";
}
validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.]{0,6}/ : /[0-9\.]{0,6}/ }
onEditingFinished:
{
@ -590,12 +599,7 @@ Cura.MachineAction
propertyProvider.setPropertyValue("value", text);
if(_forceUpdateOnChange)
{
var extruderIndex = Cura.ExtruderManager.activeExtruderIndex;
manager.forceUpdate();
if(Cura.ExtruderManager.activeExtruderIndex != extruderIndex)
{
Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex)
}
}
if(_afterOnEditingFinished)
{
@ -641,7 +645,7 @@ Cura.MachineAction
{
if(settingsTabs.currentIndex > 0)
{
return Cura.MachineManager.activeStackId;
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
}
return "";
}

View file

@ -4,6 +4,7 @@
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QOpenGLContext
from PyQt5.QtWidgets import QApplication
from UM.Application import Application
@ -13,6 +14,7 @@ from UM.Logger import Logger
from UM.Math.Color import Color
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Message import Message
from UM.Platform import Platform
from UM.PluginRegistry import PluginRegistry
from UM.Preferences import Preferences
from UM.Resources import Resources
@ -24,6 +26,7 @@ from UM.View.GL.OpenGLContext import OpenGLContext
from UM.View.View import View
from UM.i18n import i18nCatalog
from cura.ConvexHullNode import ConvexHullNode
from cura.CuraApplication import CuraApplication
from .NozzleNode import NozzleNode
from .SimulationPass import SimulationPass
@ -414,6 +417,23 @@ class SimulationView(View):
return True
if event.type == Event.ViewActivateEvent:
# FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
# This can happen when you do the following steps:
# 1. Start Cura
# 2. Load a model
# 3. Switch to Custom mode
# 4. Select the model and click on the per-object tool icon
# 5. Switch view to Layer view or X-Ray
# 6. Cura will very likely crash
# It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why.
# This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL
# context is None.
if Platform.isOSX():
if QOpenGLContext.currentContext() is None:
Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later")
CuraApplication.getInstance().callLater(lambda e=event: self.event(e))
return
# Make sure the SimulationPass is created
layer_pass = self.getSimulationPass()
self.getRenderer().addRenderPass(layer_pass)

View file

@ -187,7 +187,7 @@ geometry41core =
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert));
//And reverse so that the line is also visible from the back side.
//And reverse so that the line is also visible from the back side.
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
@ -212,17 +212,17 @@ geometry41core =
EndPrimitive();
// left side
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
EndPrimitive();
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
EndPrimitive();

View file

@ -39,19 +39,26 @@ class SliceInfo(Extension):
Preferences.getInstance().addPreference("info/send_slice_info", True)
Preferences.getInstance().addPreference("info/asked_send_slice_info", False)
if not Preferences.getInstance().getValue("info/asked_send_slice_info") and Preferences.getInstance().getValue("info/send_slice_info"):
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymised slicing statistics. You can disable this in the preferences."),
if not Preferences.getInstance().getValue("info/asked_send_slice_info"):
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."),
lifetime = 0,
dismissable = False,
title = catalog.i18nc("@info:title", "Collecting Data"))
self.send_slice_info_message.addAction("Dismiss", catalog.i18nc("@action:button", "Dismiss"), None, "")
self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
self.send_slice_info_message.addAction("Disable", name = catalog.i18nc("@action:button", "Disable"), icon = None,
description = catalog.i18nc("@action:tooltip", "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."), button_style = Message.ActionButtonStyle.LINK)
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
self.send_slice_info_message.show()
## Perform action based on user input.
# Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it.
def messageActionTriggered(self, message_id, action_id):
self.send_slice_info_message.hide()
Preferences.getInstance().setValue("info/asked_send_slice_info", True)
if action_id == "Disable":
CuraApplication.getInstance().showPreferences()
self.send_slice_info_message.hide()
def _onWriteStarted(self, output_device):
try:

View file

@ -122,26 +122,6 @@ class VersionUpgrade30to31(VersionUpgrade):
if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
if parser["metadata"]["type"] == "definition_changes":
if parser["general"]["definition"] == "custom":
# We are only interested in machine_nozzle_size
if parser.has_option("values", "machine_nozzle_size"):
machine_nozzle_size = parser["values"]["machine_nozzle_size"]
machine_extruder_count = '1' # by default it is 1 and the value cannot be stored in the global stack
if parser.has_option("values", "machine_extruder_count"):
machine_extruder_count = parser["values"]["machine_extruder_count"]
if machine_extruder_count == '1':
definition_name = parser["general"]["name"]
machine_extruders = self._getSingleExtrusionMachineExtruders(definition_name)
# For single extruder machine we need only first extruder
if len(machine_extruders) !=0:
self._updateSingleExtruderDefinitionFile(machine_extruders, machine_nozzle_size)
parser.remove_option("values", "machine_nozzle_size")
# Update version numbers
parser["general"]["version"] = "2"
parser["metadata"]["setting_version"] = "4"
@ -220,123 +200,6 @@ class VersionUpgrade30to31(VersionUpgrade):
return quality_changes_containers
def _getSingleExtrusionMachineExtruders(self, definition_name):
machine_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.MachineStack)
machine_instance_id = None
# Find machine instances
for item in os.listdir(machine_instances_dir):
file_path = os.path.join(machine_instances_dir, item)
if not os.path.isfile(file_path):
continue
parser = configparser.ConfigParser(interpolation=None)
try:
parser.read([file_path])
except:
# skip, it is not a valid stack file
continue
if not parser.has_option("metadata", "type"):
continue
if "machine" != parser["metadata"]["type"]:
continue
if not parser.has_option("general", "id"):
continue
id = parser["general"]["id"]
if id + "_settings" != definition_name:
continue
else:
machine_instance_id = id
break
if machine_instance_id is not None:
extruders_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack)
#"machine",[extruders]
extruder_instances = []
# Find all custom extruders for found machines
for item in os.listdir(extruders_instances_dir):
file_path = os.path.join(extruders_instances_dir, item)
if not os.path.isfile(file_path):
continue
parser = configparser.ConfigParser(interpolation=None)
try:
parser.read([file_path])
except:
# skip, it is not a valid stack file
continue
if not parser.has_option("metadata", "type"):
continue
if "extruder_train" != parser["metadata"]["type"]:
continue
if not parser.has_option("metadata", "machine"):
continue
if not parser.has_option("metadata", "position"):
continue
if machine_instance_id != parser["metadata"]["machine"]:
continue
extruder_instances.append(parser)
return extruder_instances
# Find extruder definition at index 0 and update its values
def _updateSingleExtruderDefinitionFile(self, extruder_instances_per_machine, machine_nozzle_size):
defintion_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer)
for item in os.listdir(defintion_instances_dir):
file_path = os.path.join(defintion_instances_dir, item)
if not os.path.isfile(file_path):
continue
parser = configparser.ConfigParser(interpolation=None)
try:
parser.read([file_path])
except:
# skip, it is not a valid stack file
continue
if not parser.has_option("general", "name"):
continue
name = parser["general"]["name"]
custom_extruder_at_0_position = None
for extruder_instance in extruder_instances_per_machine:
definition_position = extruder_instance["metadata"]["position"]
if definition_position == "0":
custom_extruder_at_0_position = extruder_instance
break
# If not null, then parsed file is for first extuder and then can be updated. I need to update only
# first, because this update for single extuder machine
if custom_extruder_at_0_position is not None:
#Add new value
parser["values"]["machine_nozzle_size"] = machine_nozzle_size
definition_output = io.StringIO()
parser.write(definition_output)
with open(file_path, "w") as f:
f.write(definition_output.getvalue())
return True
return False
def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes):
suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower())
machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "")
@ -369,4 +232,4 @@ class VersionUpgrade30to31(VersionUpgrade):
quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer)
with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w") as f:
f.write(extruder_quality_changes_output.getvalue())
f.write(extruder_quality_changes_output.getvalue())

View file

@ -185,7 +185,7 @@ class X3DReader(MeshReader):
got_center = (center.x != 0 or center.y != 0 or center.z != 0)
T = self.transform
if trans.x != 0 or trans.y != 0 or trans.z !=0:
if trans.x != 0 or trans.y != 0 or trans.z != 0:
T.translate(trans)
if got_center:
T.translate(center)

View file

@ -2,10 +2,13 @@
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
from PyQt5.QtGui import QOpenGLContext
from UM.Application import Application
from UM.Logger import Logger
from UM.Math.Color import Color
from UM.PluginRegistry import PluginRegistry
from UM.Platform import Platform
from UM.Event import Event
from UM.View.View import View
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
@ -13,6 +16,8 @@ from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
from cura.CuraApplication import CuraApplication
from . import XRayPass
## View used to display a see-through version of objects with errors highlighted.
@ -52,6 +57,23 @@ class XRayView(View):
def event(self, event):
if event.type == Event.ViewActivateEvent:
# FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
# This can happen when you do the following steps:
# 1. Start Cura
# 2. Load a model
# 3. Switch to Custom mode
# 4. Select the model and click on the per-object tool icon
# 5. Switch view to Layer view or X-Ray
# 6. Cura will very likely crash
# It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why.
# This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL
# context is None.
if Platform.isOSX():
if QOpenGLContext.currentContext() is None:
Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later")
CuraApplication.getInstance().callLater(lambda e = event: self.event(e))
return
if not self._xray_pass:
# Currently the RenderPass constructor requires a size > 0
# This should be fixed in RenderPass's constructor.