def resetRotation(self): """Reset the orientation of the mesh(es) to their original orientation(s)""" for node in self._getSelectedObjectsWithoutSelectedAncestors(): node.setMirror(Vector(1, 1, 1)) Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)
def resetRotation(self): for node in Selection.getAllSelectedObjects(): node.setMirror(Vector(1, 1, 1)) Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)
def resetRotation(self): for node in self._getSelectedObjectsWithoutSelectedAncestors(): node.setMirror(Vector(1, 1, 1)) Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)
def setX(self, x): obj = Selection.getSelectedObject(0) if obj: new_position = obj.getWorldPosition() new_position.setX(x) Selection.applyOperation(TranslateOperation, new_position, set_position=True) self.operationStopped.emit(self)
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.z), 4) != scale: scale_factor = abs(scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setScaleX(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.x), 4) != scale: scale_factor = abs(scale / obj_scale.x) if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setScaleX(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.x), 4) != scale: scale_factor = abs(scale / obj_scale.x) if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.z), 4) != scale: scale_factor = abs(scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setObjectWidth(self, width): obj = Selection.getSelectedObject(0) if obj: width = float(width) obj_width = obj.getBoundingBox().width if not Float.fuzzyCompare(obj_width, width, DIMENSION_TOLERANCE): scale_factor = width / obj_width if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setObjectHeight(self, height): obj = Selection.getSelectedObject(0) if obj: height = float(height) obj_height = obj.getBoundingBox().height if not Float.fuzzyCompare(obj_height, height, DIMENSION_TOLERANCE): scale_factor = height / obj_height if self._non_uniform_scale: scale_vector = Vector(1, scale_factor, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setObjectDepth(self, depth): obj = Selection.getSelectedObject(0) if obj: depth = float(depth) obj_depth = obj.getBoundingBox().depth if not Float.fuzzyCompare(obj_depth, depth, DIMENSION_TOLERANCE): scale_factor = depth / obj_depth if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setY(self, y): obj = Selection.getSelectedObject(0) if obj: new_position = obj.getWorldPosition() # Note; The switching of z & y is intentional. We display z as up for the user, # But store the data in openGL space. new_position.setZ(y) Selection.applyOperation(TranslateOperation, new_position, set_position=True) self.operationStopped.emit(self)
def setObjectHeight(self, height): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) obj_height = obj.getBoundingBox().height / obj_scale.y target_scale = float(height) / obj_height if obj_scale.y != target_scale: scale_factor = abs(target_scale / obj_scale.y) if self._non_uniform_scale: scale_vector = Vector(1, scale_factor, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setObjectDepth(self, depth): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) obj_depth = obj.getBoundingBox().depth / obj_scale.z target_scale = float(depth) / obj_depth if obj_scale.z != target_scale: scale_factor = abs(target_scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def resetRotation(self): for node in Selection.getAllSelectedObjects(): node.setMirror(Vector(1, 1, 1)) node._rotationX = 0.0 node._rotationY = 0.0 node._rotationZ = 0.0 Selection.applyOperation(SetTransformOperation, None, Quaternion(), None) self._X_angle = 0 self._Z_angle = 0 self._Y_angle = 0 self.propertyChanged.emit()
def setZ(self, z): obj = Selection.getSelectedObject(0) if obj: new_position = obj.getWorldPosition() selected_node = Selection.getSelectedObject(0) center = selected_node.getBoundingBox().center bottom = selected_node.getBoundingBox().bottom # Note; The switching of z & y is intentional. We display z as up for the user, # But store the data in openGL space. new_position.setY(float(z) + (center.y - bottom)) Selection.applyOperation(TranslateOperation, new_position, set_position=True) self.operationStopped.emit(self)
def layFlat(self): """Initialise and start a LayFlatOperation Note: The LayFlat functionality is mostly used for 3d printing and should probably be moved into the Cura project """ self.operationStarted.emit(self) self._progress_message = Message( i18n_catalog.i18nc("@label", "Laying object flat on buildplate..."), lifetime=0, dismissable=False, title=i18n_catalog.i18nc("@title", "Object Rotation")) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in self._getSelectedObjectsWithoutSelectedAncestors( ): self._layObjectFlat(selected_object) self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def setObjectWidth(self, width): obj = Selection.getSelectedObject(0) if obj: width = float(width) obj_width = obj.getBoundingBox().width if not Float.fuzzyCompare(obj_width, width, DIMENSION_TOLERANCE): scale_factor = width / obj_width if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation( ScaleOperation, scale_vector, scale_around_point=obj.getWorldPosition())
def layFlat(self): self.operationStarted.emit(self) self._progress_message = Message("Laying object flat on buildplate...", lifetime=0, dismissable=False) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in Selection.getAllSelectedObjects(): if selected_object.callDecoration( "isGroup"): # 2.1 hack. TODO: fix this properly self.operationStopped.emit(self) Logger.log("w", "Layflat is not supported for grouped objects") return self._total_iterations += len( selected_object.getMeshDataTransformed().getVertices()) * 2 self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def layFlat(self): self.operationStarted.emit(self) self._progress_message = Message("Laying object flat on buildplate...", lifetime=0, dismissable=False) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in Selection.getAllSelectedObjects(): if not selected_object.callDecoration("isGroup"): self._total_iterations += len( selected_object.getMeshDataTransformed().getVertices()) * 2 else: for child in selected_object.getChildren(): self._total_iterations += len( child.getMeshDataTransformed().getVertices()) * 2 self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def groupSelected(self): # Create a group-node group_node = SceneNode() group_decorator = GroupDecorator() group_node.addDecorator(group_decorator) group_node.setParent(self.getController().getScene().getRoot()) group_node.setSelectable(True) center = Selection.getSelectionCenter() group_node.setPosition(center) group_node.setCenterPosition(center) # Move selected nodes into the group-node Selection.applyOperation(SetParentOperation, group_node) # Deselect individual nodes and select the group-node instead for node in group_node.getChildren(): Selection.remove(node) Selection.add(group_node)
def test_applyOperation(self): # If there is no selection, nothing should happen assert Selection.applyOperation(TranslateOperation) is None node_1 = SceneNode() Selection.add(node_1) Selection.applyOperation(TranslateOperation, Vector(10, 20, 30)) assert node_1.getPosition() == Vector(10, 20, 30) node_2 = SceneNode() Selection.add(node_2) assert len(Selection.applyOperation(TranslateOperation, Vector(10, 20, 30))) == 2 # Node 1 got moved twice assert node_1.getPosition() == Vector(20, 40, 60) # And node 2 only once assert node_2.getPosition() == Vector(10, 20, 30)
def layFlat(self): self.operationStarted.emit(self) self._progress_message = Message(i18n_catalog.i18nc("@label", "Laying object flat on buildplate..."), lifetime = 0, dismissable = False, title = i18n_catalog.i18nc("@title", "Object Rotation")) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in self._getSelectedObjectsWithoutSelectedAncestors(): self._layObjectFlat(selected_object) self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def layFlat(self): self.operationStarted.emit(self) self._progress_message = Message("Laying object flat on buildplate...", lifetime = 0, dismissable = False) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in Selection.getAllSelectedObjects(): self._total_iterations += len(selected_object.getMeshDataTransformed().getVertices()) * 2 self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def layFlat(self): self.operationStarted.emit(self) self._progress_message = Message("Laying object flat on buildplate...", lifetime=0, dismissable=False) self._progress_message.setProgress(0) self._iterations = 0 self._total_iterations = 0 for selected_object in Selection.getAllSelectedObjects(): self._layObjectFlat(selected_object) self._progress_message.show() operations = Selection.applyOperation(LayFlatOperation) for op in operations: op.progress.connect(self._layFlatProgress) job = LayFlatJob(operations) job.finished.connect(self._layFlatFinished) job.start()
def resetRotation(self): Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)
def scaleToMax(self): if hasattr(self.getController().getScene(), "_maximum_bounds"): Selection.applyOperation( ScaleToBoundsOperation, self.getController().getScene()._maximum_bounds)
def resetScale(self): Selection.applyOperation(SetTransformOperation, None, None, Vector(1.0, 1.0, 1.0), Vector(0, 0, 0))
def event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._renderer.getIdAtCoordinate(event.x, event.y) if not id: return if ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(1, 0, 0), handle_position.x)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) elif self._locked_axis == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) self.setDragStart(event.x, event.y) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False handle_position = self._handle.getWorldPosition() drag_start = (self.getDragStart() - handle_position).normalize() drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return drag_end = (drag_position - handle_position).normalize() angle = math.acos(drag_start.dot(drag_end)) if self._snap_rotation: angle = int(angle / self._snap_angle) * self._snap_angle if angle == 0: return rotation = None if self.getLockedAxis() == ToolHandle.XAxis: direction = 1 if Vector.Unit_X.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_X) elif self.getLockedAxis() == ToolHandle.YAxis: direction = 1 if Vector.Unit_Y.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Y) elif self.getLockedAxis() == ToolHandle.ZAxis: direction = 1 if Vector.Unit_Z.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Z) Selection.applyOperation(RotateOperation, rotation) self.setDragStart(event.x, event.y) self.updateHandlePosition() if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) return True
def scaleToMax(self): if self._maximum_bounds: Selection.applyOperation(ScaleToBoundsOperation, self._maximum_bounds)
def resetScale(self): Selection.applyOperation(SetTransformOperation, None, None, Vector(1.0, 1.0, 1.0))
def scaleToMax(self): if hasattr(self.getController().getScene(), "_maximum_bounds"): Selection.applyOperation(ScaleToBoundsOperation, self.getController().getScene()._maximum_bounds)
def event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return if ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(1, 0, 0), handle_position.x)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) elif self._locked_axis == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) self.setDragStart(event.x, event.y) self._angle = 0 self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False if not self.getDragStart(): self.setDragStart(event.x, event.y) handle_position = self._handle.getWorldPosition() drag_start = (self.getDragStart() - handle_position).normalize() drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return drag_end = (drag_position - handle_position).normalize() try: angle = math.acos(drag_start.dot(drag_end)) except ValueError: angle = 0 if self._snap_rotation: angle = int(angle / self._snap_angle) * self._snap_angle if angle == 0: return rotation = None if self.getLockedAxis() == ToolHandle.XAxis: direction = 1 if Vector.Unit_X.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_X) elif self.getLockedAxis() == ToolHandle.YAxis: direction = 1 if Vector.Unit_Y.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Y) elif self.getLockedAxis() == ToolHandle.ZAxis: direction = 1 if Vector.Unit_Z.dot(drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Z) self._angle += direction * angle # Rate-limit the angle change notification # This is done to prevent the UI from being flooded with property change notifications, # which in turn would trigger constant repaints. new_time = time.monotonic() if not self._angle_update_time or new_time - self._angle_update_time > 0.01: self.propertyChanged.emit() self._angle_update_time = new_time Selection.applyOperation(RotateOperation, rotation) self.setDragStart(event.x, event.y) if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) self._angle = None self.propertyChanged.emit() self.operationStopped.emit(self) return True
def event(self, event): super().event(event) if event.type == Event.ToolActivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.connect(self.propertyChanged) if event.type == Event.ToolDeactivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.disconnect(self.propertyChanged) if event.type == Event.KeyPressEvent: if event.key == KeyEvent.ShiftKey: self._lock_steps = False self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = True self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent: if event.key == KeyEvent.ShiftKey: self._lock_steps = True self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = False self.propertyChanged.emit() if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._renderer.getIdAtCoordinate(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) else: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) self.setDragStart(event.x, event.y) self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False handle_position = self._handle.getWorldPosition() drag_position = self.getDragPosition(event.x, event.y) if drag_position: drag_length = (drag_position - handle_position).length() if self._drag_length > 0: drag_change = (drag_length - self._drag_length) / 100 if self._snap_scale and abs(drag_change) < self._snap_amount: return False scale = Vector(1.0, 1.0, 1.0) if self._non_uniform_scale: if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(1.0 + drag_change) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(1.0 + drag_change) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(1.0 + drag_change) if scale == Vector(1.0, 1.0, 1.0): scale.setX(1.0 + drag_change) scale.setY(1.0 + drag_change) scale.setZ(1.0 + drag_change) Selection.applyOperation(ScaleOperation, scale) self._drag_length = (handle_position - drag_position).length() return True if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) self._drag_length = 0 self.operationStopped.emit(self) return True
def event(self, event): super().event(event) # Make sure the displayed values are updated if the boundingbox of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.connect(self.propertyChanged) if event.type == Event.ToolDeactivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.disconnect(self.propertyChanged) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: # Snap-to-grid is turned on when pressing the shift button self._grid_snap = True if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: # Snap-to-grid is turned off when releasing the shift button self._grid_snap = False if event.type == Event.MousePressEvent and self._controller.getToolsEnabled( ): # Start a translate operation if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if id in self._enabled_axis: self.setLockedAxis(id) elif self._handle.isAxis(id): return False self._moved = False if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) else: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) if event.type == Event.MouseMoveEvent: # Perform a translate operation if not self.getDragPlane(): return False if not self.getDragStart(): self.setDragStart(event.x, event.y) return False drag = self.getDragVector(event.x, event.y) if drag: if self._grid_snap and drag.length() < self._grid_size: return False if self.getLockedAxis() == ToolHandle.XAxis: drag.setY(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.YAxis: drag.setX(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.ZAxis: drag.setX(0) drag.setY(0) if not self._moved: self._moved = True self._distance = Vector(0, 0, 0) self.operationStarted.emit(self) Selection.applyOperation(TranslateOperation, drag) self._distance += drag self.setDragStart(event.x, event.y) # Rate-limit the angle change notification # This is done to prevent the UI from being flooded with property change notifications, # which in turn would trigger constant repaints. new_time = time.monotonic() if not self._distance_update_time or new_time - self._distance_update_time > 0.1: self.propertyChanged.emit() self._distance_update_time = new_time return True if event.type == Event.MouseReleaseEvent: # Finish a translate operation if self.getDragPlane(): self.operationStopped.emit(self) self._distance = None self.propertyChanged.emit() # Force scene changed event. Some plugins choose to ignore move events when operation is in progress. if self._moved: for node in Selection.getAllSelectedObjects(): Application.getInstance().getController().getScene( ).sceneChanged.emit(node) self._moved = False self.setLockedAxis(None) self.setDragPlane(None) self.setDragStart(None, None) return True return False
def event(self, event): super().event(event) if event.type == Event.ToolActivateEvent: self._old_scale = Selection.getSelectedObject(0).getScale() for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.connect(self.propertyChanged) if event.type == Event.ToolDeactivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.disconnect(self.propertyChanged) if event.type == Event.KeyPressEvent: if event.key == KeyEvent.ShiftKey: self._snap_scale = False self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = True self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent: if event.key == KeyEvent.ShiftKey: self._snap_scale = True self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = False self.propertyChanged.emit() if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) self._saved_handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), self._saved_handle_position.z)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), self._saved_handle_position.z)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), self._saved_handle_position.y)) else: self.setDragPlane(Plane(Vector(0, 1, 0), self._saved_handle_position.y)) self.setDragStart(event.x, event.y) self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False #handle_position = self._handle.getWorldPosition() drag_position = self.getDragPosition(event.x, event.y) if drag_position: drag_length = (drag_position - self._saved_handle_position).length() if self._drag_length > 0: drag_change = (drag_length - self._drag_length) / 100 * self._scale_speed scale_factor = drag_change scale_change = Vector(0.0, 0.0, 0.0) if self._non_uniform_scale: if self.getLockedAxis() == ToolHandle.XAxis: scale_change.setX(scale_factor) elif self.getLockedAxis() == ToolHandle.YAxis: scale_change.setY(scale_factor) elif self.getLockedAxis() == ToolHandle.ZAxis: scale_change.setZ(scale_factor) else: scale_change.setX(scale_factor) scale_change.setY(scale_factor) scale_change.setZ(scale_factor) Selection.applyOperation(ScaleOperation, scale_change, relative_scale = True, snap = self._snap_scale) self._drag_length = (self._saved_handle_position - drag_position).length() return True if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) self._drag_length = 0 self.operationStopped.emit(self) return True
def event(self, event): super().event(event) if event.type == Event.ToolActivateEvent: self._old_scale = Selection.getSelectedObject(0).getScale() for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.connect(self.propertyChanged) if event.type == Event.ToolDeactivateEvent: for node in Selection.getAllSelectedObjects(): node.boundingBoxChanged.disconnect(self.propertyChanged) if event.type == Event.KeyPressEvent: if event.key == KeyEvent.ShiftKey: self._snap_scale = False self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = True self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent: if event.key == KeyEvent.ShiftKey: self._snap_scale = True self.propertyChanged.emit() elif event.key == KeyEvent.ControlKey: self._non_uniform_scale = False self.propertyChanged.emit() if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) else: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) self.setDragStart(event.x, event.y) self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False handle_position = self._handle.getWorldPosition() drag_position = self.getDragPosition(event.x, event.y) if drag_position: drag_length = (drag_position - handle_position).length() if self._drag_length > 0: drag_change = (drag_length - self._drag_length) / 100 * self._scale_speed if self._snap_scale: scaleFactor = round(drag_change, 1) else: scaleFactor = drag_change scale = Vector(0.0, 0.0, 0.0) if self._non_uniform_scale: if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(scaleFactor) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(scaleFactor) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(scaleFactor) else: scale.setX(scaleFactor) scale.setY(scaleFactor) scale.setZ(scaleFactor) Selection.applyOperation(ScaleOperation, scale, add_scale=True) #this part prevents the mesh being scaled to a size < 0. #This cannot be done before the operation (even though that would be more efficient) #because then the operation can distract more of the mesh then is remaining of its size realWorldMeshScale = Selection.getSelectedObject(0).getScale() if realWorldMeshScale.x <= 0 or realWorldMeshScale.y <= 0 or realWorldMeshScale.z <= 0: minimumScale = 0.01 #1% so the mesh never completely disapears for the user if self._snap_scale == True: minimumScale = 0.1 #10% same reason as above if realWorldMeshScale.x <= 0: realWorldMeshScale.setX(minimumScale) if realWorldMeshScale.y <= 0: realWorldMeshScale.setY(minimumScale) if realWorldMeshScale.z <= 0: realWorldMeshScale.setZ(minimumScale) Selection.applyOperation(SetTransformOperation, None, None, realWorldMeshScale) self._drag_length = (handle_position - drag_position).length() return True if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) self._drag_length = 0 self.operationStopped.emit(self) return True
def event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: self._grid_snap = True if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: self._grid_snap = False if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._renderer.getIdAtCoordinate(event.x, event.y) if not id: return False if id in self._enabled_axis: self.setLockedAxis(id) elif self._handle.isAxis(id): return False self.operationStarted.emit(self) if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) else: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False if not self.getDragStart(): self.setDragStart(event.x, event.y) return False drag = self.getDragVector(event.x, event.y) if drag: if self._grid_snap and drag.length() < self._grid_size: return False if self.getLockedAxis() == ToolHandle.XAxis: drag.setY(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.YAxis: drag.setX(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.ZAxis: drag.setX(0) drag.setY(0) Selection.applyOperation(TranslateOperation, drag) self.setDragStart(event.x, event.y) return True if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setLockedAxis(None) self.setDragPlane(None) self.setDragStart(None, None) self.operationStopped.emit(self) return True return False
def event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: self._grid_snap = True if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: self._grid_snap = False if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if id in self._enabled_axis: self.setLockedAxis(id) elif self._handle.isAxis(id): return False self._moved = False if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 0, 1), 0)) elif id == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) else: self.setDragPlane(Plane(Vector(0, 1, 0), 0)) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False if not self.getDragStart(): self.setDragStart(event.x, event.y) return False drag = self.getDragVector(event.x, event.y) if drag: if self._grid_snap and drag.length() < self._grid_size: return False if self.getLockedAxis() == ToolHandle.XAxis: drag.setY(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.YAxis: drag.setX(0) drag.setZ(0) elif self.getLockedAxis() == ToolHandle.ZAxis: drag.setX(0) drag.setY(0) if not self._moved: self._moved = True self.operationStarted.emit(self) Selection.applyOperation(TranslateOperation, drag) self.setDragStart(event.x, event.y) return True if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.operationStopped.emit(self) self.setLockedAxis(None) self.setDragPlane(None) self.setDragStart(None, None) return True return False
def event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return if ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() if id == ToolHandle.XAxis: self.setDragPlane(Plane(Vector(1, 0, 0), handle_position.x)) elif id == ToolHandle.YAxis: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) elif self._locked_axis == ToolHandle.ZAxis: self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z)) self.setDragStart(event.x, event.y) self._angle = 0 self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: if not self.getDragPlane(): return False if not self.getDragStart(): self.setDragStart(event.x, event.y) handle_position = self._handle.getWorldPosition() drag_start = (self.getDragStart() - handle_position).normalize() drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return drag_end = (drag_position - handle_position).normalize() try: angle = math.acos(drag_start.dot(drag_end)) except ValueError: angle = 0 if self._snap_rotation: angle = int(angle / self._snap_angle) * self._snap_angle if angle == 0: return rotation = None if self.getLockedAxis() == ToolHandle.XAxis: direction = 1 if Vector.Unit_X.dot( drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_X) elif self.getLockedAxis() == ToolHandle.YAxis: direction = 1 if Vector.Unit_Y.dot( drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Y) elif self.getLockedAxis() == ToolHandle.ZAxis: direction = 1 if Vector.Unit_Z.dot( drag_start.cross(drag_end)) > 0 else -1 rotation = Quaternion.fromAngleAxis(direction * angle, Vector.Unit_Z) self._angle += direction * angle # Rate-limit the angle change notification # This is done to prevent the UI from being flooded with property change notifications, # which in turn would trigger constant repaints. new_time = time.monotonic() if not self._angle_update_time or new_time - self._angle_update_time > 0.01: self.propertyChanged.emit() self._angle_update_time = new_time Selection.applyOperation(RotateOperation, rotation) self.setDragStart(event.x, event.y) if event.type == Event.MouseReleaseEvent: if self.getDragPlane(): self.setDragPlane(None) self.setLockedAxis(None) self._angle = None self.propertyChanged.emit() self.operationStopped.emit(self) return True
def resetScale(self): """Reset scale of the selected objects""" Selection.applyOperation(SetTransformOperation, None, None, Vector(1.0, 1.0, 1.0), Vector(0, 0, 0))