Source code for scfile.content.textures

"""Texture structures."""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import override


CUBEMAP_FACES = ("+x", "-x", "+y", "-y", "+z", "-z")
"""Cubemap face order."""

CUBEMAP_FACE_COUNT = len(CUBEMAP_FACES)
"""Number of faces in a cubemap."""


[docs] @dataclass class TextureMeta: """Texture source metadata.""" mipmap_count: int = 0 format: bytes = field(default_factory=bytes) path_hash: bytes = field(default_factory=bytes)
[docs] @dataclass class Texture(ABC): """Base class for texture data.""" @property @abstractmethod def mipmap_count(self) -> int: ... @property @abstractmethod def image(self) -> bytes: ... @property @abstractmethod def linear_size(self) -> int: ...
[docs] @dataclass class DefaultTexture(Texture): """Standard 2D texture with mipmaps.""" uncompressed: list[int] = field(default_factory=list) compressed: list[int] = field(default_factory=list) mipmaps: list[bytes] = field(default_factory=list) @property @override def mipmap_count(self) -> int: return len(self.mipmaps) @property @override def image(self) -> bytes: return b"".join(self.mipmaps) @property @override def linear_size(self) -> int: return self.uncompressed[0] if self.uncompressed else 0
[docs] @dataclass class CubemapTexture(Texture): """Cubemap texture with face separated mipmaps.""" uncompressed: list[list[int]] = field(default_factory=list) compressed: list[list[int]] = field(default_factory=list) faces: list[list[bytes]] = field(default_factory=lambda: [[] for _ in range(CUBEMAP_FACE_COUNT)]) @property @override def mipmap_count(self) -> int: return len(self.faces[0]) if self.faces else 0 @property @override def image(self) -> bytes: return b"".join(b"".join(face) for face in self.faces) @property @override def linear_size(self) -> int: return self.uncompressed[0][0] if self.uncompressed and self.uncompressed[0] else 0