diff --git a/src/Mod/Assembly/JointObject.py b/src/Mod/Assembly/JointObject.py index 314572a7e1..4ef2c223e4 100644 --- a/src/Mod/Assembly/JointObject.py +++ b/src/Mod/Assembly/JointObject.py @@ -146,7 +146,11 @@ def solveIfAllowed(assembly, storePrev=False): def get_camera_height(gui_doc): - camera = gui_doc.ActiveView.getCameraNode() + activeView = get_active_view(gui_doc) + if activeView is None: + return 200 + + camera = activeView.getCameraNode() # Check if the camera is a perspective camera if isinstance(camera, coin.SoPerspectiveCamera): @@ -158,6 +162,14 @@ def get_camera_height(gui_doc): return 200 +def get_active_view(gui_doc): + activeView = gui_doc.ActiveView + if activeView is None: + # Fall back on current active document. + activeView = Gui.ActiveDocument.ActiveView + return activeView + + # The joint object consists of 2 JCS (joint coordinate systems) and a Joint Type. # A JCS is a placement that is computed (unless it is detached) from : # - An Object name: this is the name of the solid. It can be any Part::Feature solid. @@ -705,12 +717,14 @@ class ViewProviderJoint: self.app_obj = vobj.Object app_doc = self.app_obj.Document self.gui_doc = Gui.getDocument(app_doc) - camera = self.gui_doc.ActiveView.getCameraNode() - self.cameraSensor = coin.SoFieldSensor(self.camera_callback, camera) - if isinstance(camera, coin.SoPerspectiveCamera): - self.cameraSensor.attach(camera.focalDistance) - elif isinstance(camera, coin.SoOrthographicCamera): - self.cameraSensor.attach(camera.height) + activeView = get_active_view(self.gui_doc) + if activeView is not None: + camera = activeView.getCameraNode() + self.cameraSensor = coin.SoFieldSensor(self.camera_callback, camera) + if isinstance(camera, coin.SoPerspectiveCamera): + self.cameraSensor.attach(camera.focalDistance) + elif isinstance(camera, coin.SoOrthographicCamera): + self.cameraSensor.attach(camera.height) self.transform1 = coin.SoTransform() self.transform2 = coin.SoTransform() @@ -1014,15 +1028,19 @@ class ViewProviderGroundedJoint: self.app_obj = vobj.Object app_doc = self.app_obj.Document self.gui_doc = Gui.getDocument(app_doc) - camera = self.gui_doc.ActiveView.getCameraNode() - self.cameraSensor = coin.SoFieldSensor(self.camera_callback, camera) - if isinstance(camera, coin.SoPerspectiveCamera): - self.cameraSensor.attach(camera.focalDistance) - elif isinstance(camera, coin.SoOrthographicCamera): - self.cameraSensor.attach(camera.height) - self.cameraSensorRot = coin.SoFieldSensor(self.camera_callback_rotation, camera) - self.cameraSensorRot.attach(camera.orientation) + activeView = get_active_view(self.gui_doc) + if activeView is not None: + camera = activeView.getCameraNode() + + self.cameraSensor = coin.SoFieldSensor(self.camera_callback, camera) + if isinstance(camera, coin.SoPerspectiveCamera): + self.cameraSensor.attach(camera.focalDistance) + elif isinstance(camera, coin.SoOrthographicCamera): + self.cameraSensor.attach(camera.height) + + self.cameraSensorRot = coin.SoFieldSensor(self.camera_callback_rotation, camera) + self.cameraSensorRot.attach(camera.orientation) factor = self.get_lock_factor() self.scale = coin.SoScale() @@ -1095,11 +1113,13 @@ class ViewProviderGroundedJoint: self.set_lock_rotation() def set_lock_rotation(self): - camera = self.gui_doc.ActiveView.getCameraNode() - rotation = camera.orientation.getValue() + activeView = get_active_view(self.gui_doc) + if activeView is not None: + camera = activeView.getCameraNode() + rotation = camera.orientation.getValue() - q = rotation.getValue() - self.transform.rotation.setValue(q[0], q[1], q[2], q[3]) + q = rotation.getValue() + self.transform.rotation.setValue(q[0], q[1], q[2], q[3]) def get_lock_factor(self): return get_camera_height(self.gui_doc) / 300 diff --git a/src/Mod/Assembly/UtilsAssembly.py b/src/Mod/Assembly/UtilsAssembly.py index 431aa384ea..f6fa9bb15e 100644 --- a/src/Mod/Assembly/UtilsAssembly.py +++ b/src/Mod/Assembly/UtilsAssembly.py @@ -180,7 +180,7 @@ def isBodySubObject(typeId): def getContainingPart(full_name, selected_object, activeAssemblyOrPart=None): # full_name is "Assembly.Assembly1.LinkOrPart1.LinkOrBox.Edge16" -> LinkOrPart1 # or "Assembly.Assembly1.LinkOrPart1.LinkOrBody.pad.Edge16" -> LinkOrPart1 - # or "Assembly.Assembly1.LinkOrPart1.LinkOrBody.Sketch.Edge1" -> LinkOrBody + # or "Assembly.Assembly1.LinkOrPart1.LinkOrBody.Sketch.Edge1" -> LinkOrPart1 if selected_object is None: App.Console.PrintError("getContainingPart() in UtilsAssembly.py selected_object is None") @@ -213,6 +213,7 @@ def getContainingPart(full_name, selected_object, activeAssemblyOrPart=None): if not activeAssemblyOrPart: return obj elif activeAssemblyOrPart in obj.OutListRecursive or obj == activeAssemblyOrPart: + # If the user put the assembly inside a Part, then we ignore it. continue else: return obj @@ -222,7 +223,7 @@ def getContainingPart(full_name, selected_object, activeAssemblyOrPart=None): if linked_obj.TypeId == "PartDesign::Body" and isBodySubObject(selected_object.TypeId): if selected_object in linked_obj.OutListRecursive: return obj - if linked_obj.TypeId == "App::Part": + if linked_obj.TypeId in ["App::Part", "Assembly::AssemblyObject"]: # linked_obj_doc = linked_obj.Document # selected_obj_in_doc = doc.getObject(selected_object.Name) if selected_object in linked_obj.OutListRecursive: