Merge branch '5.11' into CURA-12737_model-rotation-stops-over-model-with-painting

This commit is contained in:
Saumya Jain 2025-09-30 15:28:27 +02:00 committed by GitHub
commit d86984aca7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 50 additions and 14 deletions

View file

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt6.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
from typing import Iterable, TYPE_CHECKING
from typing import Iterable, TYPE_CHECKING, Optional, Dict, Any
from UM.i18n import i18nCatalog
from UM.Qt.ListModel import ListModel
@ -104,6 +104,9 @@ class ExtrudersModel(ListModel):
self.addOptionalExtruderChanged.emit()
self._updateExtruders()
def getExtruderItem(self, extruder_index: int) -> Optional[Dict[str, Any]]:
return next((item for item in self.items if item["index"] == extruder_index), None)
@pyqtProperty(bool, fset = setAddOptionalExtruder, notify = addOptionalExtruderChanged)
def addOptionalExtruder(self):
return self._add_optional_extruder

View file

@ -415,11 +415,12 @@ class StartSliceJob(Job):
for node in group:
# Only check if the printing extruder is enabled for printing meshes
is_non_printing_mesh = node.callDecoration("evaluateIsNonPrintingMesh")
extruder_position = int(node.callDecoration("getActiveExtruderPosition"))
if not is_non_printing_mesh and not extruders_enabled[extruder_position]:
skip_group = True
has_model_with_disabled_extruders = True
associated_disabled_extruders.add(extruder_position)
if not is_non_printing_mesh:
for used_extruder in StartSliceJob._getUsedExtruders(node):
if not extruders_enabled[used_extruder]:
skip_group = True
has_model_with_disabled_extruders = True
associated_disabled_extruders.add(used_extruder)
if not skip_group:
filtered_object_groups.append(group)
@ -760,3 +761,27 @@ class StartSliceJob(Job):
relations_set.add(relation.target.key)
self._addRelations(relations_set, relation.target.relations)
@staticmethod
def _getUsedExtruders(node: SceneNode) -> List[int]:
used_extruders = []
# Look at extruders used in painted texture
node_texture = node.callDecoration("getPaintTexture")
texture_data_mapping = node.callDecoration("getTextureDataMapping")
if node_texture is not None and texture_data_mapping is not None and "extruder" in texture_data_mapping:
texture_image = node_texture.getImage().copy()
image_ptr = texture_image.bits()
image_ptr.setsize(texture_image.sizeInBytes())
image_size = texture_image.height(), texture_image.width()
image_array = numpy.frombuffer(image_ptr, dtype=numpy.uint32).reshape(image_size)
bit_range_start, bit_range_end = texture_data_mapping["extruder"]
image_array = (image_array << (32 - 1 - (bit_range_end - bit_range_start))) >> (32 - 1 - bit_range_end)
used_extruders = numpy.unique(image_array).tolist()
# There is no relevant painting data, just take the extruder associated to the model
if not used_extruders:
used_extruders = [int(node.callDecoration("getActiveExtruderPosition"))]
return used_extruders

View file

@ -527,6 +527,6 @@ class FlavorParser:
# The "save/print" button's state is bound to the backend state.
backend = CuraApplication.getInstance().getBackend()
backend.backendStateChange.emit(Backend.BackendState.Disabled)
backend.setState(Backend.BackendState.Disabled)
return scene_node

View file

@ -463,12 +463,15 @@ class PaintTool(Tool):
def getRequiredExtraRenderingPasses(self) -> list[str]:
return ["selection_faces", "picking_selected"]
@staticmethod
def _updateScene(node: SceneNode = None):
def _updateScene(self, node: SceneNode = None):
if node is None:
node = Selection.getSelectedObject(0)
if node is not None:
Application.getInstance().getController().getScene().sceneChanged.emit(node)
if self._mouse_held:
Application.getInstance().getController().getScene().sceneChanged.emit(node)
else:
scene = self.getController().getScene()
scene.sceneChanged.emit(scene.getRoot())
def _onSelectionChanged(self):
super()._onSelectionChanged()

View file

@ -31,6 +31,8 @@ catalog = i18nCatalog("cura")
class PaintView(CuraView):
"""View for model-painting."""
MAX_EXTRUDER_COUNT = 16
class PaintType:
def __init__(self, display_color: Color, value: int):
self.display_color: Color = display_color
@ -114,14 +116,17 @@ class PaintView(CuraView):
def _makeExtrudersColors(self) -> Dict[str, "PaintView.PaintType"]:
extruders_colors: Dict[str, "PaintView.PaintType"] = {}
for extruder_item in self._extruders_model.items:
if "color" in extruder_item:
for extruder_index in range(PaintView.MAX_EXTRUDER_COUNT):
extruder_item = self._extruders_model.getExtruderItem(extruder_index)
if extruder_item is None:
extruder_item = self._extruders_model.getExtruderItem(0)
if extruder_item is not None and "color" in extruder_item:
material_color = extruder_item["color"]
else:
material_color = self._extruders_model.defaultColors[0]
index = extruder_item["index"]
extruders_colors[str(index)] = self.PaintType(Color(*QColor(material_color).getRgb()), index)
extruders_colors[str(extruder_index)] = self.PaintType(Color(*QColor(material_color).getRgb()), extruder_index)
return extruders_colors