Load painted texture from 3MF file

CURA-12544
This commit is contained in:
Erwan MATHIEU 2025-06-03 15:59:02 +02:00
parent f0764134cc
commit 57f811af88
2 changed files with 22 additions and 2 deletions

View File

@ -1,5 +1,11 @@
import copy
from typing import Optional
import UM.View.GL.Texture
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
from UM.View.GL.OpenGL import OpenGL from UM.View.GL.OpenGL import OpenGL
from UM.View.GL.Texture import Texture
# FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both).
@ -14,10 +20,13 @@ class SliceableObjectDecorator(SceneNodeDecorator):
def isSliceable(self) -> bool: def isSliceable(self) -> bool:
return True return True
def getPaintTexture(self, create_if_required: bool = True): def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]:
if self._paint_texture is None and create_if_required: if self._paint_texture is None and create_if_required:
self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT)
return self._paint_texture return self._paint_texture
def setPaintTexture(self, texture: UM.View.GL.Texture) -> None:
self._paint_texture = texture
def __deepcopy__(self, memo) -> "SliceableObjectDecorator": def __deepcopy__(self, memo) -> "SliceableObjectDecorator":
return type(self)() return type(self)()

View File

@ -7,6 +7,7 @@ from typing import List, Optional, Union, TYPE_CHECKING, cast
import pySavitar as Savitar import pySavitar as Savitar
import numpy import numpy
from PyQt6.QtGui import QImage
from UM.Logger import Logger from UM.Logger import Logger
from UM.Math.Matrix import Matrix from UM.Math.Matrix import Matrix
@ -18,6 +19,8 @@ from UM.Scene.GroupDecorator import GroupDecorator
from UM.Scene.SceneNode import SceneNode # For typing. from UM.Scene.SceneNode import SceneNode # For typing.
from UM.Scene.SceneNodeSettings import SceneNodeSettings from UM.Scene.SceneNodeSettings import SceneNodeSettings
from UM.Util import parseBool from UM.Util import parseBool
from UM.View.GL.OpenGL import OpenGL
from UM.View.GL.Texture import Texture
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Machines.ContainerTree import ContainerTree from cura.Machines.ContainerTree import ContainerTree
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
@ -101,7 +104,7 @@ class ThreeMFReader(MeshReader):
""" """
try: try:
node_name = savitar_node.getName() node_name = savitar_node.getName()
node_id = savitar_node.getId() node_id = str(savitar_node.getId())
except AttributeError: except AttributeError:
Logger.log("e", "Outdated version of libSavitar detected! Please update to the newest version!") Logger.log("e", "Outdated version of libSavitar detected! Please update to the newest version!")
node_name = "" node_name = ""
@ -226,6 +229,14 @@ class ThreeMFReader(MeshReader):
# affects (auto) slicing # affects (auto) slicing
sliceable_decorator = SliceableObjectDecorator() sliceable_decorator = SliceableObjectDecorator()
um_node.addDecorator(sliceable_decorator) um_node.addDecorator(sliceable_decorator)
if texture_path != "" and archive is not None:
texture_data = archive.open(texture_path).read()
texture_image = QImage.fromData(texture_data, "PNG")
texture = Texture(OpenGL.getInstance())
texture.setImage(texture_image)
sliceable_decorator.setPaintTexture(texture)
return um_node return um_node
def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: