# Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.Scene.SceneNode import SceneNode from UM.Resources import Resources from UM.Math.Color import Color from UM.Math.Vector import Vector from UM.Mesh.MeshBuilder import MeshBuilder # To create a mesh to display the convex hull with. from UM.View.GL.OpenGL import OpenGL class ConvexHullNode(SceneNode): ## Convex hull node is a special type of scene node that is used to display a 2D area, to indicate the # location an object uses on the buildplate. This area (or area's in case of one at a time printing) is # then displayed as a transparent shadow. def __init__(self, node, hull, parent = None): super().__init__(parent) self.setCalculateBoundingBox(False) self._shader = None self._original_parent = parent # Color of the drawn convex hull self._color = Color(35, 35, 35, 128) # The y-coordinate of the convex hull mesh. Must not be 0, to prevent z-fighting. self._mesh_height = 0.1 # The node this mesh is "watching" self._node = node self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged) self._onNodeDecoratorsChanged(self._node) self._convex_hull_head_mesh = None self._hull = hull if self._hull: hull_mesh = self.createHullMesh(self._hull.getPoints()) if hull_mesh: self.setMeshData(hull_mesh) convex_hull_head = self._node.callDecoration("getConvexHullHead") if convex_hull_head: self._convex_hull_head_mesh = self.createHullMesh(convex_hull_head.getPoints()) def getHull(self): return self._hull ## Actually create the mesh from the hullpoints # /param hull_points list of xy values # /return meshData def createHullMesh(self, hull_points): # Input checking. if len(hull_points) < 3: return None mesh_builder = MeshBuilder() point_first = Vector(hull_points[0][0], self._mesh_height, hull_points[0][1]) point_previous = Vector(hull_points[1][0], self._mesh_height, hull_points[1][1]) for point in hull_points[2:]: # Add the faces in the order of a triangle fan. point_new = Vector(point[0], self._mesh_height, point[1]) mesh_builder.addFace(point_first, point_previous, point_new, color = self._color) point_previous = point_new # Prepare point_previous for the next triangle. return mesh_builder.build() def getWatchedNode(self): return self._node def render(self, renderer): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._shader.setUniformValue("u_color", self._color) if self.getParent(): if self.getMeshData(): renderer.queueNode(self, transparent = True, shader = self._shader, backface_cull = True, sort = -8) if self._convex_hull_head_mesh: renderer.queueNode(self, shader = self._shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8) return True def _onNodeDecoratorsChanged(self, node): self._color = Color(35, 35, 35, 0.5) if not node: return