init python: class DollBody(DollMethods): layer_types = { # Body class has no use for layer types } layer_modifiers = { "zorder": None, } def __init__(self, obj): self.char = obj self.hue = HueMatrix(0) self.zorder = 0 self._hash = None def set_hue(self, hue): self.hue = HueMatrix(hue) self.is_stale() def generate_hash(self): salt = str( [self.char.name + self.char.pose, str(self.hue.__hash__())]) return hash(salt) @functools.cache def get_layers(self, hash): path = os.path.join("characters", self.char.name, self.char.pose, "body") extensions = self.extensions modifiers = self.layer_modifiers layers = {} for f in renpy.list_files(): fp, fn = os.path.split(f) fn, ext = os.path.splitext(fn) if not fp == path or not ext in extensions: continue _, *tails = fn.rsplit("_") zorder = self.zorder if tails: lmodifier, *tails = tails if not lmodifier in modifiers: print("Invalid modifier for file: {}".format(f)) continue zorder_mod = modifiers.get(lmodifier) zorder = (zorder + int(zorder_mod)) if lmodifier != "zorder" else int(tails[-1]) layers.setdefault(fn, [f, zorder]) return layers @functools.cache def build_image(self, hash, matrix=None): if matrix is None: matrix = self.hue processors = { "default": lambda file: Transform(Image(file), matrixcolor=matrix), } layers = self.get_layers(hash) sprites = [] for identifier, (file, zorder) in layers.items(): processor = processors.get(identifier, processors["default"]) processed_file = processor(file) sprites.append((identifier, processed_file, zorder)) return sprites @property def image(self): if not renpy.is_skipping() and self.is_stale(): hash = self._hash sprites = self.build_image(hash, self.hue) sprites.sort(key=itemgetter(2)) sprites = [x[1] for x in sprites] self._image = Fixed(*sprites, fit_first=True) return self._image