rewrote the ModSettings to be simpler

This commit is contained in:
Faraphel 2022-08-21 20:35:49 +02:00
parent 5f5dc6bfbc
commit f2d27deb68
6 changed files with 52 additions and 68 deletions

View file

@ -59,7 +59,7 @@
"en": "Should the mod balancing (fake item box, blooper) be enabled ?",
"fr": "Est-ce que l'équilibrage du mod (fausse boite d'objet, bloops) devrait être activé ?"
},
"type": "check",
"type": "boolean",
"default": true
}
},

View file

@ -6,10 +6,9 @@ import json
from PIL import Image
from source import threaded
from source.mkw import Tag
from source.mkw import Tag, ModSettings
from source.mkw.Track.Cup import Cup
from source.mkw.collection import MKWColor, Slot
from source.mkw.ModSettings import AbstractModSettings
from source.mkw.Track import CustomTrack, DefaultTrack, Arena
from source.progress import Progress
from source.safe_eval.safe_eval import safe_eval
@ -121,11 +120,11 @@ class ModConfig:
self._tracks = [CustomTrack.from_dict(self, track) for track in self._tracks if isinstance(track, dict)]
self._arenas = [Arena.from_dict(self, arena) for arena in self._arenas if isinstance(arena, dict)]
self.global_settings = {name: AbstractModSettings.get(data) for name, data in merge_dict(
self.global_settings = {name: ModSettings.get(data) for name, data in merge_dict(
default_global_settings, self.global_settings, dict_keys=default_global_settings.keys()
# Avoid modder to add their own settings to globals one
).items()}
self.specific_settings = {name: AbstractModSettings.get(data) for name, data in self.specific_settings.items()}
self.specific_settings = {name: ModSettings.get(data) for name, data in self.specific_settings.items()}
def __hash__(self) -> int:
return hash(self.name)

View file

@ -1,34 +1,25 @@
import tkinter
from tkinter import ttk
from dataclasses import dataclass, field
from source.mkw.ModSettings import AbstractModSettings
from source.translation import translate as _
@dataclass(init=False)
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.
"""
type = "check"
def __init__(self, enabled: bool = False,
default: bool | None = None, text: dict[str, str] = None, description: dict[str, str] = None):
self._value = default if default is not None else False
self.default = default
self.description = description if description is not None else {}
self.enabled = enabled
self.text = text if text is not None else {}
type = "boolean"
def tkinter_show(self, master, checkbox) -> None:
super().tkinter_show(master, checkbox)
variable = self.tkinter_variable(tkinter.BooleanVar)
value_variable = tkinter.BooleanVar(master, value=self._value)
value_variable.trace_add("write", lambda *_: setattr(self, "_value", value_variable.get()))
radiobutton_on = ttk.Radiobutton(master, text=_("DISABLED"), variable=value_variable, value=False)
radiobutton_on = ttk.Radiobutton(master, text=_("DISABLED"), variable=variable, value=False)
radiobutton_on.grid(row=1, column=1, sticky="E")
radiobutton_off = ttk.Radiobutton(master, text=_("ENABLED"), variable=value_variable, value=True)
radiobutton_off = ttk.Radiobutton(master, text=_("ENABLED"), variable=variable, value=True)
radiobutton_off.grid(row=1, column=2, sticky="E")

View file

@ -1,9 +1,11 @@
import tkinter
from dataclasses import field, dataclass
from tkinter import ttk
from source.mkw.ModSettings import AbstractModSettings
@dataclass(init=False)
class Choices(AbstractModSettings):
"""
This setting type allow you to input a string text.
@ -12,25 +14,14 @@ class Choices(AbstractModSettings):
type = "choices"
def __init__(self, choices: list[str], enabled: bool = False,
default: str | None = None, text: dict[str, str] = None, description: dict[str, str] = None):
self._value = default if default is not None else choices[0]
self.default = default
self.enabled = enabled
self.text = text if text is not None else {}
self.description = description if description is not None else {}
self.choices = choices
def __init__(self, choices: list[str] = None, **kwargs):
super().__init__(**kwargs)
self.choices = choices if choices is not None else []
def tkinter_show(self, master, checkbox) -> None:
super().tkinter_show(master, checkbox)
master.grid_rowconfigure(1, weight=1)
variable = self.tkinter_variable(tkinter.StringVar)
master.grid_columnconfigure(1, weight=1)
value_variable = tkinter.StringVar(master, value=self._value)
value_variable.trace_add("write", lambda *_: setattr(self, "_value", value_variable.get()))
combobox = ttk.Combobox(master, values=self.choices, textvariable=value_variable)
combobox = ttk.Combobox(master, values=self.choices, textvariable=variable)
combobox.grid(row=1, column=1, sticky="EW")

View file

@ -13,34 +13,23 @@ class String(AbstractModSettings):
type = "string"
def __init__(self, preview: str = None, enabled: bool = False,
default: str | None = None, text: dict[str, str] = None, description: dict[str, str] = None):
self._value: str = default if default is not None else ""
self.default = default
self.enabled = enabled
self.text = text if text is not None else {}
self.description = description if description is not None else {}
self.preview: str | None = preview
def __init__(self, preview: str | None = None, **kwargs):
super().__init__(**kwargs)
self.preview = preview
def tkinter_show(self, master, checkbox) -> None:
super().tkinter_show(master, checkbox)
master.grid_rowconfigure(1, weight=1)
variable = self.tkinter_variable(tkinter.StringVar)
master.grid_columnconfigure(1, weight=1)
value_variable = tkinter.StringVar(master, value=self._value)
value_variable.trace_add("write", lambda *_: setattr(self, "_value", value_variable.get()))
entry = ttk.Entry(master, textvariable=value_variable)
entry = ttk.Entry(master, textvariable=variable)
entry.grid(row=1, column=1, sticky="EW")
if self.preview is not None:
button = ttk.Button(
master, text="...", width=3,
command=lambda: AbstractPreviewWindow.get(self.preview)(
master.master.master.master.mod_config, value_variable
master.master.master.master.mod_config, variable
)
)
button.grid(row=1, column=2, sticky="EW")

View file

@ -1,6 +1,7 @@
import tkinter
from tkinter import ttk
from abc import ABC, abstractmethod
from typing import Type
from source.translation import translate as _
@ -16,10 +17,16 @@ class AbstractModSettings(ABC):
"""
type: str # type name of the settings
text: dict[str] # text to display in the settings window depending on the language
enabled: bool # is the settings enabled
default: str | None # default value of the settings (used is disabled)
_value: any # value for the settings
def __init__(self, text: dict[str, str] = None, description: dict[str, str] = None, enabled: bool = False,
default: str | None = None, value: any = None):
self.text = text if text is not None else {} # text to display in the window settings.
self.description = description if description is not None else {} # desc to display in the window settings.
self.enabled = enabled # is the settings enabled
self.default: str | None = default # default value of the settings (used is disabled)
self._value: any = value if value is not None else default # value for the settings
@property
def value(self) -> "any | None":
@ -45,19 +52,26 @@ class AbstractModSettings(ABC):
"""
enabled_variable.set(self.enabled)
enabled_variable.trace_add("write", lambda *_: setattr(self, "enabled", enabled_variable.get()))
# si le paramètre est modifié, coche automatiquement la case
...
@classmethod
def get(cls, settings_data: dict) -> "AbstractModSettings":
"""
Load all the settings in mod_settings_dict
:param settings_data: dictionary containing all the settings defined for the mod
"""
for subclass in filter(lambda subclass: subclass.type == settings_data["type"], cls.__subclasses__()):
settings_data.pop("type")
return subclass(**settings_data)
else: raise InvalidSettingsType(settings_data["type"])
def tkinter_variable(self, vartype: Type[tkinter.Variable]) -> tkinter.Variable:
variable = vartype(value=self._value)
variable.trace_add("write", lambda *_: setattr(self, "_value", variable.get()))
return variable
def get(settings_data: dict) -> "AbstractModSettings":
"""
Load all the settings in mod_settings_dict
:param settings_data: dictionary containing all the settings defined for the mod
"""
for subclass in filter(lambda subclass: subclass.type == settings_data["type"],
AbstractModSettings.__subclasses__()):
settings_data.pop("type")
return subclass(**settings_data)
else: raise InvalidSettingsType(settings_data["type"])
# 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, Check
from source.mkw.ModSettings import Choices, String, Boolean