Exemple #1
0
    def test_create(self):
        p = Plane()
        self.assertEqual(Vector(), p.normal)
        self.assertEqual(0.0, p.distance)

        p = Plane(Vector.Unit_Y, 1.0)
        self.assertEqual(Vector.Unit_Y, p.normal)
        self.assertEqual(1.0, p.distance)
Exemple #2
0
def test_getDragVector():
    test_tool_1 = createTool("test_tool_1")

    # No drag plane set
    assert test_tool_1.getDragVector(0, 0) is None
    test_tool_1.setDragPlane(Plane())
    # No drag start
    assert test_tool_1.getDragVector(0, 0) is None
Exemple #3
0
    def test_intersects(self):
        p = Plane(Vector.Unit_Y, 0.0)

        r = Ray(Vector(0, 10, 0), -Vector.Unit_Y)
        result = p.intersectsRay(r)
        self.assertNotEqual(False, result)
        self.assertEqual(10.0, result)

        r = Ray(Vector(0, -10, 0), Vector.Unit_Y)
        result = p.intersectsRay(r)
        self.assertNotEqual(False, result)
        self.assertEqual(10.0, result)

        r = Ray(Vector(0, 10, 0), Vector.Unit_Y)
        self.assertEqual(False, p.intersectsRay(r))

        r = Ray(Vector(0, 0, 0), Vector.Unit_X)
        self.assertEqual(False, p.intersectsRay(r))
Exemple #4
0
def test_getDragVector():
    test_tool_1 = Tool()
    test_tool_1.setPluginId("test_tool_1")

    # No drag plane set
    assert test_tool_1.getDragVector(0, 0) is None
    test_tool_1.setDragPlane(Plane())
    # No drag start
    assert test_tool_1.getDragVector(0, 0) is None
