-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathxcod.py
More file actions
109 lines (76 loc) · 2.63 KB
/
xcod.py
File metadata and controls
109 lines (76 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
from loguru import logger
from sc_compression import Signatures
from xcoder.bytestream import Reader
from xcoder.localization import locale
from xcoder.math.point import Point
@dataclass
class SheetInfo:
file_type: int
pixel_type: int
size: tuple[int, int]
@property
def width(self) -> int:
return self.size[0]
@property
def height(self) -> int:
return self.size[1]
@dataclass
class RegionInfo:
texture_id: int
points: list[Point]
@dataclass
class ShapeInfo:
id: int
regions: list[RegionInfo]
@dataclass
class FileInfo:
name: str
signature: Signatures
signature_version: int | None
sheets: list[SheetInfo]
shapes: list[ShapeInfo]
def parse_info(metadata_file_path: Path, has_detailed_info: bool) -> FileInfo:
logger.info(locale.collecting_inf % metadata_file_path.name)
print()
with open(metadata_file_path, "rb") as file:
reader = Reader(file.read(), "big")
ensure_magic_known(reader)
file_info = FileInfo(
os.path.splitext(metadata_file_path.name)[0], Signatures.NONE, None, [], []
)
parse_base_info(file_info, reader)
if has_detailed_info:
parse_detailed_info(file_info, reader)
return file_info
def parse_base_info(file_info: FileInfo, reader: Reader) -> None:
file_info.signature = Signatures.SC
file_info.signature_version = 1 if reader.read_string() == "LZMA" else 3
sheets_count = reader.read_uchar()
for i in range(sheets_count):
file_type = reader.read_uchar()
pixel_type = reader.read_uchar()
width = reader.read_ushort()
height = reader.read_ushort()
file_info.sheets.append(SheetInfo(file_type, pixel_type, (width, height)))
def parse_detailed_info(file_info: FileInfo, reader: Reader) -> None:
shapes_count = reader.read_ushort()
for shape_index in range(shapes_count):
shape_id = reader.read_ushort()
regions = []
regions_count = reader.read_ushort()
for region_index in range(regions_count):
texture_id, points_count = reader.read_uchar(), reader.read_uchar()
points = [
Point(reader.read_ushort(), reader.read_ushort())
for _ in range(points_count)
]
regions.append(RegionInfo(texture_id, points))
file_info.shapes.append(ShapeInfo(shape_id, regions))
def ensure_magic_known(reader: Reader) -> None:
magic = reader.read(4)
if magic != b"XCOD":
raise IOError("Unknown file MAGIC: " + magic.hex())