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 test_faceSelectMode(self): Selection.selectedFaceChanged = MagicMock() Selection.setFaceSelectMode(True) assert Selection.getFaceSelectMode() Selection.setFaceSelectMode(True) Selection.setFaceSelectMode(False) assert not Selection.getFaceSelectMode() assert Selection.selectedFaceChanged.emit.call_count == 2
def _changeRenderMode(self, faces=True): if Selection.hasSelection() and Selection.getFaceSelectMode() != faces: self._select = False Selection.setFaceSelectMode(faces) if self._selection_pass: self._selection_pass.render() self._select = True
def setSelectFaceToLayFlatMode(self, select: bool) -> None: if select != self._select_face_mode or select != Selection.getFaceSelectMode( ): self._select_face_mode = select if not select: Selection.clearFace() Selection.setFaceSelectMode(self._select_face_mode) self.propertyChanged.emit()
def setSelectFaceToLayFlatMode(self, select: bool) -> None: """Set the rotate tool to/from 'Lay flat by face'-Mode.""" if select != self._select_face_mode or select != Selection.getFaceSelectMode(): self._select_face_mode = select if not select: Selection.clearFace() Selection.setFaceSelectMode(self._select_face_mode) self.propertyChanged.emit()
def _pixelHover(self, event): if Selection.getFaceSelectMode(): face_id = self._selection_pass.getFaceIdAtPosition(event.x, event.y) if face_id >= 0: Selection.hoverFace(Selection.getSelectedObject(0), face_id) else: Selection.clearFace() return True return False
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 add(self): Selection.clearFace() if not Selection.getFaceSelectMode(): Selection.setFaceSelectMode(True) if len(self._bcs) == 0: N = 1 else: N = int(self._bcs[-1].getName().split(" ")[1]) + 1 if self._bc_type == BoundaryConditionListModel.Anchor: bc = SmartSliceScene.AnchorFace('Anchor ' + str(N)) bc.surface_type = SmartSliceScene.HighlightFace.SurfaceType.Flat else: bc = SmartSliceScene.LoadFace('Load ' + str(N)) bc.force.magnitude = 10.0 bc.force.direction_type = SmartSliceScene.Force.DirectionType.Normal bc.surface_type = SmartSliceScene.HighlightFace.SurfaceType.Flat self._smart_slice_scene_node.addFace(bc)
def faceSelectMode(self): return Selection.getFaceSelectMode()
def _onSelectedFaceChanged(self): self._mode = SelectionPass.SelectionMode.FACES if Selection.getFaceSelectMode( ) else SelectionPass.SelectionMode.OBJECTS
def getSelectFaceToLayFlatMode(self) -> bool: if not Selection.getFaceSelectMode(): self._select_face_mode = False # .. but not the other way around! return self._select_face_mode
def event(self, event: Event) -> bool: if not self._selection_pass: self._selection_pass = cast( SelectionPass, Application.getInstance().getRenderer().getRenderPass( "selection")) if not self._selection_pass: return False # Tool activated - make sure we render the faces if event.type == Event.ToolActivateEvent: self._changeRenderMode(faces=True) self._enabled = True if self._bc_list and self._bc_list.getActiveNode(): self._controller.getScene().sceneChanged.emit( self._bc_list.getActiveNode()) return False # Tool deactivated - make sure we render the faces if event.type == Event.ToolDeactivateEvent: self._changeRenderMode(faces=False) self._enabled = False if self._bc_list and self._bc_list.getActiveNode(): self._controller.getScene().sceneChanged.emit( self._bc_list.getActiveNode()) self._bc_list = None return False if not self.getEnabled(): return False # Not a load face - make sure we render faces if not self._bc_list or not self._bc_list.getActiveNode( ) or isinstance(self._bc_list.getActiveNode(), SmartSliceScene.AnchorFace): self._changeRenderMode(faces=True) return False active_node = self._bc_list.getActiveNode() # Load face rotator = active_node.getRotator() # Rotator on the load face arrow = active_node.activeArrow # Active arrow on the load face if event.type == Event.MousePressEvent: # Must be a left mouse event to select or rotate if MouseEvent.LeftButton not in event.buttons: return False pixel_color = self._selection_pass.getIdAtPosition( event.x, event.y) # We did not click the tool - we need to select the surface under it if it exists # TODO - This is a little hacky.... we should implement a SelectionPass just for this Tool if not pixel_color or not arrow.isAxis(pixel_color): if Selection.hasSelection( ) and not Selection.getFaceSelectMode(): self._changeRenderMode(faces=True) select_tool = PluginRegistry.getInstance().getPluginObject( "SelectionTool") return select_tool.event(event) # Rotator isn't enabled - we don't need to do anything if not rotator.isEnabled(): return False # If we made it here, we have clicked the tool. Set the locked color to our tool color, and set the plane # the user will be constrained to drag in self.setLockedAxis(pixel_color) self.setDragPlane(Plane(rotator.rotation_axis)) self.setDragStart(event.x, event.y) self._rotating = True self._angle = 0 return True if event.type == Event.MouseMoveEvent: # Rotator isn't enabled - we don't need to do anything if not rotator.isEnabled(): return False event = cast(MouseEvent, event) # Turn the shader on for the rotator and arrow if the mouse is hovered on them # in the above, pixel_color is the color of the solid mesh of the pixekl the mouse is on # For some reason, "ActiveAxis" means the color of the tool we are interested in if not self._rotating: self._changeRenderMode(faces=False) pixel_color = self._selection_pass.getIdAtPosition( event.x, event.y) if rotator.isAxis(pixel_color): rotator.setActiveAxis(pixel_color) arrow.setActiveAxis(pixel_color) else: rotator.setActiveAxis(None) arrow.setActiveAxis(None) return False # We are rotating. Check to ensure we have a starting position for the mouse if not self.getDragStart(): self.setDragStart(event.x, event.y) if not self.getDragStart(): #May have set it to None. return False self.operationStarted.emit(self) drag_start = self.getDragStart() - rotator.center drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return False drag_end = drag_position - rotator.center # Project the vectors back to the plane of the rotator drag_start = drag_start - drag_start.dot( rotator.rotation_axis) * rotator.rotation_axis drag_end = drag_end - drag_end.dot( rotator.rotation_axis) * rotator.rotation_axis angle = angleBetweenVectors(drag_start, drag_end) axes_length = (rotator.rotation_axis.normalized() - drag_end.cross(drag_start).normalized()).length() angle = -angle if axes_length < 1.e-2 else angle rotation = Quaternion.fromAngleAxis(angle, rotator.rotation_axis) self._angle += angle active_node.rotateArrow(angle) self.setDragStart(event.x, event.y) return True # Finished the rotation - reset everything and update the arrow direction if event.type == Event.MouseReleaseEvent: if self._rotating: self.setDragPlane(None) self.setLockedAxis(ToolHandle.NoAxis) self._angle = None self._rotating = False self.propertyChanged.emit() active_node.facePropertyChanged.emit(active_node) # self._changeRenderMode(faces=True) self.operationStopped.emit(self) return True return False
def getSelectFaceToLayFlatMode(self) -> bool: """Whether the rotate tool is in 'Lay flat by face'-Mode.""" if not Selection.getFaceSelectMode(): self._select_face_mode = False # .. but not the other way around! return self._select_face_mode
def _pixelSelection(self, event): # Find a node id by looking at a pixel value at the requested location if self._selection_pass: if Selection.getFaceSelectMode(): item_id = id(Selection.getSelectedObject(0)) else: item_id = self._selection_pass.getIdAtPosition( event.x, event.y) else: Logger.log( "w", "Selection pass is None. getRenderPass('selection') returned None" ) return False if not item_id and not self._shift_is_active: if Selection.hasSelection(): Selection.clearFace() Selection.clear() return True return False # Nothing was selected before and the user didn't click on an object. # Find the scene-node which matches the node-id for node in BreadthFirstIterator(self._scene.getRoot()): if id(node) != item_id: continue if self._isNodeInGroup(node): is_selected = Selection.isSelected( self._findTopGroupNode(node)) else: is_selected = Selection.isSelected(node) if self._shift_is_active: if is_selected: # Deselect the SceneNode and its siblings in a group if node.getParent(): if self._ctrl_is_active or not self._isNodeInGroup( node): Selection.remove(node) else: Selection.remove(self._findTopGroupNode(node)) return True else: # Select the SceneNode and its siblings in a group if node.getParent(): if self._ctrl_is_active or not self._isNodeInGroup( node): Selection.add(node) else: Selection.add(self._findTopGroupNode(node)) return True else: if Selection.getFaceSelectMode(): face_id = self._selection_pass.getFaceIdAtPosition( event.x, event.y) if face_id >= 0: Selection.toggleFace(node, face_id) else: Selection.clear() Selection.clearFace() if not is_selected or Selection.getCount() > 1: # Select only the SceneNode and its siblings in a group Selection.clear() if node.getParent(): if self._ctrl_is_active or not self._isNodeInGroup( node): Selection.add(node) else: Selection.add(self._findTopGroupNode(node)) return True elif self._isNodeInGroup(node) and self._ctrl_is_active: Selection.clear() Selection.add(node) return True return False