def event(self, event): super().event(event) if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Initialise a mirror 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 ToolHandle.isAxis(id): self.setLockedAxis(id) self._operation_started = True self.operationStarted.emit(self) return True if event.type == Event.MouseReleaseEvent: if self._operation_started: self._operation_started = False self.operationStopped.emit(self) # Perform a mirror operation if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op = MirrorOperation(node, mirror, mirror_around_center = True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op.addOperation(MirrorOperation(node, mirror, mirror_around_center = True)) op.push() self.setLockedAxis(None) return True return False
def event(self, event): super().event(event) if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Initialise a mirror 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 ToolHandle.isAxis(id): self.setLockedAxis(id) return True if event.type == Event.MouseReleaseEvent: # Perform a mirror operation if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op = MirrorOperation(node, mirror, mirror_around_center = True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op.addOperation(MirrorOperation(node, mirror, mirror_around_center = True)) op.push() self.setLockedAxis(None) return True return False
def event(self, event): super().event(event) 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) return True if event.type == Event.MouseReleaseEvent: if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op = ScaleOperation(node, scale, set_scale=True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op.addOperation( ScaleOperation(node, scale, set_scale=True)) op.push() self.setLockedAxis(None) return True return False
def event(self, event): super().event(event) 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) return True if event.type == Event.MouseReleaseEvent: if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) mirror = node.getMirror() if self.getLockedAxis() == ToolHandle.XAxis: mirror.setX(-mirror.x) elif self.getLockedAxis() == ToolHandle.YAxis: mirror.setY(-mirror.y) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror.setZ(-mirror.z) op = MirrorOperation(node, mirror, set_mirror=True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): mirror = node.getMirror() if self.getLockedAxis() == ToolHandle.XAxis: mirror.setX(-mirror.x) elif self.getLockedAxis() == ToolHandle.YAxis: mirror.setY(-mirror.y) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror.setZ(-mirror.z) op.addOperation(MirrorOperation(node, mirror, set_mirror = True)) op.push() self.setLockedAxis(None) return True return False
def event(self, event): super().event(event) 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) return True if event.type == Event.MouseReleaseEvent: if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op = ScaleOperation(node, scale, set_scale=True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op.addOperation(ScaleOperation(node, scale, set_scale = True)) op.push() self.setLockedAxis(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 event(self, event): super().event(event) if event.type == Event.KeyPressEvent and event.key == KeyEvent.ShiftKey: # Snap is toggled when pressing the shift button self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: # Snap is "toggled back" when releasing the shift button self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Start a rotate operation 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() # Save the current positions of the node, as we want to rotate around their current centres self._saved_node_positions = [] for node in Selection.getAllSelectedObjects(): self._saved_node_positions.append((node, node.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: # Perform a rotate operation 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).normalized() drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return drag_end = (drag_position - handle_position).normalized() 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) # 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.1: self._angle_update_time = new_time self._angle += direction * angle self.propertyChanged.emit() # Rotate around the saved centeres of all selected nodes op = GroupedOperation() for node, position in self._saved_node_positions: op.addOperation(RotateOperation(node, rotation, rotate_around_point = position)) op.push() self.setDragStart(event.x, event.y) if event.type == Event.MouseReleaseEvent: # Finish a rotate operation 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: 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) # Handle modifier keys: Shift toggles snap, Control toggles uniform scaling 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( ): # Initialise a scale 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 ToolHandle.isAxis(id): self.setLockedAxis(id) # Save the current positions of the node, as we want to scale arround their current centres self._saved_node_positions = [] for node in Selection.getAllSelectedObjects(): self._saved_node_positions.append((node, node.getPosition())) self._saved_handle_position = self._handle.getWorldPosition() self._scale_sum = 0.0 self._last_event = event 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: # Perform a scale operation if not self.getDragPlane(): return False 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 if self.getLockedAxis() in [ ToolHandle.XAxis, ToolHandle.YAxis, ToolHandle.ZAxis ]: # drag the handle, axis is already determined if self._snap_scale: scale_factor = round(drag_change, 1) else: scale_factor = drag_change else: # uniform scaling; because we use central cube, we use the screen x, y for scaling. # upper right is scale up, lower left is scale down scale_factor_delta = ( (self._last_event.y - event.y) - (self._last_event.x - event.x)) * self._scale_speed self._scale_sum += scale_factor_delta if self._snap_scale: scale_factor = round(self._scale_sum, 1) # remember the decimals when snap scaling self._scale_sum -= scale_factor else: scale_factor = self._scale_sum self._scale_sum = 0.0 if scale_factor: scale_change = Vector(0.0, 0.0, 0.0) if self._non_uniform_scale: if self.getLockedAxis() == ToolHandle.XAxis: scale_change = scale_change.set(x=scale_factor) elif self.getLockedAxis() == ToolHandle.YAxis: scale_change = scale_change.set(y=scale_factor) elif self.getLockedAxis() == ToolHandle.ZAxis: scale_change = scale_change.set(z=scale_factor) else: # Middle handle scale_change = scale_change.set(x=scale_factor, y=scale_factor, z=scale_factor) else: scale_change = scale_change.set(x=scale_factor, y=scale_factor, z=scale_factor) # Scale around the saved centers of all selected nodes op = GroupedOperation() for node, position in self._saved_node_positions: op.addOperation( ScaleOperation(node, scale_change, relative_scale=True, scale_around_point=position)) op.push() self._drag_length = (self._saved_handle_position - drag_position).length() else: self._drag_length = ( self._saved_handle_position - drag_position ).length() #First move, do nothing but set right length. self._last_event = event # remember for uniform drag return True if event.type == Event.MouseReleaseEvent: # Finish a scale operation 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) # Handle modifier keys: Shift toggles snap, Control toggles uniform scaling 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(): # Initialise a scale 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 ToolHandle.isAxis(id): self.setLockedAxis(id) # Save the current positions of the node, as we want to scale arround their current centres self._saved_node_positions = [] for node in Selection.getAllSelectedObjects(): self._saved_node_positions.append((node, node.getWorldPosition())) 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: # Perform a scale operation if not self.getDragPlane(): return False 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 if self._snap_scale: scale_factor = round(drag_change, 1) else: scale_factor = drag_change if scale_factor: scale_change = Vector(0.0, 0.0, 0.0) if self._non_uniform_scale: if self.getLockedAxis() == ToolHandle.XAxis: scale_change = scale_change.set(x=scale_factor) elif self.getLockedAxis() == ToolHandle.YAxis: scale_change = scale_change.set(y=scale_factor) elif self.getLockedAxis() == ToolHandle.ZAxis: scale_change = scale_change.set(z=scale_factor) else: scale_change = Vector(x=scale_factor, y=scale_factor, z=scale_factor) # Scale around the saved centeres of all selected nodes op = GroupedOperation() for node, position in self._saved_node_positions: op.addOperation(ScaleOperation(node, scale_change, relative_scale = True, scale_around_point = position)) op.push() self._drag_length = (self._saved_handle_position - drag_position).length() else: self._drag_length = (self._saved_handle_position - drag_position).length() #First move, do nothing but set right length. return True if event.type == Event.MouseReleaseEvent: # Finish a scale operation 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: # Snap is toggled when pressing the shift button self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey: # Snap is "toggled back" when releasing the shift button self._snap_rotation = (not self._snap_rotation) self.propertyChanged.emit() if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Start a rotate 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 ToolHandle.isAxis(id): self.setLockedAxis(id) handle_position = self._handle.getWorldPosition() # Save the current positions of the node, as we want to rotate around their current centres self._saved_node_positions = [] for node in Selection.getAllSelectedObjects(): self._saved_node_positions.append((node, node.getPosition())) 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)) else: self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y)) self.setDragStart(event.x, event.y) self._angle = 0 self.operationStarted.emit(self) if event.type == Event.MouseMoveEvent: # Perform a rotate operation 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).normalized() drag_position = self.getDragPosition(event.x, event.y) if not drag_position: return drag_end = (drag_position - handle_position).normalized() 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) # 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.1: self._angle_update_time = new_time self._angle += direction * angle self.propertyChanged.emit() # Rotate around the saved centeres of all selected nodes op = GroupedOperation() for node, position in self._saved_node_positions: op.addOperation(RotateOperation(node, rotation, rotate_around_point = position)) op.push() self.setDragStart(event.x, event.y) if event.type == Event.MouseReleaseEvent: # Finish a rotate operation 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) 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: 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) # Handle modifier keys: Shift toggles snap, Control toggles uniform scaling 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(): # Initialise a scale 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 ToolHandle.isAxis(id): self.setLockedAxis(id) # Save the current positions of the node, as we want to scale arround their current centres self._saved_node_positions = [] for node in Selection.getAllSelectedObjects(): self._saved_node_positions.append((node, node.getWorldPosition())) 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: # Perform a scale operation if not self.getDragPlane(): return False 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 if self._snap_scale: scale_factor = round(drag_change, 1) else: scale_factor = drag_change if scale_factor: 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) # Scale around the saved centeres of all selected nodes op = GroupedOperation() for node, position in self._saved_node_positions: op.addOperation(ScaleOperation(node, scale_change, relative_scale = True, scale_around_point = position)) op.push() self._drag_length = (self._saved_handle_position - drag_position).length() else: self._drag_length = (self._saved_handle_position - drag_position).length() #First move, do nothing but set right length. return True if event.type == Event.MouseReleaseEvent: # Finish a scale operation 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.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.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