diff --git a/Pack/MKWFaraphel/essentials/_PREPATCH/files/thp/video.thp.json b/Pack/MKWFaraphel/essentials/_PREPATCH/files/thp/video.thp.json index 7814605..2ca454a 100644 --- a/Pack/MKWFaraphel/essentials/_PREPATCH/files/thp/video.thp.json +++ b/Pack/MKWFaraphel/essentials/_PREPATCH/files/thp/video.thp.json @@ -1,4 +1,4 @@ { - "mode": "match", + "mode": "match-copy", "match_regex": "*/*.thp" } \ No newline at end of file diff --git a/Pack/MKWFaraphel/szstest/_PATCH/files/Race/Course/track.szs b/Pack/MKWFaraphel/szstest/_PATCH/files/Race/Course/track.szs new file mode 100644 index 0000000..e69de29 diff --git a/Pack/MKWFaraphel/szstest/_PATCH/files/Race/Course/track.szs.json b/Pack/MKWFaraphel/szstest/_PATCH/files/Race/Course/track.szs.json new file mode 100644 index 0000000..63b7bf6 --- /dev/null +++ b/Pack/MKWFaraphel/szstest/_PATCH/files/Race/Course/track.szs.json @@ -0,0 +1,12 @@ +{ + "mode": "match-edit", + "match_regex": "*.szs", + + "operation": { + "szs-edit": { + "scale": {"x": 2, "y": 2, "z": 2}, + "speed": 1.5, + "laps": 9 + } + } +} \ No newline at end of file diff --git a/source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py b/source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py index e95381b..0381e1f 100644 --- a/source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py +++ b/source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py @@ -23,6 +23,7 @@ class AbstractLayer(ABC): """ Patch a bmg with the actual layer. Return the new bmg content. """ + ... @classmethod def get(cls, layer: dict) -> "AbstractLayer": diff --git a/source/mkw/Patch/PatchOperation/ImageEditor/__init__.py b/source/mkw/Patch/PatchOperation/ImageEditor/__init__.py index 56b703a..263ba7f 100644 --- a/source/mkw/Patch/PatchOperation/ImageEditor/__init__.py +++ b/source/mkw/Patch/PatchOperation/ImageEditor/__init__.py @@ -65,6 +65,7 @@ class AbstractLayer(ABC): """ Patch an image with the actual layer. Return the new image. """ + ... @classmethod def get(cls, layer: dict) -> "AbstractLayer": diff --git a/source/mkw/Patch/PatchOperation/SzsEditor.py b/source/mkw/Patch/PatchOperation/SzsEditor.py new file mode 100644 index 0000000..2583ff3 --- /dev/null +++ b/source/mkw/Patch/PatchOperation/SzsEditor.py @@ -0,0 +1,39 @@ +from io import BytesIO +from typing import IO, TYPE_CHECKING + +from source.mkw.Patch.PatchOperation import AbstractPatchOperation +from source.wt import szs + +if TYPE_CHECKING: + from source.mkw.Patch import Patch + + +class SzsEditor(AbstractPatchOperation): + """ + patch a track szs file + """ + + type = "szs-edit" + + def __init__(self, scale: dict[str, int] = None, shift: dict[str, int] = None, rotation: dict[str, int] = None, + translate: dict[str, int] = None, speed: str = None, laps: str = None): + self.scale = scale # example : {"x": 1, "y": 1, "z": 1} + self.shift = shift + self.rotation = rotation + self.translate = translate + + self.speed = float(speed) + self.laps = int(laps) + + def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO): + patched_content = BytesIO(szs.patch( + file_content.read(), + scale=self.scale, + shift=self.shift, + rotation=self.rotation, + translate=self.translate, + speed=self.speed, + laps=self.laps, + )) + + return file_name, patched_content diff --git a/source/mkw/Patch/PatchOperation/__init__.py b/source/mkw/Patch/PatchOperation/__init__.py index a5ab7fe..fc13f66 100644 --- a/source/mkw/Patch/PatchOperation/__init__.py +++ b/source/mkw/Patch/PatchOperation/__init__.py @@ -39,5 +39,5 @@ class AbstractPatchOperation(ABC): # load all the subclass of AbstractPatchOperation to that __subclasses__ can filter them from source.mkw.Patch.PatchOperation import ( ImageDecoder, ImageEncoder, Rename, Special, StrEditor, - BmgTxtEditor, ImageEditor, BmgEncoder, BmgDecoder + BmgTxtEditor, ImageEditor, BmgEncoder, BmgDecoder, SzsEditor ) diff --git a/source/wt/szs.py b/source/wt/szs.py index d884f9b..fc19695 100644 --- a/source/wt/szs.py +++ b/source/wt/szs.py @@ -6,6 +6,7 @@ tools_path = tools_szs_dir / "wszst" _tools_run = get_tools_run_function(tools_path) _tools_run_dict = get_tools_run_dict_function(tools_path) +_tools_run_popen = get_tools_run_popen_function(tools_path) @better_wt_error(tools_path) @@ -40,6 +41,31 @@ def create(extracted_szs: Path | str, dest: Path | str, overwrite: bool = False) return SZSPath(dest) +def patch(szs_data: bytes, scale: dict[str, int] = None, shift: dict[str, int] = None, rotation: dict[str, int] = None, + translate: dict[str, int] = None, speed: float = None, laps: int = None): + """ + Patch a szs file (especially track file) + :return: the patched szs file + """ + + args = [] + if scale is not None: args.append(f"--scale={scale.get('x', 1)},{scale.get('y', 1)},{scale.get('z', 1)}") + if shift is not None: args.append(f"--shift={shift.get('x', 0)},{scale.get('y', 0)},{scale.get('z', 0)}") + if rotation is not None: args.append(f"--rot={rotation.get('x', 0)},{rotation.get('y', 0)},{rotation.get('z', 0)}") + if translate is not None: args.append( + f"--translate={translate.get('x', 0)},{translate.get('y', 0)},{translate.get('z', 0)}" + ) + if speed is not None: args.append(f"--speed-mod={speed}") + if laps is not None: args.append(f"--kmp={laps}LAPS") + + process = _tools_run_popen("PATCH", "-", *args, "--DEST", "-") + stdout, _ = process.communicate(input=szs_data) + if process.returncode != 0: + raise WTError(tools_path, process.returncode) + + return stdout + + class SZSPath: __slots__ = ("path", "_analyze")