mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-23 06:09:38 +08:00
108 lines
4.7 KiB
Python
108 lines
4.7 KiB
Python
# 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()
|