mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-02 02:38:30 +02:00
module filtering subclasses have been simplified to made the code easier to read with less directory inside other useless directory and comment have been added
This commit is contained in:
parent
547e9108da
commit
59106d8ed9
30 changed files with 223 additions and 223 deletions
|
@ -1,7 +1,6 @@
|
|||
import tkinter
|
||||
from tkinter import ttk
|
||||
from source.translation import translate as _
|
||||
from source.gui.preview import track_formatting
|
||||
|
||||
|
||||
ModConfig: any
|
||||
|
|
|
@ -23,15 +23,15 @@ class AbstractPreviewWindow(tkinter.Toplevel, ABC):
|
|||
super().__init__()
|
||||
...
|
||||
|
||||
|
||||
def get_preview_window_class(name: str) -> Type[AbstractPreviewWindow]:
|
||||
@classmethod
|
||||
def get(cls, name: str) -> Type["AbstractPreviewWindow"]:
|
||||
"""
|
||||
Return the windows class object from its name
|
||||
:param name: name of the window class
|
||||
:return: the window class object
|
||||
"""
|
||||
for window_class in filter(lambda cls: cls.name == name, AbstractPreviewWindow.__subclasses__()):
|
||||
return window_class
|
||||
for subclass in filter(lambda subclass: subclass.name == name, cls.__subclasses__()):
|
||||
return subclass
|
||||
raise InvalidPreviewWindowName(name)
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from source import threaded
|
|||
from source.mkw import Tag
|
||||
from source.mkw.Cup import Cup
|
||||
from source.mkw.MKWColor import bmg_color_text
|
||||
from source.mkw.ModSettings import ModSettings
|
||||
from source.mkw.ModSettings import AbstractModSettings
|
||||
from source.mkw.Track import Track
|
||||
import json
|
||||
|
||||
|
@ -65,8 +65,10 @@ class ModConfig:
|
|||
self.macros: dict = macros if macros is not None else {}
|
||||
self.messages: dict = messages if messages is not None else {}
|
||||
|
||||
self.global_settings: dict = ModSettings(global_settings)
|
||||
self.specific_settings: dict = ModSettings(specific_settings if specific_settings is not None else {})
|
||||
self.global_settings: dict = AbstractModSettings.get(global_settings)
|
||||
self.specific_settings: dict = AbstractModSettings.get(
|
||||
specific_settings if specific_settings is not None else {}
|
||||
)
|
||||
|
||||
self.name: str = name
|
||||
self.nickname: str = nickname if nickname is not None else name
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import tkinter
|
||||
from tkinter import ttk
|
||||
from source.mkw.ModSettings.TypeSettings import AbstractTypeSettings
|
||||
|
||||
from source.mkw.ModSettings import AbstractModSettings
|
||||
|
||||
|
||||
class Choices(AbstractTypeSettings):
|
||||
class Choices(AbstractModSettings):
|
||||
"""
|
||||
This setting type allow you to input a string text.
|
||||
You can optionally add a "preview" to allow the user to use a window to select the value.
|
|
@ -1,11 +1,11 @@
|
|||
import tkinter
|
||||
from tkinter import ttk
|
||||
|
||||
from source.mkw.ModSettings.TypeSettings import AbstractTypeSettings
|
||||
from source.gui.preview import get_preview_window_class
|
||||
from source.mkw.ModSettings import AbstractModSettings
|
||||
from source.gui.preview import AbstractPreviewWindow
|
||||
|
||||
|
||||
class String(AbstractTypeSettings):
|
||||
class String(AbstractModSettings):
|
||||
"""
|
||||
This setting type allow you to input a string text.
|
||||
You can optionally add a "preview" to allow the user to use a window to select the value.
|
||||
|
@ -30,7 +30,7 @@ class String(AbstractTypeSettings):
|
|||
if self.preview is not None:
|
||||
button = ttk.Button(
|
||||
master, text="...", width=3,
|
||||
command=lambda: get_preview_window_class(
|
||||
command=lambda: AbstractPreviewWindow.get(
|
||||
self.preview
|
||||
)(master.master.master.master.mod_config, value_variable)
|
||||
)
|
|
@ -1,31 +0,0 @@
|
|||
import tkinter
|
||||
from tkinter import ttk
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class AbstractTypeSettings(ABC):
|
||||
type: str # type name of the settings
|
||||
value: str # value for the settings
|
||||
enabled: bool # is the settings enabled
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, value: str = None, preview: str = None, enabled: bool = False):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def tkinter_show(self, master: ttk.LabelFrame, checkbox) -> None:
|
||||
"""
|
||||
Show the option inside a tkinter widget
|
||||
:master: master widget
|
||||
:checkbox: checkbox inside the labelframe allowing to enable or disable the setting
|
||||
"""
|
||||
master.grid_rowconfigure(1, weight=1)
|
||||
master.grid_columnconfigure(1, weight=1)
|
||||
|
||||
enabled_variable = tkinter.BooleanVar(master, value=self.enabled)
|
||||
enabled_variable.trace_add("write", lambda *_: setattr(self, "enabled", enabled_variable.get()))
|
||||
checkbox.configure(variable=enabled_variable)
|
||||
...
|
||||
|
||||
|
||||
from source.mkw.ModSettings.TypeSettings import String, Choices
|
|
@ -1,4 +1,6 @@
|
|||
from source.mkw.ModSettings.TypeSettings import AbstractTypeSettings
|
||||
import tkinter
|
||||
from tkinter import ttk
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class InvalidSettingsType(Exception):
|
||||
|
@ -6,21 +8,51 @@ class InvalidSettingsType(Exception):
|
|||
super().__init__(f"Error : Type of mod settings '{settings_type}' not found.")
|
||||
|
||||
|
||||
class ModSettings:
|
||||
def __new__(cls, settings_dict: dict) -> dict[str, AbstractTypeSettings]:
|
||||
class AbstractModSettings(ABC):
|
||||
"""
|
||||
Base class for every different type of ModSettings
|
||||
"""
|
||||
|
||||
type: str # type name of the settings
|
||||
value: str # value for the settings
|
||||
enabled: bool # is the settings enabled
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, value: str = None, preview: str = None, enabled: bool = False):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def tkinter_show(self, master: ttk.LabelFrame, checkbox) -> None:
|
||||
"""
|
||||
Show the option inside a tkinter widget
|
||||
:master: master widget
|
||||
:checkbox: checkbox inside the labelframe allowing to enable or disable the setting
|
||||
"""
|
||||
master.grid_rowconfigure(1, weight=1)
|
||||
master.grid_columnconfigure(1, weight=1)
|
||||
|
||||
enabled_variable = tkinter.BooleanVar(master, value=self.enabled)
|
||||
enabled_variable.trace_add("write", lambda *_: setattr(self, "enabled", enabled_variable.get()))
|
||||
checkbox.configure(variable=enabled_variable)
|
||||
...
|
||||
|
||||
@classmethod
|
||||
def get(cls, settings_dict: dict) -> dict[str, "AbstractModSettings"]:
|
||||
"""
|
||||
Load all the settings in mod_settings_dict
|
||||
:param settings_dict: dictionnary containing all the settings defined for the mod
|
||||
:param settings_dict: dictionary containing all the settings defined for the mod
|
||||
"""
|
||||
settings: dict[str, AbstractTypeSettings] = {}
|
||||
settings: dict[str, AbstractModSettings] = {}
|
||||
|
||||
for settings_name, settings_data in settings_dict.items():
|
||||
for subclass in filter(
|
||||
lambda subclass: subclass.type == settings_data["type"], AbstractTypeSettings.__subclasses__()
|
||||
):
|
||||
for subclass in filter(lambda subclass: subclass.type == settings_data["type"], cls.__subclasses__()):
|
||||
settings_data.pop("type")
|
||||
settings[settings_name] = subclass(**settings_data)
|
||||
break
|
||||
else: raise InvalidSettingsType(settings_name)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
# these import load the different ModSettings, and so get_mod_settings will be able to fetch them with __subclasses__
|
||||
from source.mkw.ModSettings import Choices, String
|
||||
|
|
|
@ -2,7 +2,7 @@ from io import BytesIO
|
|||
from typing import Generator, IO
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation import PatchOperation
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.mkw.Patch.PatchObject import PatchObject
|
||||
from source.wt.szs import SZSPath
|
||||
|
||||
|
@ -55,7 +55,7 @@ class PatchFile(PatchObject):
|
|||
for operation_name, operation in self.configuration.get("operation", {}).items():
|
||||
# process every operation and get the new patch_path (if the name is changed)
|
||||
# and the new content of the patch
|
||||
patch_name, patch_content = PatchOperation(operation_name)(**operation).patch(
|
||||
patch_name, patch_content = AbstractPatchOperation.get(operation_name)(**operation).patch(
|
||||
self.patch, patch_name, patch_content
|
||||
)
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.wt import bmg
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class BmgDecoder(AbstractOperation):
|
||||
class BmgDecoder(AbstractPatchOperation):
|
||||
"""
|
||||
decode a bmg file to a txt file
|
||||
"""
|
|
@ -1,13 +1,13 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.wt import bmg
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class BmgEncoder(AbstractOperation):
|
||||
class BmgEncoder(AbstractPatchOperation):
|
||||
"""
|
||||
encode a bmg file to a txt file
|
||||
"""
|
|
@ -1,6 +1,7 @@
|
|||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import AbstractLayer
|
||||
from source.wt import ctc
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import re
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import AbstractLayer
|
||||
from source.mkw.Track import Track
|
||||
from source.wt import bmg
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import AbstractLayer
|
||||
|
||||
|
||||
Patch: any
|
|
@ -1,6 +1,7 @@
|
|||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import AbstractLayer
|
||||
from source.wt import bmg
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import re
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import AbstractLayer
|
||||
|
||||
|
||||
Patch: any
|
62
source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py
Normal file
62
source/mkw/Patch/PatchOperation/BmgTxtEditor/__init__.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
|
||||
|
||||
Layer: any
|
||||
Patch: any
|
||||
|
||||
|
||||
class AbstractLayer(ABC):
|
||||
"""
|
||||
Represent a Layer for a bmgtxt patch
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def patch_bmg(self, patch: "Patch", decoded_content: str) -> str:
|
||||
"""
|
||||
Patch a bmg with the actual layer. Return the new bmg content.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get(cls, layer: dict) -> "Layer":
|
||||
"""
|
||||
return the correct type of layer corresponding to the layer mode
|
||||
:param layer: the layer to load
|
||||
"""
|
||||
for subclass in filter(lambda subclass: subclass.mode == layer["mode"], cls.__subclasses__()):
|
||||
layer.pop("mode")
|
||||
return subclass(**layer)
|
||||
raise InvalidBmgLayerMode(layer["mode"])
|
||||
|
||||
|
||||
class BmgTxtEditor(AbstractPatchOperation):
|
||||
"""
|
||||
edit a decoded bmg
|
||||
"""
|
||||
|
||||
type = "bmgtxt-edit"
|
||||
|
||||
def __init__(self, layers: list[dict]):
|
||||
"""
|
||||
:param layers: layers
|
||||
"""
|
||||
self.layers = layers
|
||||
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
decoded_content: str = file_content.read().decode("utf-8")
|
||||
|
||||
for layer in self.layers:
|
||||
decoded_content = AbstractLayer.get(layer).patch_bmg(patch, decoded_content)
|
||||
|
||||
patch_content: IO = BytesIO(decoded_content.encode("utf-8"))
|
||||
return file_name, patch_content
|
||||
|
||||
|
||||
# Load the subclasses so that get_layer can filter them.
|
||||
from source.mkw.Patch.PatchOperation.BmgTxtEditor import (
|
||||
CTFileLayer, FormatOriginalTrackLayer, IDLayer, PatchLayer, RegexLayer
|
||||
)
|
|
@ -1,14 +1,14 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.wt import img
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class ImageDecoder(AbstractOperation):
|
||||
class ImageDecoder(AbstractPatchOperation):
|
||||
"""
|
||||
decode a game image to a image file
|
||||
"""
|
|
@ -1,6 +1,6 @@
|
|||
from PIL import ImageDraw, Image
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation.ImageEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.ImageEditor import AbstractLayer
|
||||
|
||||
|
||||
Patch: any
|
|
@ -1,7 +1,7 @@
|
|||
from PIL import Image
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation.Operation.ImageEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.ImageEditor import AbstractLayer
|
||||
|
||||
|
||||
class ImageLayer(AbstractLayer):
|
||||
|
@ -36,3 +36,4 @@ class ImageLayer(AbstractLayer):
|
|||
)
|
||||
|
||||
return image
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from PIL import ImageFont, ImageDraw, Image
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation.Operation.ImageEditor.Layer import *
|
||||
from source.mkw.Patch.PatchOperation.ImageEditor import AbstractLayer
|
||||
|
||||
|
||||
class TextLayer(AbstractLayer):
|
|
@ -1,8 +1,13 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
from abc import abstractmethod, ABC
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
|
||||
|
||||
Layer: any
|
||||
Patch: any
|
||||
|
||||
|
||||
|
@ -58,6 +63,42 @@ class AbstractLayer(ABC):
|
|||
Patch an image with the actual layer. Return the new image.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get(cls, layer: dict) -> "Layer":
|
||||
"""
|
||||
return the correct type of layer corresponding to the layer mode
|
||||
:param layer: the layer to load
|
||||
"""
|
||||
for subclass in filter(lambda subclass: subclass.type == layer["type"], cls.__subclasses__()):
|
||||
layer.pop("type")
|
||||
return subclass(**layer)
|
||||
raise InvalidImageLayerType(layer["type"])
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation.ImageEditor.Layer import ColorLayer, ImageLayer, TextLayer
|
||||
__all__ = ["AbstractLayer", "ColorLayer", "ImageLayer", "TextLayer"]
|
||||
|
||||
class ImageGenerator(AbstractPatchOperation):
|
||||
"""
|
||||
generate a new image based on a file and apply a generator on it
|
||||
"""
|
||||
|
||||
type = "img-edit"
|
||||
|
||||
def __init__(self, layers: list[dict]):
|
||||
self.layers: list["Layer"] = [AbstractLayer.get(layer) for layer in layers]
|
||||
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
image = Image.open(file_content).convert("RGBA")
|
||||
|
||||
for layer in self.layers:
|
||||
image = layer.patch_image(patch, image)
|
||||
|
||||
patch_content = BytesIO()
|
||||
image.save(patch_content, format="PNG")
|
||||
patch_content.seek(0)
|
||||
|
||||
return file_name, patch_content
|
||||
|
||||
|
||||
# Load the class so that __subclasses__ can find them
|
||||
from source.mkw.Patch.PatchOperation.ImageEditor import (
|
||||
ColorLayer, ImageLayer, TextLayer
|
||||
)
|
|
@ -1,14 +1,14 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.wt import img
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class ImageEncoder(AbstractOperation):
|
||||
class ImageEncoder(AbstractPatchOperation):
|
||||
"""
|
||||
encode an image to a game image file
|
||||
"""
|
|
@ -1,17 +0,0 @@
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class AbstractLayer(ABC):
|
||||
@abstractmethod
|
||||
def patch_bmg(self, patch: "Patch", decoded_content: str) -> str:
|
||||
"""
|
||||
Patch a bmg with the actual layer. Return the new bmg content.
|
||||
"""
|
||||
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import IDLayer, RegexLayer, CTFileLayer, PatchLayer, \
|
||||
FormatOriginalTrackLayer
|
||||
__all__ = ["AbstractLayer", "IDLayer", "RegexLayer", "CTFileLayer", "PatchLayer", "FormatOriginalTrackLayer"]
|
|
@ -1,45 +0,0 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation.Operation.BmgTxtEditor.Layer import *
|
||||
|
||||
|
||||
class BmgTxtEditor(AbstractOperation):
|
||||
"""
|
||||
edit a decoded bmg
|
||||
"""
|
||||
|
||||
type = "bmgtxt-edit"
|
||||
|
||||
def __init__(self, layers: list[dict]):
|
||||
"""
|
||||
:param layers: layers
|
||||
"""
|
||||
self.layers = layers
|
||||
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
decoded_content: str = file_content.read().decode("utf-8")
|
||||
|
||||
for layer in self.layers:
|
||||
decoded_content = self.Layer(layer).patch_bmg(patch, decoded_content)
|
||||
|
||||
patch_content: IO = BytesIO(decoded_content.encode("utf-8"))
|
||||
return file_name, patch_content
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
represent a layer for a bmg-edit
|
||||
"""
|
||||
|
||||
def __new__(cls, layer: dict) -> "Layer":
|
||||
"""
|
||||
return the correct type of layer corresponding to the layer mode
|
||||
:param layer: the layer to load
|
||||
"""
|
||||
for subclass in filter(lambda subclass: subclass.mode == layer["mode"],
|
||||
AbstractLayer.__subclasses__()):
|
||||
layer.pop("mode")
|
||||
return subclass(**layer)
|
||||
raise InvalidBmgLayerMode(layer["mode"])
|
|
@ -1,47 +0,0 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation.Operation.ImageEditor.Layer import *
|
||||
|
||||
|
||||
class ImageGenerator(AbstractOperation):
|
||||
"""
|
||||
generate a new image based on a file and apply a generator on it
|
||||
"""
|
||||
|
||||
type = "img-edit"
|
||||
|
||||
def __init__(self, layers: list[dict]):
|
||||
self.layers: list["Layer"] = [self.Layer(layer) for layer in layers]
|
||||
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
image = Image.open(file_content).convert("RGBA")
|
||||
|
||||
for layer in self.layers:
|
||||
image = layer.patch_image(patch, image)
|
||||
|
||||
patch_content = BytesIO()
|
||||
image.save(patch_content, format="PNG")
|
||||
patch_content.seek(0)
|
||||
|
||||
return file_name, patch_content
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
represent a layer for an image generator
|
||||
"""
|
||||
|
||||
def __new__(cls, layer: dict) -> "Layer":
|
||||
"""
|
||||
return the correct type of layer corresponding to the layer mode
|
||||
:param layer: the layer to load
|
||||
"""
|
||||
for subclass in filter(lambda subclass: subclass.type == layer["type"],
|
||||
AbstractLayer.__subclasses__()):
|
||||
layer.pop("type")
|
||||
return subclass(**layer)
|
||||
raise InvalidImageLayerType(layer["type"])
|
|
@ -1,22 +0,0 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from typing import IO
|
||||
|
||||
Patch: any
|
||||
Layer: any
|
||||
|
||||
|
||||
class AbstractOperation(ABC):
|
||||
|
||||
mode: str # name of the operation
|
||||
|
||||
@abstractmethod
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
"""
|
||||
patch a file and return the new file_path (if changed) and the new content of the file
|
||||
"""
|
||||
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import ImageDecoder, ImageEncoder, Rename, Special, StrEditor, \
|
||||
BmgTxtEditor, ImageEditor, BmgEncoder, BmgDecoder
|
||||
__all__ = ["AbstractOperation", "ImageDecoder", "ImageEncoder", "Rename",
|
||||
"Special", "StrEditor", "BmgTxtEditor", "ImageEditor", "BmgEncoder", "BmgDecoder"]
|
|
@ -1,12 +1,12 @@
|
|||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class Rename(AbstractOperation):
|
||||
class Rename(AbstractPatchOperation):
|
||||
"""
|
||||
Rename the output file
|
||||
"""
|
|
@ -1,12 +1,12 @@
|
|||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
|
||||
|
||||
Patch: any
|
||||
|
||||
|
||||
class Special(AbstractOperation):
|
||||
class Special(AbstractPatchOperation):
|
||||
"""
|
||||
use a file defined as special in the patch to replace the current file content
|
||||
"""
|
|
@ -1,12 +1,12 @@
|
|||
from io import BytesIO
|
||||
from typing import IO
|
||||
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from source.mkw.Patch.PatchOperation import AbstractPatchOperation
|
||||
from source.mkw.Patch import *
|
||||
from source.wt import wstrt
|
||||
|
||||
|
||||
class StrEditor(AbstractOperation):
|
||||
class StrEditor(AbstractPatchOperation):
|
||||
"""
|
||||
patch the main.dol file
|
||||
"""
|
|
@ -1,18 +1,39 @@
|
|||
from source.mkw.Patch import *
|
||||
from source.mkw.Patch.PatchOperation.Operation import *
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import IO, Type
|
||||
|
||||
Patch: any
|
||||
Layer: any
|
||||
|
||||
|
||||
class PatchOperation:
|
||||
class AbstractPatchOperation(ABC):
|
||||
"""
|
||||
Represent an operation that can be applied onto a patch to modify it before installing
|
||||
An AbstractPatchOperation representing any PatchOperation that can be used on one of the game files
|
||||
"""
|
||||
|
||||
def __new__(cls, name) -> "Operation":
|
||||
mode: str # name of the operation
|
||||
|
||||
@abstractmethod
|
||||
def patch(self, patch: "Patch", file_name: str, file_content: IO) -> (str, IO):
|
||||
"""
|
||||
patch a file and return the new file_path (if changed) and the new content of the file
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get(cls, name: str) -> Type["AbstractPatchOperation"]:
|
||||
"""
|
||||
Return an operation from its name
|
||||
:name: name of the operation
|
||||
:return: an Operation from its name
|
||||
"""
|
||||
|
||||
for subclass in filter(lambda subclass: subclass.type == name, AbstractOperation.__subclasses__()):
|
||||
for subclass in filter(lambda subclass: subclass.type == name, cls.__subclasses__()):
|
||||
return subclass
|
||||
raise InvalidPatchOperation(name)
|
||||
|
||||
|
||||
# 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
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue