Skip to content

Commit

Permalink
refactor: the encode methods functions are refactored, metadata parsi…
Browse files Browse the repository at this point in the history
…ng is refactored, menu refilling is now more correct
  • Loading branch information
danila-schelkov committed Apr 16, 2023
1 parent 766514c commit 85047da
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 159 deletions.
6 changes: 6 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[flake8]
max-line-length = 88
ignore = E203, W503
exclude =
updates
venv
24 changes: 13 additions & 11 deletions system/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,27 @@ def refill_menu():
import sc_compression

del sc_compression

except ImportError:
logger.warning(locale.install_to_unlock % "sc-compression")
else:
from system.lib.features.csv.compress import compress_csv
from system.lib.features.csv.decompress import decompress_csv

try:
import PIL

del PIL

from system.lib.features.sc.assembly_encode import (
collect_objects_and_encode,
)
except ImportError:
logger.warning(locale.install_to_unlock % "PILLOW")
else:
from system.lib.features.sc.decode import (
decode_and_render_objects,
decode_textures_only,
)
from system.lib.features.sc.encode import sc_encode
from system.lib.features.sc.encode import (
collect_objects_and_encode,
encode_textures_only,
)

sc_category = Menu.Category(0, locale.sc_label)
sc_category.add(
Expand All @@ -89,7 +93,9 @@ def refill_menu():
)
)
sc_category.add(
Menu.Item(locale.encode_sc, locale.encode_sc_description, sc_encode)
Menu.Item(
locale.encode_sc, locale.encode_sc_description, encode_textures_only
)
)
sc_category.add(
Menu.Item(
Expand All @@ -113,8 +119,6 @@ def refill_menu():
)
)
menu.add_category(sc_category)
except ImportError:
logger.warning(locale.install_to_unlock % "PILLOW")

csv_category = Menu.Category(1, locale.csv_label)
csv_category.add(
Expand All @@ -128,8 +132,6 @@ def refill_menu():
)
)
menu.add_category(csv_category)
except ImportError:
logger.warning(locale.install_to_unlock % "sc-compression")

other = Menu.Category(10, locale.other_features_label)
other.add(
Expand Down
5 changes: 4 additions & 1 deletion system/lib/features/files.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os

from loguru import logger
from sc_compression import compress, decompress
from sc_compression.signatures import Signatures

from system.localization import locale


def write_sc(output_filename: str, buffer: bytes, use_lzham: bool):
def write_sc(output_filename: str | os.PathLike, buffer: bytes, use_lzham: bool):
with open(output_filename, "wb") as file_out:
logger.info(locale.header_done)

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


def open_sc(input_filename: str) -> tuple[bytes, bool]:
Expand Down
73 changes: 34 additions & 39 deletions system/lib/features/place_sprites.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import os
from typing import List, Tuple
from pathlib import Path
from typing import List

from PIL import Image, ImageDraw

from system.lib import Console
from system.lib.helper import get_sides, get_size
from system.lib.images import get_format_by_pixel_type
from system.lib.xcod import FileInfo, parse_info
from system.lib.xcod import FileInfo
from system.localization import locale

MASK_COLOR = 255

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

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

sheets = []
for i in range(len(file_info.sheets)):
Expand All @@ -30,74 +31,68 @@ def place_sprites(
)
)

shapes_count = xcod.read_ushort()
for shape_index in range(shapes_count):
shapes_count = len(file_info.shapes)
for shape_index, shape_info in enumerate(file_info.shapes):
Console.progress_bar(
locale.place_sprites_process % (shape_index + 1, shapes_count),
shape_index,
shapes_count,
)
shape_id = xcod.read_ushort()

