Source code for nanome.api.shapes.serializers

from nanome._internal.serializer_fields import TypeSerializer, StringField, UnityPositionField, ColorField, ArrayField
import os
import tempfile
import logging
from nanome.util.enums import ShapeType
from .anchor import Anchor
from . import Label, Line, Mesh, Sphere

logger = logging.getLogger(__name__)


[docs]class AnchorSerializer(TypeSerializer): def __init__(self): self._offset = UnityPositionField()
[docs] def version(self): return 0
[docs] def name(self): return "ShapeAnchor"
[docs] def serialize(self, version, value, context): context.write_long(value._target) context.write_byte(int(value._anchor_type)) context.write_using_serializer(self._offset, value._local_offset) context.write_using_serializer(self._offset, value._global_offset) context.write_using_serializer(self._offset, value._viewer_offset)
[docs] def deserialize(self, version, context): result = Anchor() result._target = context.read_long() result._anchor_type = ShapeType.safe_cast(context.read_byte()) result._local_offset = context.read_using_serializer(self._offset) result._global_offset = context.read_using_serializer(self._offset) result._viewer_offset = context.read_using_serializer(self._offset) return result
[docs]class LabelSerializer(TypeSerializer): def __init__(self): self._string = StringField()
[docs] def version(self): return 0
[docs] def name(self): return "LabelShape"
[docs] def serialize(self, version, value, context): context.write_using_serializer(self._string, value._text) context.write_float(value._font_size)
[docs] def deserialize(self, version, context): result = Label() result._text = context.read_using_serializer(self._string) result._font_size = context.read_float() return result
[docs]class LineSerializer(TypeSerializer):
[docs] def version(self): return 0
[docs] def name(self): return "LineShape"
[docs] def serialize(self, version, value, context): context.write_float(value._thickness) context.write_float(value._dash_length) context.write_float(value._dash_distance)
[docs] def deserialize(self, version, context): result = Line._create() result._thickness = context.read_float() result._dash_length = context.read_float() result._dash_distance = context.read_float() return result
[docs]class MeshSerializer(TypeSerializer):
[docs] def version(self): return 1
[docs] def name(self): return "MeshShape"
[docs] def read_texture(self, value): if value.texture_path != "": filename, ext = os.path.splitext(value.texture_path) if ext.lower() in [".jpeg", ".jpg", ".png"]: path = value.texture_path.replace("\\", "/") if os.path.isfile(path): try: with open(path, "rb") as f: texture_bytes = bytearray(f.read()) return texture_bytes except Exception as e: logger.error("Error reading texture file: " + e) else: logger.error("Texture file does not exist") else: logger.error("Texture file should be a png or a jpg file") return []
[docs] def serialize(self, version, value, context): context.write_float_array(value.vertices) context.write_float_array(value.normals) context.write_float_array(value.colors) context.write_int_array(value.triangles) context.write_float_array(value.uv) texture_bytes = self.read_texture(value) context.write_byte_array(texture_bytes) if len(texture_bytes) > 0: logger.debug("Sending texture: {}".format(value.texture_path)) if version >= 1: context.write_bool(value.unlit)
[docs] def create_texture_file(self, texture_path, texture_bytes): with open(texture_path, "wb") as f: f.write(texture_bytes)
[docs] def deserialize(self, version, context): result = Mesh._create() result.vertices = context.read_float_array() result.normals = context.read_float_array() result.colors = context.read_float_array() result.triangles = context.read_int_array() result.uv = context.read_float_array() texture_bytes = context.read_byte_array() if version >= 1: result.unlit = context.read_bool() if len(texture_bytes) > 0: temp_texture = tempfile.NamedTemporaryFile( delete=False, suffix='png') self.create_texture_file(temp_texture.name, texture_bytes) result.texture_path = temp_texture.name return result
[docs]class ShapeSerializer(TypeSerializer): def __init__(self): self._position = UnityPositionField() self._color = ColorField() self._sphere = SphereSerializer() self._line = LineSerializer() self._label = LabelSerializer() self._mesh = MeshSerializer() self._anchor_array = ArrayField() self._anchor_array.set_type(AnchorSerializer())
[docs] def version(self): return 1
[docs] def name(self): return "Shape"
[docs] def serialize(self, version, value, context): context.write_byte(int(value._shape_type)) if value.shape_type == ShapeType.Sphere: context.write_using_serializer(self._sphere, value) elif value.shape_type == ShapeType.Line: context.write_using_serializer(self._line, value) elif value.shape_type == ShapeType.Label: context.write_using_serializer(self._label, value) elif value.shape_type == ShapeType.Mesh: context.write_using_serializer(self._mesh, value) context.write_int(value._index) context.write_using_serializer(self._anchor_array, value._anchors) context.write_using_serializer(self._color, value._color)
[docs] def deserialize(self, version, context): from nanome.util.enums import ShapeType shapeType = ShapeType.safe_cast(context.read_byte()) result = None if shapeType == ShapeType.Sphere: result = context.read_using_serializer(self._sphere) elif shapeType == ShapeType.Line: result = context.read_using_serializer(self._line) elif shapeType == ShapeType.Label: result = context.read_using_serializer(self._label) elif shapeType == ShapeType.Mesh: result = context.read_using_serializer(self._mesh) result._index = context.read_int() result._anchors = context.read_using_serializer(self._anchor_array) result._color = context.read_using_serializer(self._color) return (context.read_int(), context.read_bool())
[docs]class SphereSerializer(TypeSerializer):
[docs] def version(self): return 0
[docs] def name(self): return "SphereShape"
[docs] def serialize(self, version, value, context): context.write_float(value.radius)
[docs] def deserialize(self, version, context): result = Sphere._create() result.radius = context.read_float() return result