Ejemplo n.º 1
0
    def _onSelectedFaceChanged(self):
        self._handle.setEnabled(not Selection.getFaceSelectMode())

        selected_face = Selection.getSelectedFace()
        if not Selection.getSelectedFace() or not (Selection.hasSelection() and Selection.getFaceSelectMode()):
            return

        original_node, face_id = selected_face
        meshdata = original_node.getMeshDataTransformed()
        if not meshdata or face_id < 0:
            return

        rotation_point, face_normal = meshdata.getFacePlane(face_id)
        rotation_point_vector = Vector(rotation_point[0], rotation_point[1], rotation_point[2])
        face_normal_vector = Vector(face_normal[0], face_normal[1], face_normal[2])
        rotation_quaternion = Quaternion.rotationTo(face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0))

        operation = GroupedOperation()
        current_node = None  # type: Optional[SceneNode]
        for node in Selection.getAllSelectedObjects():
            current_node = node
            parent_node = current_node.getParent()
            while parent_node and parent_node.callDecoration("isGroup"):
                current_node = parent_node
                parent_node = current_node.getParent()
        if current_node is None:
            return

        rotate_operation = RotateOperation(current_node, rotation_quaternion, rotation_point_vector)
        operation.addOperation(rotate_operation)
        operation.push()
Ejemplo n.º 2
0
    def _getSelectedTriangles(
        self, current_surface: Tuple[SceneNode, int],
        surface_type: SmartSliceScene.HighlightFace.SurfaceType
    ) -> Tuple[pywim.geom.tri.Face, pywim.geom.Vector]:

        if current_surface is None:
            current_surface = Selection.getSelectedFace()

        if current_surface is None:
            return None, None

        node, face_id = current_surface

        smart_slice_node = findChildSceneNode(node, SmartSliceScene.Root)

        interactive_mesh = smart_slice_node.getInteractiveMesh()

        if interactive_mesh is None:
            return None, None

        if surface_type == SmartSliceScene.HighlightFace.SurfaceType.Flat:
            selected_face = interactive_mesh.select_planar_face(face_id)
        elif surface_type == SmartSliceScene.HighlightFace.SurfaceType.Concave:
            selected_face = interactive_mesh.select_concave_face(face_id)
        elif surface_type == SmartSliceScene.HighlightFace.SurfaceType.Convex:
            selected_face = interactive_mesh.select_convex_face(face_id)

        axis = None
        if surface_type == SmartSliceScene.HighlightFace.SurfaceType.Flat:
            axis = selected_face.planar_axis()
        else:
            axis = selected_face.rotation_axis()

        return selected_face, axis
Ejemplo n.º 3
0
    def _onSelectedFaceChanged(self, current_surface=None):
        """
        Gets face id and triangles from current face selection
        """
        if getPrintableNodes() and Selection.isSelected(getPrintableNodes(
        )[0]):  # Fixes bug for when scene is unselected
            if not self.getEnabled() or not self._select:
                return

            if self._bc_list is None:
                return

            bc_node = self._bc_list.getActiveNode()

            if bc_node is None:
                return

            try:
                selected_face, axis = self._getSelectedTriangles(
                    current_surface, bc_node.surface_type)
            except Exception as exc:
                Logger.logException("e", "Unable to select face")
                selected_face = None

            if selected_face is not None:
                bc_node.selection = Selection.getSelectedFace()
                bc_node.setMeshDataFromPywimTriangles(selected_face, axis)

            self.selectedFaceChanged.emit(bc_node)
Ejemplo n.º 4
0
    def _onSelectedFaceChanged(self):
        if not self._select_face_mode:
            return

        self._handle.setEnabled(not Selection.getFaceSelectMode())

        selected_face = Selection.getSelectedFace()
        if not Selection.getSelectedFace() or not (
                Selection.hasSelection() and Selection.getFaceSelectMode()):
            return

        original_node, face_id = selected_face
        meshdata = original_node.getMeshDataTransformed()
        if not meshdata or face_id < 0:
            return
        if face_id > (meshdata.getVertexCount() / 3 if
                      not meshdata.hasIndices() else meshdata.getFaceCount()):
            return

        face_mid, face_normal = meshdata.getFacePlane(face_id)
        object_mid = original_node.getBoundingBox().center
        rotation_point_vector = Vector(object_mid.x, object_mid.y, face_mid[2])
        face_normal_vector = Vector(face_normal[0], face_normal[1],
                                    face_normal[2])
        rotation_quaternion = Quaternion.rotationTo(
            face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0))

        operation = GroupedOperation()
        current_node = None  # type: Optional[SceneNode]
        for node in Selection.getAllSelectedObjects():
            current_node = node
            parent_node = current_node.getParent()
            while parent_node and parent_node.callDecoration("isGroup"):
                current_node = parent_node
                parent_node = current_node.getParent()
        if current_node is None:
            return

        rotate_operation = RotateOperation(current_node, rotation_quaternion,
                                           rotation_point_vector)
        gravity_operation = GravityOperation(current_node)
        operation.addOperation(rotate_operation)
        operation.addOperation(gravity_operation)
        operation.push()
