Skip to content

Commit 85047da

Browse files
refactor: the encode methods functions are refactored, metadata parsing is refactored, menu refilling is now more correct
1 parent 766514c commit 85047da

File tree

10 files changed

+225
-159
lines changed

10 files changed

+225
-159
lines changed

.flake8

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[flake8]
2+
max-line-length = 88
3+
ignore = E203, W503
4+
exclude =
5+
updates
6+
venv

system/lib/__init__.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,27 @@ def refill_menu():
6464
import sc_compression
6565

6666
del sc_compression
67-
67+
except ImportError:
68+
logger.warning(locale.install_to_unlock % "sc-compression")
69+
else:
6870
from system.lib.features.csv.compress import compress_csv
6971
from system.lib.features.csv.decompress import decompress_csv
7072

7173
try:
7274
import PIL
7375

7476
del PIL
75-
76-
from system.lib.features.sc.assembly_encode import (
77-
collect_objects_and_encode,
78-
)
77+
except ImportError:
78+
logger.warning(locale.install_to_unlock % "PILLOW")
79+
else:
7980
from system.lib.features.sc.decode import (
8081
decode_and_render_objects,
8182
decode_textures_only,
8283
)
83-
from system.lib.features.sc.encode import sc_encode
84+
from system.lib.features.sc.encode import (
85+
collect_objects_and_encode,
86+
encode_textures_only,
87+
)
8488

8589
sc_category = Menu.Category(0, locale.sc_label)
8690
sc_category.add(
@@ -89,7 +93,9 @@ def refill_menu():
8993
)
9094
)
9195
sc_category.add(
92-
Menu.Item(locale.encode_sc, locale.encode_sc_description, sc_encode)
96+
Menu.Item(
97+
locale.encode_sc, locale.encode_sc_description, encode_textures_only
98+
)
9399
)
94100
sc_category.add(
95101
Menu.Item(
@@ -113,8 +119,6 @@ def refill_menu():
113119
)
114120
)
115121
menu.add_category(sc_category)
116-
except ImportError:
117-
logger.warning(locale.install_to_unlock % "PILLOW")
118122

119123
csv_category = Menu.Category(1, locale.csv_label)
120124
csv_category.add(
@@ -128,8 +132,6 @@ def refill_menu():
128132
)
129133
)
130134
menu.add_category(csv_category)
131-
except ImportError:
132-
logger.warning(locale.install_to_unlock % "sc-compression")
133135

134136
other = Menu.Category(10, locale.other_features_label)
135137
other.add(

system/lib/features/files.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
import os
2+
13
from loguru import logger
24
from sc_compression import compress, decompress
35
from sc_compression.signatures import Signatures
46

57
from system.localization import locale
68

79

8-
def write_sc(output_filename: str, buffer: bytes, use_lzham: bool):
10+
def write_sc(output_filename: str | os.PathLike, buffer: bytes, use_lzham: bool):
911
with open(output_filename, "wb") as file_out:
1012
logger.info(locale.header_done)
1113

@@ -21,6 +23,7 @@ def write_sc(output_filename: str, buffer: bytes, use_lzham: bool):
2123
compressed = compress(buffer, Signatures.SC, 3)
2224
file_out.write(compressed)
2325
logger.info(locale.compression_done)
26+
print()
2427

2528

2629
def open_sc(input_filename: str) -> tuple[bytes, bool]:

system/lib/features/place_sprites.py

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
import os
2-
from typing import List, Tuple
2+
from pathlib import Path
3+
from typing import List
34

45
from PIL import Image, ImageDraw
56

67
from system.lib import Console
78
from system.lib.helper import get_sides, get_size
89
from system.lib.images import get_format_by_pixel_type
9-
from system.lib.xcod import FileInfo, parse_info
10+
from system.lib.xcod import FileInfo
1011
from system.localization import locale
1112

13+
MASK_COLOR = 255
1214

13-
def place_sprites(
14-
xcod_path: str, folder: str, overwrite: bool = False
15-
) -> Tuple[List[Image.Image], FileInfo]:
16-
file_info, xcod = parse_info(xcod_path)
1715

18-
files_to_overwrite = os.listdir(f'{folder}{"/overwrite" if overwrite else ""}')
19-
texture_files = os.listdir(f"{folder}/textures")
16+
def place_sprites(
17+
file_info: FileInfo, folder: Path, overwrite: bool = False
18+
) -> List[Image.Image]:
19+
files_to_overwrite = os.listdir(folder / ("overwrite" if overwrite else ""))
20+
texture_files = os.listdir(folder / "textures")
2021

2122
sheets = []
2223
for i in range(len(file_info.sheets)):
@@ -30,74 +31,68 @@ def place_sprites(
3031
)
3132
)
3233