Exemple #5
0
    def test_intersects(self):
        p = Plane(Vector.Unit_Y, 0.0)

        r = Ray(Vector(0, 10, 0), -Vector.Unit_Y)
        result = p.intersectsRay(r)
        self.assertNotEqual(False, result)
        self.assertEqual(10.0, result)

        r = Ray(Vector(0, -10, 0), Vector.Unit_Y)
        result = p.intersectsRay(r)
        self.assertNotEqual(False, result)
        self.assertEqual(10.0, result)

        r = Ray(Vector(0, 10, 0), Vector.Unit_Y)
        self.assertEqual(False, p.intersectsRay(r))

        r = Ray(Vector(0, 0, 0), Vector.Unit_X)
        self.assertEqual(False, p.intersectsRay(r))
    def event(self, event: Event) -> bool:
        super().event(event)

        # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes
        if event.type == Event.ToolActivateEvent:
            for node in self._getSelectedObjectsWithoutSelectedAncestors():
                node.boundingBoxChanged.connect(self.propertyChanged)

        if event.type == Event.ToolDeactivateEvent:
            for node in self._getSelectedObjectsWithoutSelectedAncestors():
                node.boundingBoxChanged.disconnect(self.propertyChanged)

        if event.type == Event.KeyPressEvent and cast(
                KeyEvent, event).key == KeyEvent.ShiftKey:
            return False

        if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(
        ):
            # Start a translate operation
            if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons:
                return False

            if not self._selection_pass:
                return False
            id = self._selection_pass.getIdAtPosition(
                cast(MouseEvent, event).x,
                cast(MouseEvent, 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

            camera = self._controller.getScene().getActiveCamera()
            if not camera:
                return False
            camera_direction = camera.getPosition().normalized()

            abs_x = abs(camera_direction.x)
            abs_y = abs(camera_direction.y)

            # We have to define a plane vector that is suitable for the selected toolhandle axis
            # and at the same time the camera direction should not be exactly perpendicular to the plane vector
            if id == ToolHandle.XAxis:
                plane_vector = Vector(0, camera_direction.y,
                                      camera_direction.z).normalized()
            elif id == ToolHandle.YAxis:
                plane_vector = Vector(camera_direction.x, 0,
                                      camera_direction.z).normalized()
            elif id == ToolHandle.ZAxis:
                plane_vector = Vector(camera_direction.x, camera_direction.y,
                                      0).normalized()
            else:
                if abs_y > DIRECTION_TOLERANCE:
                    plane_vector = Vector(0, 1, 0)
                elif abs_x > DIRECTION_TOLERANCE:
                    plane_vector = Vector(1, 0, 0)
                    self.setLockedAxis(
                        ToolHandle.ZAxis)  # Do not move y / vertical
                else:
                    plane_vector = Vector(0, 0, 1)
                    self.setLockedAxis(
                        ToolHandle.XAxis)  # Do not move y / vertical

            self.setDragPlane(Plane(plane_vector, 0))
            return True

        if event.type == Event.MouseMoveEvent:
            # Perform a translate operation

            if not self.getDragPlane():
                return False

            x = cast(MouseEvent, event).x
            y = cast(MouseEvent, event).y

            if not self.getDragStart():
                self.setDragStart(x, y)
                return False

            drag = self.getDragVector(x, y)
            if drag:
                if self._grid_snap and drag.length() < self._grid_size:
                    return False

                if self.getLockedAxis() == ToolHandle.XAxis:
                    drag = drag.set(y=0, z=0)
                elif self.getLockedAxis() == ToolHandle.YAxis:
                    drag = drag.set(x=0, z=0)
                elif self.getLockedAxis() == ToolHandle.ZAxis:
                    drag = drag.set(x=0, y=0)

                if not self._moved:
                    self._moved = True
                    self._distance = Vector(0, 0, 0)
                    self.operationStarted.emit(self)

                selected_nodes = self._getSelectedObjectsWithoutSelectedAncestors(
                )
                if len(selected_nodes) > 1:
                    op = GroupedOperation()
                    for node in selected_nodes:
                        if node.getSetting(SceneNodeSettings.LockPosition,
                                           "False") == "False":
                            op.addOperation(TranslateOperation(node, drag))
                    op.push()
                else:
                    for node in selected_nodes:
                        if node.getSetting(SceneNodeSettings.LockPosition,
                                           "False") == "False":
                            TranslateOperation(node, drag).push()

                if not self._distance:
                    self._distance = Vector(0, 0, 0)
                self._distance += drag

            self.setDragStart(x, 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()
                self.setLockedAxis(ToolHandle.NoAxis)
                self.setDragPlane(None)
                self.setDragStart(
                    cast(MouseEvent, event).x,
                    cast(MouseEvent, event).y)
                return True

        return False
Exemple #7
0
    def event(self, event):
        super().event(event)

        # Make sure the displayed values are updated if the bounding box 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:
            return 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 = drag.set(y=0, z=0)
                elif self.getLockedAxis() == ToolHandle.YAxis:
                    drag = drag.set(x=0, z=0)
                elif self.getLockedAxis() == ToolHandle.ZAxis:
                    drag = drag.set(x=0, y=0)

                if not self._moved:
                    self._moved = True
                    self._distance = Vector(0, 0, 0)
                    self.operationStarted.emit(self)

                op = GroupedOperation()
                for node in Selection.getAllSelectedObjects():
                    op.addOperation(TranslateOperation(node, drag))
                op.push()

                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()
                self.setLockedAxis(None)
                self.setDragPlane(None)
                self.setDragStart(None, None)
                return True

        return False
Exemple #8
0
    def event(self, event):
        """Handle mouse and keyboard events

        :param event: type(Event)
        """

        super().event(event)

        if event.type == Event.ToolActivateEvent:
            for node in self._getSelectedObjectsWithoutSelectedAncestors():
                node.boundingBoxChanged.connect(self.propertyChanged)

        if event.type == Event.ToolDeactivateEvent:
            for node in self._getSelectedObjectsWithoutSelectedAncestors():
                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.setScaleSnap(not self._snap_scale)

            elif event.key == KeyEvent.ControlKey:
                self.setNonUniformScale(not self._non_uniform_scale)

        if event.type == Event.KeyReleaseEvent:
            if event.key == KeyEvent.ShiftKey:
                self.setScaleSnap(not self._snap_scale)

            elif event.key == KeyEvent.ControlKey:
                self.setNonUniformScale(not self._non_uniform_scale)

        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 self._handle.isAxis(id):
                self.setLockedAxis(id)
            self._saved_handle_position = self._handle.getWorldPosition()

            # Save the current positions of the node, as we want to scale arround their current centres
            self._saved_node_positions = []
            for node in self._getSelectedObjectsWithoutSelectedAncestors():
                self._saved_node_positions.append((node, node.getPosition()))

            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)
            return True

        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:
                if self.getLockedAxis() == ToolHandle.XAxis:
                    drag_position = drag_position.set(y=0, z=0)
                elif self.getLockedAxis() == ToolHandle.YAxis:
                    drag_position = drag_position.set(x=0, z=0)
                elif self.getLockedAxis() == ToolHandle.ZAxis:
                    drag_position = drag_position.set(x=0, y=0)

                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
                        if len(self._saved_node_positions) > 1:
                            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()
                        else:
                            for node, position in self._saved_node_positions:
                                ScaleOperation(
                                    node,
                                    scale_change,
                                    relative_scale=True,
                                    scale_around_point=position).push()
                        self._drag_length = (self._saved_handle_position -
                                             drag_position).length()
                else:
                    self.operationStarted.emit(self)
                    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(ToolHandle.NoAxis)
                self._drag_length = 0
                self.operationStopped.emit(self)
                return True
Exemple #9
0
    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.setRotationSnap(not self._snap_rotation)

        if event.type == Event.KeyReleaseEvent and event.key == KeyEvent.ShiftKey:
            # Snap is "toggled back" when releasing the shift button
            self.setRotationSnap(not self._snap_rotation)

        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 self._handle.isAxis(id):
                self.setLockedAxis(id)
            else:
                # Not clicked on an axis: do nothing.
                return False

            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 self._getSelectedObjectsWithoutSelectedAncestors():
                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._rotating = False
            self._angle = 0
            return True

        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)
                if not self.getDragStart():  #May have set it to None.
                    return False

            if not self._rotating:
                self._rotating = True
                self.operationStarted.emit(self)

            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 False
            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 False

            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)
            else:
                direction = -1

            # 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
                if len(self._saved_node_positions) > 1:
                    op = GroupedOperation()
                    for node, position in self._saved_node_positions:
                        op.addOperation(
                            RotateOperation(node,
                                            rotation,
                                            rotate_around_point=position))
                    op.push()
                else:
                    for node, position in self._saved_node_positions:
                        RotateOperation(node,
                                        rotation,
                                        rotate_around_point=position).push()

                self.setDragStart(event.x, event.y)
            return True

        if event.type == Event.MouseReleaseEvent:
            # Finish a rotate operation
            if self.getDragPlane():
                self.setDragPlane(None)
                self.setLockedAxis(ToolHandle.NoAxis)
                self._angle = None
                self.propertyChanged.emit()
                if self._rotating:
                    self.operationStopped.emit(self)
                return True
Exemple #10
0
from UM.Scene.ToolHandle import ToolHandle
from UM.Tool import Tool


def test_exposedProperties():

    test_tool_1 = Tool()
    test_tool_1.setPluginId("test_tool_1")

    test_tool_1.setExposedProperties("bla", "omg", "zomg")
    assert test_tool_1.getExposedProperties() == ["bla", "omg", "zomg"]


test_validate_data = [{
    "attribute": "DragPlane",
    "value": Plane()
}, {
    "attribute": "Handle",
    "value": None
}]


@pytest.mark.parametrize("data", test_validate_data)
def test_getAndSet(data):
    test_tool = Tool()
    # Attempt to set the value
    getattr(test_tool, "set" + data["attribute"])(data["value"])

    # Ensure that the value got set
    assert getattr(test_tool, "get" + data["attribute"])() == data["value"]
Exemple #11
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)
            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
Exemple #12
0
    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
Exemple #13
0
    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
Exemple #14
0
    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
Exemple #15
0
    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
Exemple #16
0
    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