Ejemplo n.º 5
0
    def test_addRemoveSelection(self):
        node_1 = SceneNode()
        Selection.add(node_1)
        Selection.setFace(node_1, 99)

        assert Selection.getAllSelectedObjects() == [node_1]

        Selection.remove(node_1)
        assert Selection.getAllSelectedObjects() == []
        assert Selection.getSelectedFace() is None
    def onSelectedFaceChanged(self, scene_node, face_id):
        #  Throw out "fake" selection changes
        if Selection.getSelectedFace() is None:
            return
        if self._selection_mode is SelectionMode.AnchorMode:
            if Selection.getSelectedFace()[1] == self._anchoredID:
                return
        elif self._selection_mode is SelectionMode.LoadMode:
            if Selection.getSelectedFace()[1] == self._loadedID:
                return

        select_tool = Application.getInstance().getController().getTool(
            "SmartSlicePlugin_SelectTool")
        selected_triangles = list(
            select_tool._interactive_mesh.select_planar_face(face_id))

        #  If busy, add it to 'pending changes' and ask user to confirm
        if self.connector.status in {
                SmartSliceCloudStatus.BusyValidating,
                SmartSliceCloudStatus.BusyOptimizing,
                SmartSliceCloudStatus.Optimized
        }:
            self._propertiesChanged.append(SmartSliceProperty.SelectedFace)
            self._changedValues.append(face_id)
            self._changedValues.append(scene_node)
            self._changedValues.append(selected_triangles)
            self.connector.confirmPendingChanges()
        else:
            if self._selection_mode is SelectionMode.AnchorMode:
                self._anchoredID = face_id
                self._anchoredNode = scene_node
                self._anchoredTris = selected_triangles
                self.proxy._anchorsApplied = 1  #  TODO:  Change this when > 1 anchors in Use Case
                self.applyAnchor()
            elif self._selection_mode is SelectionMode.LoadMode:
                self._loadedID = face_id
                self._loadedNode = scene_node
                self._loadedTris = selected_triangles
                self.proxy._loadsApplied = 1  #  TODO:  Change this when > 1 loads in Use Case
                self.applyLoad()
            self.connector.prepareValidation()
    def _onSelectedFaceChanged(self, curr_sf=None):
        if not self.getEnabled():
            return

        curr_sf = Selection.getSelectedFace()
        if curr_sf is None:
            return

        self._calculateMesh()

        scene_node, face_id = curr_sf

        self._handle._connector.propertyHandler.onSelectedFaceChanged(scene_node, face_id)
Ejemplo n.º 8
0
    def bottomFaceSelection(self) -> None:
        selected_face = Selection.getSelectedFace()
        if not selected_face:
            Logger.log(
                "e",
                "Bottom face operation shouldn't have been called without a selected face."
            )
            return

        original_node, face_id = selected_face
        meshdata = original_node.getMeshDataTransformed()
        if not meshdata or face_id < 0 or face_id > Selection.getMaxFaceSelectionId(
        ):
            return

        rotation_point, face_normal = meshdata.getFacePlane(face_id)
        rotation_point_vector = Vector(rotation_point[0], rotation_point[1],
                                       rotation_point[2])
        face_normal_vector = Vector(face_normal[0], face_normal[1],
                                    face_normal[2])
        rotation_quaternion = Quaternion.rotationTo(
            face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0))

        operation = GroupedOperation()
        current_node = None  # type: Optional[SceneNode]
        for node in Selection.getAllSelectedObjects():
            current_node = node
            parent_node = current_node.getParent()
            while parent_node and parent_node.callDecoration("isGroup"):
                current_node = parent_node
                parent_node = current_node.getParent()
        if current_node is None:
            return

        rotate_operation = RotateOperation(current_node, rotation_quaternion,
                                           rotation_point_vector)
        operation.addOperation(rotate_operation)
        operation.push()
Ejemplo n.º 9
0
    def test_toggleFace(self):
        Selection.selectedFaceChanged = MagicMock()
        node_1 = SceneNode()
        node_2 = SceneNode()

        assert Selection.getSelectedFace() is None

        Selection.toggleFace(node_1, 91)
        assert Selection.getSelectedFace() == (node_1, 91)
        Selection.toggleFace(node_2, 92)
        assert Selection.getSelectedFace() == (node_2, 92)
        Selection.toggleFace(node_2, 93)
        assert Selection.getSelectedFace() == (node_2, 93)
        Selection.toggleFace(node_2, 93)
        assert Selection.getSelectedFace() is None
        Selection.toggleFace(node_2, 93)
        assert Selection.getSelectedFace() == (node_2, 93)

        Selection.clearFace()
        assert Selection.getSelectedFace() is None

        assert Selection.selectedFaceChanged.emit.call_count == 6
