mirror of
https://github.com/Ultimaker/Cura.git
synced 2026-01-22 13:17:00 -07:00
Move patch for buildvolume into BlackBelt plugin
This commit is contained in:
parent
00980dcde2
commit
2f9889c350
3 changed files with 224 additions and 15 deletions
|
|
@ -258,18 +258,12 @@ class BuildVolume(SceneNode):
|
|||
self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
|
||||
self._error_area_color = Color(*theme.getColor("error_area").getRgb())
|
||||
|
||||
# Get a dict from the machine metadata optionally overriding the build volume
|
||||
# Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura
|
||||
limit_buildvolume = self._global_container_stack.getMetaDataEntry("limit_buildvolume", {})
|
||||
if not isinstance(limit_buildvolume, dict):
|
||||
limit_buildvolume = {}
|
||||
|
||||
min_w = limit_buildvolume.get("width", {}).get("minimum",-self._width / 2)
|
||||
max_w = limit_buildvolume.get("width", {}).get("maximum", self._width / 2)
|
||||
min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0)
|
||||
max_h = limit_buildvolume.get("height", {}).get("maximum", self._height)
|
||||
min_d = limit_buildvolume.get("depth", {}).get("minimum",-self._depth / 2)
|
||||
max_d = limit_buildvolume.get("depth", {}).get("maximum", self._depth / 2)
|
||||
min_w = -self._width / 2
|
||||
max_w = self._width / 2
|
||||
min_h = 0.0
|
||||
max_h = self._height
|
||||
min_d = -self._depth / 2
|
||||
max_d = self._depth / 2
|
||||
|
||||
z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from UM.Math.Vector import Vector
|
|||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("BlackBeltPlugin")
|
||||
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from . import BuildVolumePatches
|
||||
|
||||
import math
|
||||
import os.path
|
||||
|
|
@ -21,6 +21,8 @@ class BlackBeltPlugin(Extension):
|
|||
|
||||
self._application = Application.getInstance()
|
||||
|
||||
self._build_volume_patches = None
|
||||
|
||||
self._global_container_stack = None
|
||||
self._application.globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
|
||||
self._onGlobalContainerStackChanged()
|
||||
|
|
@ -29,7 +31,7 @@ class BlackBeltPlugin(Extension):
|
|||
self._scene_root.addDecorator(BlackBeltDecorator())
|
||||
self._application.getBackend().slicingStarted.connect(self._onSlicingStarted)
|
||||
|
||||
self._application.engineCreatedSignal.connect(self._fixPreferences)
|
||||
self._application.engineCreatedSignal.connect(self._onEngineCreated)
|
||||
|
||||
def _onGlobalContainerStackChanged(self):
|
||||
if self._global_container_stack:
|
||||
|
|
@ -53,7 +55,11 @@ class BlackBeltPlugin(Extension):
|
|||
# This is a bit of a hack, but it seems quick enough.
|
||||
self._application.globalContainerStackChanged.emit()
|
||||
|
||||
def _fixPreferences(self):
|
||||
def _onEngineCreated(self):
|
||||
# Apply patches
|
||||
self._build_volume_patches = BuildVolumePatches.BuildVolumePatches(self._application.getBuildVolume())
|
||||
|
||||
# Fix preferences
|
||||
preferences = Preferences.getInstance()
|
||||
visible_settings = preferences.getValue("general/visible_settings")
|
||||
if not visible_settings:
|
||||
|
|
|
|||
209
plugins/BlackBeltPlugin/BuildVolumePatches.py
Normal file
209
plugins/BlackBeltPlugin/BuildVolumePatches.py
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
from UM.Application import Application
|
||||
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Math.Matrix import Matrix
|
||||
from UM.Math.Color import Color
|
||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||
|
||||
import numpy
|
||||
import math
|
||||
|
||||
class BuildVolumePatches():
|
||||
def __init__(self, build_volume):
|
||||
self._build_volume = build_volume
|
||||
self._build_volume.rebuild = self._rebuild
|
||||
|
||||
## Recalculates the build volume & disallowed areas.
|
||||
# Copied verbatim from Buildvolume.rebuild, with a minor patch to limit the buildvolume asymmetrically
|
||||
def _rebuild(self):
|
||||
if not self._build_volume._width or not self._build_volume._height or not self._build_volume._depth:
|
||||
return
|
||||
|
||||
if not Application.getInstance()._engine:
|
||||
return
|
||||
|
||||
if not self._build_volume._volume_outline_color:
|
||||
theme = Application.getInstance().getTheme()
|
||||
self._build_volume._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
|
||||
self._build_volume._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
|
||||
self._build_volume._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
|
||||
self._build_volume._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
|
||||
self._build_volume._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
|
||||
self._build_volume._error_area_color = Color(*theme.getColor("error_area").getRgb())
|
||||
|
||||
### START PATCH
|
||||
# Get a dict from the machine metadata optionally overriding the build volume
|
||||
# Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura
|
||||
limit_buildvolume = self._build_volume._global_container_stack.getMetaDataEntry("limit_buildvolume", {})
|
||||
if not isinstance(limit_buildvolume, dict):
|
||||
limit_buildvolume = {}
|
||||
|
||||
min_w = limit_buildvolume.get("width", {}).get("minimum",-self._build_volume._width / 2)
|
||||
max_w = limit_buildvolume.get("width", {}).get("maximum", self._build_volume._width / 2)
|
||||
min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0)
|
||||
max_h = limit_buildvolume.get("height", {}).get("maximum", self._build_volume._height)
|
||||
min_d = limit_buildvolume.get("depth", {}).get("minimum",-self._build_volume._depth / 2)
|
||||
max_d = limit_buildvolume.get("depth", {}).get("maximum", self._build_volume._depth / 2)
|
||||
### END PATCH
|
||||
|
||||
z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting
|
||||
|
||||
if self._build_volume._shape != "elliptic":
|
||||
# Outline 'cube' of the build volume
|
||||
mb = MeshBuilder()
|
||||
mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self._build_volume._volume_outline_color)
|
||||
|
||||
mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
|
||||
mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
|
||||
|
||||
self._build_volume.setMeshData(mb.build())
|
||||
|
||||
# Build plate grid mesh
|
||||
mb = MeshBuilder()
|
||||
mb.addQuad(
|
||||
Vector(min_w, min_h - z_fight_distance, min_d),
|
||||
Vector(max_w, min_h - z_fight_distance, min_d),
|
||||
Vector(max_w, min_h - z_fight_distance, max_d),
|
||||
Vector(min_w, min_h - z_fight_distance, max_d)
|
||||
)
|
||||
|
||||
for n in range(0, 6):
|
||||
v = mb.getVertex(n)
|
||||
mb.setVertexUVCoordinates(n, v[0], v[2])
|
||||
self._build_volume._grid_mesh = mb.build()
|
||||
|
||||
else:
|
||||
# Bottom and top 'ellipse' of the build volume
|
||||
aspect = 1.0
|
||||
scale_matrix = Matrix()
|
||||
if self._build_volume._width != 0:
|
||||
# Scale circular meshes by aspect ratio if width != height
|
||||
aspect = self._build_volume._depth / self._build_volume._width
|
||||
scale_matrix.compose(scale = Vector(1, 1, aspect))
|
||||
mb = MeshBuilder()
|
||||
mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self._build_volume._volume_outline_color)
|
||||
mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self._build_volume._volume_outline_color)
|
||||
self._build_volume.setMeshData(mb.build().getTransformed(scale_matrix))
|
||||
|
||||
# Build plate grid mesh
|
||||
mb = MeshBuilder()
|
||||
mb.addVertex(0, min_h - z_fight_distance, 0)
|
||||
mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0))
|
||||
sections = mb.getVertexCount() - 1 # Center point is not an arc section
|
||||
indices = []
|
||||
for n in range(0, sections - 1):
|
||||
indices.append([0, n + 2, n + 1])
|
||||
mb.addIndices(numpy.asarray(indices, dtype = numpy.int32))
|
||||
mb.calculateNormals()
|
||||
|
||||
for n in range(0, mb.getVertexCount()):
|
||||
v = mb.getVertex(n)
|
||||
mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
|
||||
self._build_volume._grid_mesh = mb.build().getTransformed(scale_matrix)
|
||||
|
||||
# Indication of the machine origin
|
||||
if self._build_volume._global_container_stack.getProperty("machine_center_is_zero", "value"):
|
||||
origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2
|
||||
else:
|
||||
origin = Vector(min_w, min_h, max_d)
|
||||
|
||||
mb = MeshBuilder()
|
||||
mb.addCube(
|
||||
width = self._build_volume._origin_line_length,
|
||||
height = self._build_volume._origin_line_width,
|
||||
depth = self._build_volume._origin_line_width,
|
||||
center = origin + Vector(self._build_volume._origin_line_length / 2, 0, 0),
|
||||
color = self._build_volume._x_axis_color
|
||||
)
|
||||
mb.addCube(
|
||||
width = self._build_volume._origin_line_width,
|
||||
height = self._build_volume._origin_line_length,
|
||||
depth = self._build_volume._origin_line_width,
|
||||
center = origin + Vector(0, self._build_volume._origin_line_length / 2, 0),
|
||||
color = self._build_volume._y_axis_color
|
||||
)
|
||||
mb.addCube(
|
||||
width = self._build_volume._origin_line_width,
|
||||
height = self._build_volume._origin_line_width,
|
||||
depth = self._build_volume._origin_line_length,
|
||||
center = origin - Vector(0, 0, self._build_volume._origin_line_length / 2),
|
||||
color = self._build_volume._z_axis_color
|
||||
)
|
||||
self._build_volume._origin_mesh = mb.build()
|
||||
|
||||
disallowed_area_height = 0.1
|
||||
disallowed_area_size = 0
|
||||
if self._build_volume._disallowed_areas:
|
||||
mb = MeshBuilder()
|
||||
color = self._build_volume._disallowed_area_color
|
||||
for polygon in self._build_volume._disallowed_areas:
|
||||
points = polygon.getPoints()
|
||||
if len(points) == 0:
|
||||
continue
|
||||
|
||||
first = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d))
|
||||
previous_point = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d))
|
||||
for point in points:
|
||||
new_point = Vector(self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(point[1], min_d, max_d))
|
||||
mb.addFace(first, previous_point, new_point, color = color)
|
||||
previous_point = new_point
|
||||
|
||||
# Find the largest disallowed area to exclude it from the maximum scale bounds.
|
||||
# This is a very nasty hack. This pretty much only works for UM machines.
|
||||
# This disallowed area_size needs a -lot- of rework at some point in the future: TODO
|
||||
if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
|
||||
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
|
||||
else:
|
||||
size = 0
|
||||
disallowed_area_size = max(size, disallowed_area_size)
|
||||
|
||||
self._build_volume._disallowed_area_mesh = mb.build()
|
||||
else:
|
||||
self._build_volume._disallowed_area_mesh = None
|
||||
|
||||
if self._build_volume._error_areas:
|
||||
mb = MeshBuilder()
|
||||
for error_area in self._build_volume._error_areas:
|
||||
color = self._build_volume._error_area_color
|
||||
points = error_area.getPoints()
|
||||
first = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height,
|
||||
self._build_volume._clamp(points[0][1], min_d, max_d))
|
||||
previous_point = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height,
|
||||
self._build_volume._clamp(points[0][1], min_d, max_d))
|
||||
for point in points:
|
||||
new_point = Vector(self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height,
|
||||
self._build_volume._clamp(point[1], min_d, max_d))
|
||||
mb.addFace(first, previous_point, new_point, color=color)
|
||||
previous_point = new_point
|
||||
self._build_volume._error_mesh = mb.build()
|
||||
else:
|
||||
self._build_volume._error_mesh = None
|
||||
|
||||
self._build_volume._volume_aabb = AxisAlignedBox(
|
||||
minimum = Vector(min_w, min_h - 1.0, min_d),
|
||||
maximum = Vector(max_w, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d))
|
||||
|
||||
bed_adhesion_size = self._build_volume._getEdgeDisallowedSize()
|
||||
|
||||
# As this works better for UM machines, we only add the disallowed_area_size for the z direction.
|
||||
# This is probably wrong in all other cases. TODO!
|
||||
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
|
||||
scale_to_max_bounds = AxisAlignedBox(
|
||||
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
|
||||
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
|
||||
)
|
||||
|
||||
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
|
||||
|
||||
self._build_volume.updateNodeBoundaryCheck()
|
||||
Loading…
Add table
Add a link
Reference in a new issue