def _onSelectedFaceChanged(self): self._handle.setEnabled(not Selection.getFaceSelectMode()) selected_face = Selection.getSelectedFace() if not Selection.getSelectedFace() or not (Selection.hasSelection() and Selection.getFaceSelectMode()): return original_node, face_id = selected_face meshdata = original_node.getMeshDataTransformed() if not meshdata or face_id < 0: return rotation_point, face_normal = meshdata.getFacePlane(face_id) rotation_point_vector = Vector(rotation_point[0], rotation_point[1], rotation_point[2]) face_normal_vector = Vector(face_normal[0], face_normal[1], face_normal[2]) rotation_quaternion = Quaternion.rotationTo(face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0)) operation = GroupedOperation() current_node = None # type: Optional[SceneNode] for node in Selection.getAllSelectedObjects(): current_node = node parent_node = current_node.getParent() while parent_node and parent_node.callDecoration("isGroup"): current_node = parent_node parent_node = current_node.getParent() if current_node is None: return rotate_operation = RotateOperation(current_node, rotation_quaternion, rotation_point_vector) operation.addOperation(rotate_operation) operation.push()
def _getSelectedTriangles( self, current_surface: Tuple[SceneNode, int], surface_type: SmartSliceScene.HighlightFace.SurfaceType ) -> Tuple[pywim.geom.tri.Face, pywim.geom.Vector]: if current_surface is None: current_surface = Selection.getSelectedFace() if current_surface is None: return None, None node, face_id = current_surface smart_slice_node = findChildSceneNode(node, SmartSliceScene.Root) interactive_mesh = smart_slice_node.getInteractiveMesh() if interactive_mesh is None: return None, None if surface_type == SmartSliceScene.HighlightFace.SurfaceType.Flat: selected_face = interactive_mesh.select_planar_face(face_id) elif surface_type == SmartSliceScene.HighlightFace.SurfaceType.Concave: selected_face = interactive_mesh.select_concave_face(face_id) elif surface_type == SmartSliceScene.HighlightFace.SurfaceType.Convex: selected_face = interactive_mesh.select_convex_face(face_id) axis = None if surface_type == SmartSliceScene.HighlightFace.SurfaceType.Flat: axis = selected_face.planar_axis() else: axis = selected_face.rotation_axis() return selected_face, axis
def _onSelectedFaceChanged(self, current_surface=None): """ Gets face id and triangles from current face selection """ if getPrintableNodes() and Selection.isSelected(getPrintableNodes( )[0]): # Fixes bug for when scene is unselected if not self.getEnabled() or not self._select: return if self._bc_list is None: return bc_node = self._bc_list.getActiveNode() if bc_node is None: return try: selected_face, axis = self._getSelectedTriangles( current_surface, bc_node.surface_type) except Exception as exc: Logger.logException("e", "Unable to select face") selected_face = None if selected_face is not None: bc_node.selection = Selection.getSelectedFace() bc_node.setMeshDataFromPywimTriangles(selected_face, axis) self.selectedFaceChanged.emit(bc_node)
def _onSelectedFaceChanged(self): if not self._select_face_mode: return self._handle.setEnabled(not Selection.getFaceSelectMode()) selected_face = Selection.getSelectedFace() if not Selection.getSelectedFace() or not ( Selection.hasSelection() and Selection.getFaceSelectMode()): return original_node, face_id = selected_face meshdata = original_node.getMeshDataTransformed() if not meshdata or face_id < 0: return if face_id > (meshdata.getVertexCount() / 3 if not meshdata.hasIndices() else meshdata.getFaceCount()): return face_mid, face_normal = meshdata.getFacePlane(face_id) object_mid = original_node.getBoundingBox().center rotation_point_vector = Vector(object_mid.x, object_mid.y, face_mid[2]) face_normal_vector = Vector(face_normal[0], face_normal[1], face_normal[2]) rotation_quaternion = Quaternion.rotationTo( face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0)) operation = GroupedOperation() current_node = None # type: Optional[SceneNode] for node in Selection.getAllSelectedObjects(): current_node = node parent_node = current_node.getParent() while parent_node and parent_node.callDecoration("isGroup"): current_node = parent_node parent_node = current_node.getParent() if current_node is None: return rotate_operation = RotateOperation(current_node, rotation_quaternion, rotation_point_vector) gravity_operation = GravityOperation(current_node) operation.addOperation(rotate_operation) operation.addOperation(gravity_operation) operation.push()
def test_addRemoveSelection(self): node_1 = SceneNode() Selection.add(node_1) Selection.setFace(node_1, 99) assert Selection.getAllSelectedObjects() == [node_1] Selection.remove(node_1) assert Selection.getAllSelectedObjects() == [] assert Selection.getSelectedFace() is None
def onSelectedFaceChanged(self, scene_node, face_id): # Throw out "fake" selection changes if Selection.getSelectedFace() is None: return if self._selection_mode is SelectionMode.AnchorMode: if Selection.getSelectedFace()[1] == self._anchoredID: return elif self._selection_mode is SelectionMode.LoadMode: if Selection.getSelectedFace()[1] == self._loadedID: return select_tool = Application.getInstance().getController().getTool( "SmartSlicePlugin_SelectTool") selected_triangles = list( select_tool._interactive_mesh.select_planar_face(face_id)) # If busy, add it to 'pending changes' and ask user to confirm if self.connector.status in { SmartSliceCloudStatus.BusyValidating, SmartSliceCloudStatus.BusyOptimizing, SmartSliceCloudStatus.Optimized }: self._propertiesChanged.append(SmartSliceProperty.SelectedFace) self._changedValues.append(face_id) self._changedValues.append(scene_node) self._changedValues.append(selected_triangles) self.connector.confirmPendingChanges() else: if self._selection_mode is SelectionMode.AnchorMode: self._anchoredID = face_id self._anchoredNode = scene_node self._anchoredTris = selected_triangles self.proxy._anchorsApplied = 1 # TODO: Change this when > 1 anchors in Use Case self.applyAnchor() elif self._selection_mode is SelectionMode.LoadMode: self._loadedID = face_id self._loadedNode = scene_node self._loadedTris = selected_triangles self.proxy._loadsApplied = 1 # TODO: Change this when > 1 loads in Use Case self.applyLoad() self.connector.prepareValidation()
def _onSelectedFaceChanged(self, curr_sf=None): if not self.getEnabled(): return curr_sf = Selection.getSelectedFace() if curr_sf is None: return self._calculateMesh() scene_node, face_id = curr_sf self._handle._connector.propertyHandler.onSelectedFaceChanged(scene_node, face_id)
def bottomFaceSelection(self) -> None: selected_face = Selection.getSelectedFace() if not selected_face: Logger.log( "e", "Bottom face operation shouldn't have been called without a selected face." ) return original_node, face_id = selected_face meshdata = original_node.getMeshDataTransformed() if not meshdata or face_id < 0 or face_id > Selection.getMaxFaceSelectionId( ): return rotation_point, face_normal = meshdata.getFacePlane(face_id) rotation_point_vector = Vector(rotation_point[0], rotation_point[1], rotation_point[2]) face_normal_vector = Vector(face_normal[0], face_normal[1], face_normal[2]) rotation_quaternion = Quaternion.rotationTo( face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0)) operation = GroupedOperation() current_node = None # type: Optional[SceneNode] for node in Selection.getAllSelectedObjects(): current_node = node parent_node = current_node.getParent() while parent_node and parent_node.callDecoration("isGroup"): current_node = parent_node parent_node = current_node.getParent() if current_node is None: return rotate_operation = RotateOperation(current_node, rotation_quaternion, rotation_point_vector) operation.addOperation(rotate_operation) operation.push()
def test_toggleFace(self): Selection.selectedFaceChanged = MagicMock() node_1 = SceneNode() node_2 = SceneNode() assert Selection.getSelectedFace() is None Selection.toggleFace(node_1, 91) assert Selection.getSelectedFace() == (node_1, 91) Selection.toggleFace(node_2, 92) assert Selection.getSelectedFace() == (node_2, 92) Selection.toggleFace(node_2, 93) assert Selection.getSelectedFace() == (node_2, 93) Selection.toggleFace(node_2, 93) assert Selection.getSelectedFace() is None Selection.toggleFace(node_2, 93) assert Selection.getSelectedFace() == (node_2, 93) Selection.clearFace() assert Selection.getSelectedFace() is None assert Selection.selectedFaceChanged.emit.call_count == 6
def hasFaceSelected(self): return Selection.getSelectedFace() is not None
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() if not self._extruders_model: self._extruders_model = Application.getInstance( ).getExtrudersModel() if not self._theme: self._theme = Application.getInstance().getTheme() if not self._enabled_shader: self._enabled_shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "overhang.shader")) self._enabled_shader.setUniformValue( "u_overhangColor", Color(*self._theme.getColor("model_overhang").getRgb())) if not self._disabled_shader: self._disabled_shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "striped.shader")) self._disabled_shader.setUniformValue( "u_diffuseColor1", Color(*self._theme.getColor("model_unslicable").getRgb())) self._disabled_shader.setUniformValue( "u_diffuseColor2", Color(*self._theme.getColor("model_unslicable_alt").getRgb())) self._disabled_shader.setUniformValue("u_width", 50.0) if not self._non_printing_shader: self._non_printing_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "transparent_object.shader")) self._non_printing_shader.setUniformValue( "u_diffuseColor", Color(*self._theme.getColor("model_non_printing").getRgb())) self._non_printing_shader.setUniformValue("u_opacity", 0.6) if not self._support_mesh_shader: self._support_mesh_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "striped.shader")) self._support_mesh_shader.setUniformValue("u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) global_container_stack = Application.getInstance( ).getGlobalContainerStack() if global_container_stack: if Application.getInstance().getPreferences().getValue( "view/show_overhang"): # Make sure the overhang angle is valid before passing it to the shader if self._support_angle is not None and self._support_angle >= 0 and self._support_angle <= 90: self._enabled_shader.setUniformValue( "u_overhangAngle", math.cos(math.radians(90 - self._support_angle))) else: self._enabled_shader.setUniformValue( "u_overhangAngle", math.cos(math.radians(0)) ) #Overhang angle of 0 causes no area at all to be marked as overhang. else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) for node in DepthFirstIterator(scene.getRoot()): if not node.render(renderer): if node.getMeshData() and node.isVisible( ) and not node.callDecoration("getLayerData"): uniforms = {} shade_factor = 1.0 per_mesh_stack = node.callDecoration("getStack") extruder_index = node.callDecoration( "getActiveExtruderPosition") if extruder_index is None: extruder_index = "0" extruder_index = int(extruder_index) # Use the support extruder instead of the active extruder if this is a support_mesh if per_mesh_stack: if per_mesh_stack.getProperty("support_mesh", "value"): extruder_index = int( global_container_stack. getExtruderPositionValueWithDefault( "support_extruder_nr")) try: material_color = self._extruders_model.getItem( extruder_index)["color"] except KeyError: material_color = self._extruders_model.defaultColors[0] if extruder_index != ExtruderManager.getInstance( ).activeExtruderIndex: # Shade objects that are printed with the non-active extruder 25% darker shade_factor = 0.6 try: # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0]) uniforms["diffuse_color"] = [ shade_factor * int(material_color[1:3], 16) / 255, shade_factor * int(material_color[3:5], 16) / 255, shade_factor * int(material_color[5:7], 16) / 255, 1.0 ] # Color the currently selected face-id. face = Selection.getSelectedFace() uniforms["selected_face"] = ( Selection.getMaxFaceSelectionId() + 1) if not face or node != face[0] else face[1] except ValueError: pass if node.callDecoration("isNonPrintingMesh"): if per_mesh_stack and (per_mesh_stack.getProperty( "infill_mesh", "value") or per_mesh_stack.getProperty( "cutting_mesh", "value")): renderer.queueNode( node, shader=self._non_printing_shader, uniforms=uniforms, transparent=True) else: renderer.queueNode( node, shader=self._non_printing_shader, transparent=True) elif getattr(node, "_outside_buildarea", False): renderer.queueNode(node, shader=self._disabled_shader) elif per_mesh_stack and per_mesh_stack.getProperty( "support_mesh", "value"): # Render support meshes with a vertical stripe that is darker shade_factor = 0.6 uniforms["diffuse_color_2"] = [ uniforms["diffuse_color"][0] * shade_factor, uniforms["diffuse_color"][1] * shade_factor, uniforms["diffuse_color"][2] * shade_factor, 1.0 ] renderer.queueNode(node, shader=self._support_mesh_shader, uniforms=uniforms) else: renderer.queueNode(node, shader=self._enabled_shader, uniforms=uniforms) if node.callDecoration("isGroup") and Selection.isSelected( node): renderer.queueNode(scene.getRoot(), mesh=node.getBoundingBoxMesh(), mode=RenderBatch.RenderMode.LineLoop)