Send texture data to the engine

CURA-12574
This commit is contained in:
Erwan MATHIEU 2025-06-24 13:36:49 +02:00
parent 7dcc5cd470
commit be14fc7dd6
4 changed files with 45 additions and 28 deletions

View file

@ -1,8 +1,10 @@
import copy
import json
from typing import Optional, Dict
from PyQt6.QtGui import QImage
from PyQt6.QtCore import QBuffer
from PyQt6.QtGui import QImage, QImageWriter
import UM.View.GL.Texture
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
@ -40,6 +42,22 @@ class SliceableObjectDecorator(SceneNodeDecorator):
def setTextureDataMapping(self, mapping: Dict[str, tuple[int, int]]) -> None:
self._texture_data_mapping = mapping
def packTexture(self) -> Optional[bytearray]:
if self._paint_texture is None:
return None
texture_image = self._paint_texture.getImage()
if texture_image is None:
return None
texture_buffer = QBuffer()
texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite)
image_writer = QImageWriter(texture_buffer, b"png")
image_writer.setText("Description", json.dumps(self._texture_data_mapping))
image_writer.write(texture_image)
return texture_buffer.data()
def __deepcopy__(self, memo) -> "SliceableObjectDecorator":
copied_decorator = SliceableObjectDecorator()
copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture()))

View file

@ -29,7 +29,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Snapshot import Snapshot
from PyQt6.QtCore import Qt, QBuffer
from PyQt6.QtGui import QImage, QPainter, QImageWriter
from PyQt6.QtGui import QImage, QPainter
import pySavitar as Savitar
from .UCPDialog import UCPDialog
@ -158,24 +158,13 @@ class ThreeMFWriter(MeshWriter):
else:
savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tobytes())
texture = um_node.callDecoration("getPaintTexture")
packed_texture = um_node.callDecoration("packTexture")
uv_coordinates_array = mesh_data.getUVCoordinatesAsByteArray()
if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0:
texture_image = texture.getImage()
if texture_image is not None:
texture_buffer = QBuffer()
texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite)
image_writer = QImageWriter(texture_buffer, b"png")
texture_data_mapping = um_node.callDecoration("getTextureDataMapping")
if texture_data_mapping is not None:
image_writer.setText("Description", json.dumps(texture_data_mapping))
image_writer.write(texture_image)
if packed_texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0:
texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png"
texture_file = zipfile.ZipInfo(texture_path)
# Don't try to compress texture file, because the PNG is pretty much as compact as it will get
archive.writestr(texture_file, texture_buffer.data())
archive.writestr(texture_file, packed_texture)
savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, texture_path, scene)

View file

@ -53,6 +53,8 @@ message Object
bytes indices = 4; //An array of ints.
repeated Setting settings = 5; // Setting override per object, overruling the global settings.
string name = 6; //Mesh name
bytes uv_coordinates = 7; //An array of 2 floats.
bytes texture = 8; //PNG-encoded texture data
}
message Progress

View file

@ -509,6 +509,14 @@ class StartSliceJob(Job):
obj.vertices = flat_verts
uv_coordinates = mesh_data.getUVCoordinates()
if uv_coordinates is not None:
obj.uv_coordinates = uv_coordinates.flatten()
packed_texture = object.callDecoration("packTexture")
if packed_texture is not None:
obj.texture = packed_texture
self._handlePerObjectSettings(cast(CuraSceneNode, object), obj)
Job.yieldThread()