Ejemplo n.º 10
0
 def hasFaceSelected(self):
     return Selection.getSelectedFace() is not None
Ejemplo n.º 11
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._extruders_model:
            self._extruders_model = Application.getInstance(
            ).getExtrudersModel()

        if not self._theme:
            self._theme = Application.getInstance().getTheme()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "overhang.shader"))
            self._enabled_shader.setUniformValue(
                "u_overhangColor",
                Color(*self._theme.getColor("model_overhang").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor1",
                Color(*self._theme.getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor2",
                Color(*self._theme.getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)

        if not self._non_printing_shader:
            self._non_printing_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders,
                                  "transparent_object.shader"))
            self._non_printing_shader.setUniformValue(
                "u_diffuseColor",
                Color(*self._theme.getColor("model_non_printing").getRgb()))
            self._non_printing_shader.setUniformValue("u_opacity", 0.6)

        if not self._support_mesh_shader:
            self._support_mesh_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._support_mesh_shader.setUniformValue("u_vertical_stripes",
                                                      True)
            self._support_mesh_shader.setUniformValue("u_width", 5.0)

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack:
            if Application.getInstance().getPreferences().getValue(
                    "view/show_overhang"):
                # Make sure the overhang angle is valid before passing it to the shader
                if self._support_angle is not None and self._support_angle >= 0 and self._support_angle <= 90:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle",
                        math.cos(math.radians(90 - self._support_angle)))
                else:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(0))
                    )  #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle",
                                                     math.cos(math.radians(0)))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible(
                ) and not node.callDecoration("getLayerData"):
                    uniforms = {}
                    shade_factor = 1.0

                    per_mesh_stack = node.callDecoration("getStack")

                    extruder_index = node.callDecoration(
                        "getActiveExtruderPosition")
                    if extruder_index is None:
                        extruder_index = "0"
                    extruder_index = int(extruder_index)

                    # Use the support extruder instead of the active extruder if this is a support_mesh
                    if per_mesh_stack:
                        if per_mesh_stack.getProperty("support_mesh", "value"):
                            extruder_index = int(
                                global_container_stack.
                                getExtruderPositionValueWithDefault(
                                    "support_extruder_nr"))

                    try:
                        material_color = self._extruders_model.getItem(
                            extruder_index)["color"]
                    except KeyError:
                        material_color = self._extruders_model.defaultColors[0]

                    if extruder_index != ExtruderManager.getInstance(
                    ).activeExtruderIndex:
                        # Shade objects that are printed with the non-active extruder 25% darker
                        shade_factor = 0.6

                    try:
                        # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                        # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                        uniforms["diffuse_color"] = [
                            shade_factor * int(material_color[1:3], 16) / 255,
                            shade_factor * int(material_color[3:5], 16) / 255,
                            shade_factor * int(material_color[5:7], 16) / 255,
                            1.0
                        ]

                        # Color the currently selected face-id.
                        face = Selection.getSelectedFace()
                        uniforms["selected_face"] = (
                            Selection.getMaxFaceSelectionId() +
                            1) if not face or node != face[0] else face[1]
                    except ValueError:
                        pass

                    if node.callDecoration("isNonPrintingMesh"):
                        if per_mesh_stack and (per_mesh_stack.getProperty(
                                "infill_mesh", "value")
                                               or per_mesh_stack.getProperty(
                                                   "cutting_mesh", "value")):
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                uniforms=uniforms,
                                transparent=True)
                        else:
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                transparent=True)
                    elif getattr(node, "_outside_buildarea", False):
                        renderer.queueNode(node, shader=self._disabled_shader)
                    elif per_mesh_stack and per_mesh_stack.getProperty(
                            "support_mesh", "value"):
                        # Render support meshes with a vertical stripe that is darker
                        shade_factor = 0.6
                        uniforms["diffuse_color_2"] = [
                            uniforms["diffuse_color"][0] * shade_factor,
                            uniforms["diffuse_color"][1] * shade_factor,
                            uniforms["diffuse_color"][2] * shade_factor, 1.0
                        ]
                        renderer.queueNode(node,
                                           shader=self._support_mesh_shader,
                                           uniforms=uniforms)
                    else:
                        renderer.queueNode(node,
                                           shader=self._enabled_shader,
                                           uniforms=uniforms)
                if node.callDecoration("isGroup") and Selection.isSelected(
                        node):
                    renderer.queueNode(scene.getRoot(),
                                       mesh=node.getBoundingBoxMesh(),
                                       mode=RenderBatch.RenderMode.LineLoop)