123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- # Copyright (c) 2015 Ultimaker B.V.
- # Cura is released under the terms of the LGPLv3 or higher.
- from typing import Optional, TYPE_CHECKING
- from UM.Application import Application
- from UM.Math.Polygon import Polygon
- from UM.Qt.QtApplication import QtApplication
- from UM.Scene.SceneNode import SceneNode
- from UM.Resources import Resources
- from UM.Math.Color import Color
- from UM.Mesh.MeshBuilder import MeshBuilder # To create a mesh to display the convex hull with.
- from UM.View.GL.OpenGL import OpenGL
- if TYPE_CHECKING:
- from UM.Mesh.MeshData import MeshData
- class ConvexHullNode(SceneNode):
- shader = None # To prevent the shader from being re-built over and over again, only load it once.
- def __init__(self, node: SceneNode, hull: Optional[Polygon], thickness: float, parent: Optional[SceneNode] = None) -> None:
- """Convex hull node is a special type of scene node that is used to display an 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. If the adhesion type is set to raft, the area is extruded
- to represent the raft as well.
- """
- super().__init__(parent)
- self.setCalculateBoundingBox(False)
- self._original_parent = parent
- # Color of the drawn convex hull
- if not Application.getInstance().getIsHeadLess():
- theme = QtApplication.getInstance().getTheme()
- if theme:
- self._color = Color(*theme.getColor("convex_hull").getRgb())
- else:
- self._color = Color(0, 0, 0)
- else:
- self._color = Color(0, 0, 0)
- # The y-coordinate of the convex hull mesh. Must not be 0, to prevent z-fighting.
- self._mesh_height = 0.1
- self._thickness = thickness
- # The node this mesh is "watching"
- self._node = node
- # Area of the head + fans for display as a shadow on the buildplate
- self._convex_hull_head_mesh = None # type: Optional[MeshData]
- self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
- self._onNodeDecoratorsChanged(self._node)
- self._hull = hull
- if self._hull:
- hull_mesh_builder = MeshBuilder()
- if self._thickness == 0:
- if hull_mesh_builder.addConvexPolygon(
- self._hull.getPoints()[::], # bottom layer is reversed
- self._mesh_height, color = self._color):
- hull_mesh_builder.resetNormals()
- hull_mesh = hull_mesh_builder.build()
- self.setMeshData(hull_mesh)
- else:
- if hull_mesh_builder.addConvexPolygonExtrusion(
- self._hull.getPoints()[::-1], # bottom layer is reversed
- self._mesh_height - thickness, self._mesh_height, color = self._color):
- hull_mesh_builder.resetNormals()
- hull_mesh = hull_mesh_builder.build()
- self.setMeshData(hull_mesh)
- def getHull(self):
- return self._hull
- def getThickness(self):
- return self._thickness
- def getWatchedNode(self):
- return self._node
- def render(self, renderer):
- if not ConvexHullNode.shader:
- ConvexHullNode.shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "transparent_object.shader"))
- ConvexHullNode.shader.setUniformValue("u_diffuseColor", self._color)
- ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
- batch = renderer.getNamedBatch("convex_hull_node")
- if not batch:
- batch = renderer.createRenderBatch(transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
- renderer.addRenderBatch(batch, name = "convex_hull_node")
- batch.addItem(self.getWorldTransformation(copy = False), self.getMeshData())
- if self._convex_hull_head_mesh:
- # The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
- # cannot be printed after A, because the head would hit A while printing the current object
- renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
- return True
- def _onNodeDecoratorsChanged(self, node: SceneNode) -> None:
- convex_hull_head = self._node.callDecoration("getConvexHullHeadFull")
- if convex_hull_head:
- convex_hull_head_builder = MeshBuilder()
- convex_hull_head_builder.addConvexPolygon(convex_hull_head.getPoints(), self._mesh_height - self._thickness)
- self._convex_hull_head_mesh = convex_hull_head_builder.build()
|