regions_count = xcod.read_ushort()
for region_index in range(regions_count):
texture_id, points_count = xcod.read_uchar(), xcod.read_uchar()
texture_width, texture_height = (
sheets[texture_id].width,
sheets[texture_id].height,

for region_index, region_info in enumerate(shape_info.regions):
texture_size = (
sheets[region_info.texture_id].width,
sheets[region_info.texture_id].height,
)
points = [
(xcod.read_ushort(), xcod.read_ushort()) for _ in range(points_count)
]
mirroring, rotation = xcod.read_uchar() == 1, xcod.read_char() * 90

filename = f"shape_{shape_id}_{region_index}.png"
filename = f"shape_{shape_info.id}_{region_index}.png"
if filename not in files_to_overwrite:
continue

img_mask = Image.new("L", (texture_width, texture_height), 0)
color = 255
ImageDraw.Draw(img_mask).polygon(points, fill=color)
img_mask = Image.new("L", texture_size, 0)
ImageDraw.Draw(img_mask).polygon(region_info.points, fill=MASK_COLOR)
bbox = img_mask.getbbox()

if not bbox:
min_x = min(i[0] for i in points)
min_y = min(i[1] for i in points)
max_x = max(i[0] for i in points)
max_y = max(i[1] for i in points)
min_x = min(i[0] for i in region_info.points)
min_y = min(i[1] for i in region_info.points)
max_x = max(i[0] for i in region_info.points)
max_y = max(i[1] for i in region_info.points)

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

elif max_x - min_x != 0:
for _x in range(max_x - min_x):
img_mask.putpixel((min_x + _x - 1, max_y - 1), color)
img_mask.putpixel((min_x + _x - 1, max_y - 1), MASK_COLOR)
else:
img_mask.putpixel((max_x - 1, max_y - 1), color)
img_mask.putpixel((max_x - 1, max_y - 1), MASK_COLOR)

left, top, right, bottom = get_sides(points)
left, top, right, bottom = get_sides(region_info.points)
if left == right:
right += 1
if top == bottom:
bottom += 1

width, height = get_size(left, top, right, bottom)
left = int(left)
top = int(top)

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

tmp_region = Image.open(
f'{folder}{"/overwrite" if overwrite else ""}/{filename}'
).convert("RGBA")
if mirroring:
if region_info.is_mirrored:
tmp_region = tmp_region.transpose(Image.FLIP_LEFT_RIGHT)
tmp_region = tmp_region.rotate(rotation, expand=True)
tmp_region = tmp_region.rotate(region_info.rotation, expand=True)
tmp_region = tmp_region.resize((width, height), Image.ANTIALIAS)

sheets[texture_id].paste(
sheets[region_info.texture_id].paste(
Image.new("RGBA", (width, height)), (left, top), img_mask.crop(bbox)
)
sheets[texture_id].paste(tmp_region, (left, top), tmp_region)
sheets[region_info.texture_id].paste(tmp_region, (left, top), tmp_region)
print()

return sheets, file_info
return sheets
43 changes: 16 additions & 27 deletions system/lib/features/sc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
import struct
from typing import List, Optional
from pathlib import Path
from typing import List

from loguru import logger
from PIL import Image
Expand All @@ -14,57 +14,46 @@


def compile_sc(
_dir,
output_folder: Path,
file_info: FileInfo,
sheets: Optional[List[Image.Image]] = None,
output_folder: Optional[str] = None,
sheets: List[Image.Image],
):
name = _dir.split("/")[-2]

if sheets:
files = sheets
else:
files = []
[files.append(i) if i.endswith(".png") else None for i in os.listdir(_dir)]
files.sort()
if not files:
return logger.info(locale.dir_empty % _dir.split("/")[-2])
files = [Image.open(f"{_dir}{i}") for i in files]

sc = Writer()

for picture_index in range(len(files)):
for picture_index in range(len(sheets)):
sheet_info = file_info.sheets[picture_index]
img = files[picture_index]
sheet = sheets[picture_index]

file_type = sheet_info.file_type
pixel_type = sheet_info.pixel_type

if img.size != sheet_info.size:
if sheet.size != sheet_info.size:
logger.info(
locale.illegal_size
% (sheet_info.width, sheet_info.height, img.width, img.height)
% (sheet_info.width, sheet_info.height, sheet.width, sheet.height)
)

if Console.question(locale.resize_qu):
logger.info(locale.resizing)
img = img.resize(sheet_info.size, Image.ANTIALIAS)
sheet = sheet.resize(sheet_info.size, Image.ANTIALIAS)

width, height = img.size
width, height = sheet.size
pixel_size = get_pixel_size(pixel_type)

file_size = width * height * pixel_size + 5

logger.info(locale.about_sc % (name, picture_index, pixel_type, width, height))
logger.info(
locale.about_sc % (file_info.name, picture_index, pixel_type, width, height)
)

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

if file_type in (27, 28):
split_image(img)
split_image(sheet)

save_texture(sc, img, pixel_type)
save_texture(sc, sheet, pixel_type)
print()

sc.write(bytes(5))

write_sc(f"{output_folder}/{name}.sc", sc.getvalue(), file_info.use_lzham)
write_sc(output_folder / f"{file_info.name}.sc", sc.getvalue(), file_info.use_lzham)
35 changes: 0 additions & 35 deletions system/lib/features/sc/assembly_encode.py

This file was deleted.

18 changes: 11 additions & 7 deletions system/lib/features/sc/decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
from system.lib.swf import SupercellSWF
from system.localization import locale

IN_COMPRESSED_PATH = Path("./SC/In-Compressed")
OUT_DECOMPRESSED = Path("./SC/Out-Decompressed")
OUT_SPRITES_PATH = Path("./SC/Out-Sprites")


def decode_textures_only():
input_folder = Path("./SC/In-Compressed")
output_folder = Path("./SC/Out-Decompressed")
input_folder = IN_COMPRESSED_PATH
output_folder = OUT_DECOMPRESSED

files = os.listdir(input_folder)
for file in files:
Expand Down Expand Up @@ -50,8 +54,8 @@ def decode_textures_only():


def decode_and_render_objects():
input_folder = Path("./SC/In-Compressed")
output_folder = Path("./SC/Out-Sprites")
input_folder = IN_COMPRESSED_PATH
output_folder = OUT_SPRITES_PATH
files = os.listdir(input_folder)

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

swf = SupercellSWF()
texture_loaded, use_lzham = swf.load(f"{input_folder}/{file}")
texture_loaded, use_lzham = swf.load(input_folder / file)
if not texture_loaded:
logger.error(locale.not_found % f"{base_name}_tex.sc")
continue
Expand Down Expand Up @@ -105,13 +109,13 @@ def _save_textures(swf: SupercellSWF, textures_output: Path, base_name: str) ->
os.makedirs(textures_output, exist_ok=True)
for img_index in range(len(swf.textures)):
filename = base_name + "_" * img_index
swf.textures[img_index].image.save(f"{textures_output / filename}.png")
swf.textures[img_index].image.save(textures_output / f"{filename}.png")


def _save_meta_file(
swf: SupercellSWF, objects_output_folder: Path, base_name: str, use_lzham: bool
) -> None:
with open(f"{objects_output_folder/base_name}.xcod", "wb") as xcod_file:
with open(objects_output_folder / f"{base_name}.xcod", "wb") as xcod_file:
xcod_file.write(b"XCOD")
xcod_file.write(bool.to_bytes(use_lzham, 1, "big"))
xcod_file.write(int.to_bytes(len(swf.textures), 1, "big"))
Expand Down
Loading

0 comments on commit 85047da

Please sign in to comment.