diff --git a/ahb_raster_view.py b/ahb_raster_view.py index 929ba7b..30c0323 100644 --- a/ahb_raster_view.py +++ b/ahb_raster_view.py @@ -79,12 +79,33 @@ class RasterView: offset = self.image_view.Assembly_handbook_ViewVolumeOffset p = point2d - offset return self.image_x_dir_inv * p.x + self.image_y_dir_inv * p.y + self.image_z_dir_inv * p.z + + def _flatten_objects_tree(self, obj_list): + result = [] + for obj in obj_list: + if obj.TypeId == 'Part::FeaturePython' and hasattr(obj, 'LinkedObject'): # variant link + result.extend(self._flatten_objects_tree(obj.Group)) + elif obj.TypeId in ['App::Link']: + result.extend(self._flatten_objects_tree([obj.LinkedObject])) + elif obj.TypeId in ['App::Part', 'App::DocumentObjectGroup']: + result.extend(self._flatten_objects_tree(obj.Group)) + elif obj.TypeId in ['Part::Feature', 'Part::FeaturePython', 'PartDesign::Body', 'PartDesign::CoordinateSystem', 'PartDesign::Line', 'Part::Mirroring', 'Part::Cut']: + result.append(obj) + if hasattr(obj, 'Group'): + result.extend(self._flatten_objects_tree(obj.Group)) + + return result + + def _should_render(self, obj): + return obj.TypeId in ['Part::Feature', 'Part::FeaturePython', 'PartDesign::Body', 'Part::Mirroring', 'Part::Cut'] def render(self): from pivy import coin import os from PIL import Image, ImageDraw, ImageChops + workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench + view = self.source_view self.init_image() @@ -94,36 +115,87 @@ class RasterView: dir = os.path.dirname(self.image_file_name) if not os.path.exists(dir): os.makedirs(dir) - + doc = App.newDocument('tmp_raster', hidden=False, temp=False) - for part in view.XSource: - link = doc.addObject('App::Link', part.Name) - link.Label = part.Label - if part.TypeId == 'App::Link': - link.LinkedObject = part.LinkedObject - link.Placement = part.Placement - elif part.TypeId == 'Part::FeaturePython' and hasattr(part, 'LinkedObject'): # variant link - link.LinkedObject = part.LinkedObject - link.Placement = part.Placement - else: - link.LinkedObject = part + + objects_to_reset = {} + try: + for part in view.XSource: + link = doc.addObject('App::Link', part.Name) + link.Label = part.Label + if part.TypeId == 'App::Link': + link.LinkedObject = part.LinkedObject + link.Placement = part.Placement + elif part.TypeId == 'Part::FeaturePython' and hasattr(part, 'LinkedObject'): # variant link + link.LinkedObject = part.LinkedObject + link.Placement = part.Placement + else: + link.LinkedObject = part + + new_part = workbench.techDrawExtensions.isNewPartInView(view, part) - docView = Gui.getDocument(doc.Name).mdiViewsOfType('Gui::View3DInventor')[0] - - cam = docView.getCameraNode() - - rot = coin.SbRotation(coin.SbVec3f(1,0,0), coin.SbVec3f(view.XDirection.x,view.XDirection.y,view.XDirection.z)) - rot *= coin.SbRotation(coin.SbVec3f(0,0,1), coin.SbVec3f(view.Direction.x,view.Direction.y,view.Direction.z)) - cam.orientation.setValue(rot) - - docView.fitAll() - - viewVolume = cam.getViewVolume(0.0) - self.image_view.Assembly_handbook_ViewVolumeWidth = viewVolume.getWidth() - self.image_view.Assembly_handbook_ViewVolumeHeight = viewVolume.getHeight() - self.image_view.Assembly_handbook_ViewVolumeDepth = viewVolume.getDepth() - - docView.saveImage(self.image_file_name, 4096, 4096, "#ffffff") + link.ViewObject.OverrideMaterial = True + link.ViewObject.ShapeMaterial.DiffuseColor = (0.0, 0.0, 0.0, 0.0) if new_part else (0.5, 0.5, 0.5, 0.0) # this actually changes the line color + + # in current version of freecad, link override material does not allow to override all material properties, for example emissive color, so we have to change material of the linked object + for obj in self._flatten_objects_tree([link]): + if obj in objects_to_reset.keys(): + continue + + if self._should_render(obj): + objects_to_reset[obj] = ( + obj.ViewObject.LineColor, + obj.ViewObject.ShapeMaterial.AmbientColor, + obj.ViewObject.ShapeMaterial.DiffuseColor, + obj.ViewObject.ShapeMaterial.SpecularColor, + obj.ViewObject.ShapeMaterial.EmissiveColor, + obj.ViewObject.LineWidth + ) + + obj.ViewObject.LineColor = (0.0, 0.0, 0.0, 0.0) + obj.ViewObject.ShapeMaterial.AmbientColor = (0.0, 0.0, 0.0, 0.0) + obj.ViewObject.ShapeMaterial.DiffuseColor = (0.0, 0.0, 0.0, 0.0) + obj.ViewObject.ShapeMaterial.SpecularColor = (0.0, 0.0, 0.0, 0.0) + obj.ViewObject.ShapeMaterial.EmissiveColor = (1.0, 1.0, 1.0, 0.0) + + # We need to set two different values otherwise freecad does not always update LineWidth of sub-elements + obj.ViewObject.LineWidth = 1.0 + obj.ViewObject.LineWidth = 2.0 + else: + objects_to_reset[obj] = ( + obj.ViewObject.Visibility, + ) + + obj.ViewObject.Visibility = False + + docView = Gui.getDocument(doc.Name).mdiViewsOfType('Gui::View3DInventor')[0] + + cam = docView.getCameraNode() + + rot = coin.SbRotation(coin.SbVec3f(1,0,0), coin.SbVec3f(view.XDirection.x,view.XDirection.y,view.XDirection.z)) + rot *= coin.SbRotation(coin.SbVec3f(0,0,1), coin.SbVec3f(view.Direction.x,view.Direction.y,view.Direction.z)) + cam.orientation.setValue(rot) + + docView.fitAll() + + viewVolume = cam.getViewVolume(0.0) + self.image_view.Assembly_handbook_ViewVolumeWidth = viewVolume.getWidth() + self.image_view.Assembly_handbook_ViewVolumeHeight = viewVolume.getHeight() + self.image_view.Assembly_handbook_ViewVolumeDepth = viewVolume.getDepth() + + docView.saveImage(self.image_file_name, 4096, 4096, "#ffffff") + + finally: + for obj, props in objects_to_reset.items(): + if self._should_render(obj): + obj.ViewObject.LineColor = props[0] + obj.ViewObject.ShapeMaterial.AmbientColor = props[1] + obj.ViewObject.ShapeMaterial.DiffuseColor = props[2] + obj.ViewObject.ShapeMaterial.SpecularColor = props[3] + obj.ViewObject.ShapeMaterial.EmissiveColor = props[4] + obj.ViewObject.LineWidth = props[5] + else: + obj.ViewObject.Visibility = props[0] with Image.open(self.image_file_name) as img: original_size = img.size