Skip to content

Commit

Permalink
Merge pull request #20 from xcoder-tool/khronos-texture-tags
Browse files Browse the repository at this point in the history
feat(tags): support for new texture and movie clip tags
  • Loading branch information
danila-schelkov authored Aug 12, 2024
2 parents d64e1f7 + 6cc21ef commit ab416fe
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 19 deletions.
6 changes: 3 additions & 3 deletions system/lib/features/sc/decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def decode_and_render_objects():
files = os.listdir(input_folder)

for file in files:
if file.endswith("_tex.sc"):
if file.endswith("_tex.sc") or not file.endswith(".sc"):
continue

try:
Expand Down Expand Up @@ -99,9 +99,9 @@ def get_file_basename(swf: SupercellSWF):

def _create_objects_output_folder(output_folder: Path, base_name: str) -> Path:
objects_output_folder = output_folder / base_name
if os.path.isdir(objects_output_folder):
if objects_output_folder.exists():
shutil.rmtree(objects_output_folder)
os.mkdir(objects_output_folder)
objects_output_folder.mkdir(parents=True)
return objects_output_folder


Expand Down
5 changes: 4 additions & 1 deletion system/lib/objects/movie_clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ def load(self, swf: "SupercellSWF", tag: int):
if tag in (3, 14):
pass
else:
if tag == 49:
swf.reader.read_char() # unknown

transforms_count = swf.reader.read_uint()

for i in range(transforms_count):
Expand All @@ -79,7 +82,7 @@ def load(self, swf: "SupercellSWF", tag: int):
bind_id = swf.reader.read_ushort() # bind_id
self.binds.append(bind_id)

if tag in (12, 35):
if tag in (12, 35, 49):
for i in range(binds_count):
blend = swf.reader.read_char() # blend
self.blends.append(blend)
Expand Down
22 changes: 20 additions & 2 deletions system/lib/objects/texture.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from __future__ import annotations

import os
from typing import TYPE_CHECKING

import zstandard
from PIL import Image

from system.lib.images import (
Expand All @@ -10,19 +14,25 @@
)
from system.lib.pvr_tex_tool import get_image_from_ktx_data

if TYPE_CHECKING:
from system.lib.swf import SupercellSWF


class SWFTexture:
def __init__(self):
self.width = 0
self.height = 0

self.pixel_type = -1
self.khronos_texture_filename: str | None = None

self.image: Image.Image
self.image: Image.Image | None = None

def load(self, swf, tag: int, has_texture: bool):
def load(self, swf: SupercellSWF, tag: int, has_texture: bool):
if tag == 45:
khronos_texture_length = swf.reader.read_int()
elif tag == 47:
self.khronos_texture_filename = swf.reader.read_string()

self.pixel_type = swf.reader.read_char()
self.width, self.height = (swf.reader.read_ushort(), swf.reader.read_ushort())
Expand All @@ -35,6 +45,14 @@ def load(self, swf, tag: int, has_texture: bool):
khronos_texture_data = swf.reader.read(khronos_texture_length)
self.image = get_image_from_ktx_data(khronos_texture_data)
return
elif tag == 47:
with open(
swf.filepath.parent / self.khronos_texture_filename, "rb"
) as file:
decompressor = zstandard.ZstdDecompressor()
decompressed = decompressor.decompress(file.read())
self.image = get_image_from_ktx_data(decompressed)
return

img = Image.new(
get_format_by_pixel_type(self.pixel_type), (self.width, self.height)
Expand Down
33 changes: 20 additions & 13 deletions system/lib/swf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from pathlib import Path
from typing import List, Tuple

from loguru import logger
Expand All @@ -14,15 +15,15 @@


class SupercellSWF:
TEXTURES_TAGS = (1, 16, 28, 29, 34, 19, 24, 27, 45)
TEXTURES_TAGS = (1, 16, 28, 29, 34, 19, 24, 27, 45, 47)
SHAPES_TAGS = (2, 18)
MOVIE_CLIPS_TAGS = (3, 10, 12, 14, 35)
MOVIE_CLIPS_TAGS = (3, 10, 12, 14, 35, 49)

TEXTURE_EXTENSION = "_tex.sc"

def __init__(self):
self.filename: str
self.reader: Reader
self.filename: str | None = None
self.reader: Reader | None = None

self.use_lowres_texture: bool = False

Expand All @@ -32,8 +33,8 @@ def __init__(self):

self.xcod_writer = Writer("big")

self._filepath: str
self._uncommon_texture_path: str
self._filepath: Path | None = None
self._uncommon_texture_path: str | os.PathLike | None = None

self._lowres_suffix: str = DEFAULT_LOWRES_SUFFIX
self._highres_suffix: str = DEFAULT_HIGHRES_SUFFIX
Expand All @@ -50,13 +51,13 @@ def __init__(self):
self._export_names: List[str] = []

self._matrix_banks: List[MatrixBank] = []
self._matrix_bank: MatrixBank
self._matrix_bank: MatrixBank | None = None

def load(self, filepath: str | os.PathLike) -> Tuple[bool, bool]:
self._filepath = str(filepath)
self._filepath = Path(filepath)

texture_loaded, use_lzham = self._load_internal(
self._filepath, self._filepath.endswith("_tex.sc")
self._filepath, self._filepath.name.endswith("_tex.sc")
)

if not texture_loaded:
Expand All @@ -65,12 +66,14 @@ def load(self, filepath: str | os.PathLike) -> Tuple[bool, bool]:
self._uncommon_texture_path, True
)
else:
texture_path = self._filepath[:-3] + SupercellSWF.TEXTURE_EXTENSION
texture_path = str(self._filepath)[:-3] + SupercellSWF.TEXTURE_EXTENSION
texture_loaded, use_lzham = self._load_internal(texture_path, True)

return texture_loaded, use_lzham

def _load_internal(self, filepath: str, is_texture_file: bool) -> Tuple[bool, bool]:
def _load_internal(
self, filepath: str | os.PathLike, is_texture_file: bool
) -> Tuple[bool, bool]:
self.filename = os.path.basename(filepath)

logger.info(locale.collecting_inf % self.filename)
Expand Down Expand Up @@ -180,12 +183,12 @@ def _load_tags(self, is_texture_file: bool) -> bool:
elif tag == 30:
self._use_uncommon_texture = True
highres_texture_path = (
self._filepath[:-3]
str(self._filepath)[:-3]
+ self._highres_suffix
+ SupercellSWF.TEXTURE_EXTENSION
)
lowres_texture_path = (
self._filepath[:-3]
str(self._filepath)[:-3]
+ self._lowres_suffix
+ SupercellSWF.TEXTURE_EXTENSION
)
Expand Down Expand Up @@ -231,3 +234,7 @@ def get_display_object(

def get_matrix_bank(self, index: int) -> MatrixBank:
return self._matrix_banks[index]

@property
def filepath(self) -> Path:
return self._filepath

0 comments on commit ab416fe

Please sign in to comment.