33-
shapes_count = xcod.read_ushort()
34-
for shape_index in range(shapes_count):
34+
shapes_count = len(file_info.shapes)
35+
for shape_index, shape_info in enumerate(file_info.shapes):
3536
Console.progress_bar(
3637
locale.place_sprites_process % (shape_index + 1, shapes_count),
3738
shape_index,
3839
shapes_count,
3940
)
40-
shape_id = xcod.read_ushort()
41-
42-
regions_count = xcod.read_ushort()
43-
for region_index in range(regions_count):
44-
texture_id, points_count = xcod.read_uchar(), xcod.read_uchar()
45-
texture_width, texture_height = (
46-
sheets[texture_id].width,
47-
sheets[texture_id].height,
41+
42+
for region_index, region_info in enumerate(shape_info.regions):
43+
texture_size = (
44+
sheets[region_info.texture_id].width,
45+
sheets[region_info.texture_id].height,
4846
)
49-
points = [
50-
(xcod.read_ushort(), xcod.read_ushort()) for _ in range(points_count)
51-
]
52-
mirroring, rotation = xcod.read_uchar() == 1, xcod.read_char() * 90
5347

54-
filename = f"shape_{shape_id}_{region_index}.png"
48+
filename = f"shape_{shape_info.id}_{region_index}.png"
5549
if filename not in files_to_overwrite:
5650
continue
5751

58-
img_mask = Image.new("L", (texture_width, texture_height), 0)
59-
color = 255
60-
ImageDraw.Draw(img_mask).polygon(points, fill=color)
52+
img_mask = Image.new("L", texture_size, 0)
53+
ImageDraw.Draw(img_mask).polygon(region_info.points, fill=MASK_COLOR)
6154
bbox = img_mask.getbbox()
6255

6356
if not bbox:
64-
min_x = min(i[0] for i in points)
65-
min_y = min(i[1] for i in points)
66-
max_x = max(i[0] for i in points)
67-
max_y = max(i[1] for i in points)
57+
min_x = min(i[0] for i in region_info.points)
58+
min_y = min(i[1] for i in region_info.points)
59+
max_x = max(i[0] for i in region_info.points)
60+
max_y = max(i[1] for i in region_info.points)
6861

6962
if max_y - min_y != 0:
7063
for _y in range(max_y - min_y):
71-
img_mask.putpixel((max_x - 1, min_y + _y - 1), color)
64+
img_mask.putpixel((max_x - 1, min_y + _y - 1), MASK_COLOR)
7265

7366
elif max_x - min_x != 0:
7467
for _x in range(max_x - min_x):
75-
img_mask.putpixel((min_x + _x - 1, max_y - 1), color)
68+
img_mask.putpixel((min_x + _x - 1, max_y - 1), MASK_COLOR)
7669
else:
77-
img_mask.putpixel((max_x - 1, max_y - 1), color)
70+
img_mask.putpixel((max_x - 1, max_y - 1), MASK_COLOR)
7871

79-
left, top, right, bottom = get_sides(points)
72+
left, top, right, bottom = get_sides(region_info.points)
8073
if left == right:
8174
right += 1
8275
if top == bottom:
8376
bottom += 1
8477

8578
width, height = get_size(left, top, right, bottom)
79+
left = int(left)
80+
top = int(top)
8681

8782
bbox = int(left), int(top), int(right), int(bottom)
8883

8984
tmp_region = Image.open(
9085
f'{folder}{"/overwrite" if overwrite else ""}/{filename}'
9186
).convert("RGBA")
92-
if mirroring:
87+
if region_info.is_mirrored:
9388
tmp_region = tmp_region.transpose(Image.FLIP_LEFT_RIGHT)
94-
tmp_region = tmp_region.rotate(rotation, expand=True)
89+
tmp_region = tmp_region.rotate(region_info.rotation, expand=True)
9590
tmp_region = tmp_region.resize((width, height), Image.ANTIALIAS)
9691

97-
sheets[texture_id].paste(
92+
sheets[region_info.texture_id].paste(
9893
Image.new("RGBA", (width, height)), (left, top), img_mask.crop(bbox)
9994
)
100-
sheets[texture_id].paste(tmp_region, (left, top), tmp_region)
95+
sheets[region_info.texture_id].paste(tmp_region, (left, top), tmp_region)
10196
print()
10297

103-
return sheets, file_info
98+
return sheets

system/lib/features/sc/__init__.py

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import os
21
import struct
3-
from typing import List, Optional
2+
from pathlib import Path
3+
from typing import List
44

55
from loguru import logger
66
from PIL import Image
@@ -14,57 +14,46 @@
1414

1515

1616
def compile_sc(
17-
_dir,
17+
output_folder: Path,
1818
file_info: FileInfo,
19-
sheets: Optional[List[Image.Image]] = None,
20-
output_folder: Optional[str] = None,
19+
sheets: List[Image.Image],
2120
):
22-
name = _dir.split("/")[-2]
23-
24-
if sheets:
25-
files = sheets
26-
else:
27-
files = []
28-
[files.append(i) if i.endswith(".png") else None for i in os.listdir(_dir)]
29-
files.sort()
30-
if not files:
31-
return logger.info(locale.dir_empty % _dir.split("/")[-2])
32-
files = [Image.open(f"{_dir}{i}") for i in files]
33-
3421
sc = Writer()
3522

36-
for picture_index in range(len(files)):
23+
for picture_index in range(len(sheets)):
3724
sheet_info = file_info.sheets[picture_index]
38-
img = files[picture_index]
25+
sheet = sheets[picture_index]
3926

4027
file_type = sheet_info.file_type
4128
pixel_type = sheet_info.pixel_type
4229

43-
if img.size != sheet_info.size:
30+
if sheet.size != sheet_info.size:
4431
logger.info(
4532
locale.illegal_size
46-
% (sheet_info.width, sheet_info.height, img.width, img.height)
33+
% (sheet_info.width, sheet_info.height, sheet.width, sheet.height)
4734
)
4835

4936
if Console.question(locale.resize_qu):
5037
logger.info(locale.resizing)
51-
img = img.resize(sheet_info.size, Image.ANTIALIAS)
38+
sheet = sheet.resize(sheet_info.size, Image.ANTIALIAS)
5239

53-
width, height = img.size
40+
width, height = sheet.size
5441
pixel_size = get_pixel_size(pixel_type)
5542

5643
file_size = width * height * pixel_size + 5
5744

58-
logger.info(locale.about_sc % (name, picture_index, pixel_type, width, height))
45+
logger.info(
46+
locale.about_sc % (file_info.name, picture_index, pixel_type, width, height)
47+
)
5948

6049
sc.write(struct.pack("<BIBHH", file_type, file_size, pixel_type, width, height))
6150

6251
if file_type in (27, 28):
63-
split_image(img)
52+
split_image(sheet)
6453

65-
save_texture(sc, img, pixel_type)
54+
save_texture(sc, sheet, pixel_type)
6655
print()
6756

6857
sc.write(bytes(5))
6958

70-
write_sc(f"{output_folder}/{name}.sc", sc.getvalue(), file_info.use_lzham)
59+
write_sc(output_folder / f"{file_info.name}.sc", sc.getvalue(), file_info.use_lzham)

system/lib/features/sc/assembly_encode.py

Lines changed: 0 additions & 35 deletions
This file was deleted.

system/lib/features/sc/decode.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
from system.lib.swf import SupercellSWF
99
from system.localization import locale
1010

11+
IN_COMPRESSED_PATH = Path("./SC/In-Compressed")
12+
OUT_DECOMPRESSED = Path("./SC/Out-Decompressed")
13+
OUT_SPRITES_PATH = Path("./SC/Out-Sprites")
14+
1115

1216
def decode_textures_only():
13-
input_folder = Path("./SC/In-Compressed")
14-
output_folder = Path("./SC/Out-Decompressed")
17+
input_folder = IN_COMPRESSED_PATH
18+
output_folder = OUT_DECOMPRESSED
1519

1620
files = os.listdir(input_folder)
1721
for file in files:
@@ -50,8 +54,8 @@ def decode_textures_only():
5054

5155

5256
def decode_and_render_objects():
53-
input_folder = Path("./SC/In-Compressed")
54-
output_folder = Path("./SC/Out-Sprites")
57+
input_folder = IN_COMPRESSED_PATH
58+
output_folder = OUT_SPRITES_PATH
5559
files = os.listdir(input_folder)
5660

5761
for file in files:
@@ -62,7 +66,7 @@ def decode_and_render_objects():
6266
base_name = os.path.basename(file).rsplit(".", 1)[0]
6367

6468
swf = SupercellSWF()
65-
texture_loaded, use_lzham = swf.load(f"{input_folder}/{file}")
69+
texture_loaded, use_lzham = swf.load(input_folder / file)
6670
if not texture_loaded:
6771
logger.error(locale.not_found % f"{base_name}_tex.sc")
6872
continue
@@ -105,13 +109,13 @@ def _save_textures(swf: SupercellSWF, textures_output: Path, base_name: str) ->
105109
os.makedirs(textures_output, exist_ok=True)
106110
for img_index in range(len(swf.textures)):
107111
filename = base_name + "_" * img_index
108-
swf.textures[img_index].image.save(f"{textures_output / filename}.png")
112+
swf.textures[img_index].image.save(textures_output / f"{filename}.png")
109113

110114

111115
def _save_meta_file(
112116
swf: SupercellSWF, objects_output_folder: Path, base_name: str, use_lzham: bool
113117
) -> None:
114-
with open(f"{objects_output_folder/base_name}.xcod", "wb") as xcod_file:
118+
with open(objects_output_folder / f"{base_name}.xcod", "wb") as xcod_file:
115119
xcod_file.write(b"XCOD")
116120
xcod_file.write(bool.to_bytes(use_lzham, 1, "big"))
117121
xcod_file.write(int.to_bytes(len(swf.textures), 1, "big"))

0 commit comments

Comments
 (0)