forked from SilverStudioGames/WTS
LoafyLemon
c1b04f6ccd
* Refactored DollFace * Refactored DollBody * Refactored DollCum * Refactored DollCloth * Refactored Doll * Refactored clothing item zorders * Refactored implementation of body, face, cum, clothing layers * Refactored function calls * Removed DollLipstick * Added DollMakeup class, allowing adding dynamic clothes tracking face states * Added DollClothDynamic, allowing dynamic clothes tracking other cloth states with bangs support * Added cache to frequently called functions, drastically reducing the overhead * Added hash system, reducing clone redundancy * Added layer modifiers support for all types (face, body, cum, clothes etc.) * Added support for an arbitrary number of equipped multislot clothing items (makeup, tattoos, piercings, etc.) * Simplified initialization for clothing items and dolls * Simplified class function calls * Reduced the number of image creation calls * Added hue support for additional skin layers * Added displayable support to image cropping function * Replaced store cache with built-in functools cache for _list_files function * Refactored all character files * and more...
142 lines
4.6 KiB
Plaintext
142 lines
4.6 KiB
Plaintext
init python:
|
|
class DollCum(DollMethods):
|
|
layer_types = {
|
|
"skin": 0,
|
|
"cum": 100,
|
|
}
|
|
|
|
layer_modifiers = {
|
|
"zorder": None,
|
|
}
|
|
|
|
def __init__(self, obj):
|
|
self.char = obj
|
|
self.layers = None
|
|
self._cum = {k: None for k in {"hair", "face", "breasts", "body", "crotch", "pussy", "legs"}}
|
|
|
|
def set_cum(self, *args, **kwargs):
|
|
if args:
|
|
self._cum = {k: args[0] for k in self._cum}
|
|
|
|
self._cum.update(kwargs)
|
|
self.layers = self.get_layers()
|
|
self.rebuild_image()
|
|
|
|
def get_layers(self):
|
|
cum = self._cum
|
|
|
|
extensions = self.extensions
|
|
types = self.layer_types
|
|
modifiers = self.layer_modifiers
|
|
|
|
layers = {}
|
|
for part, name in cum.items():
|
|
|
|
if name is None:
|
|
continue
|
|
|
|
path = os.path.join("characters", self.char.name, self.char.pose, "cum", part, name)
|
|
|
|
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
|
|
|
|
ltype, *tails = fn.rsplit("_")
|
|
|
|
if not ltype in types:
|
|
print("Invalid layer type for file: {}".format(f))
|
|
continue
|
|
|
|
zorder = types.get(ltype)
|
|
|
|
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))
|
|
layers.setdefault(" ".join([part, name, ltype, lmodifier]), [f, zorder])
|
|
else:
|
|
layers.setdefault(" ".join([part, name, ltype]), [f, zorder])
|
|
|
|
return layers
|
|
|
|
def build_image(self, matrix=None):
|
|
self.layers = layers = self.layers or self.get_layers()
|
|
|
|
if matrix is None:
|
|
matrix = self.char.body.hue
|
|
|
|
processors = {
|
|
"skin": lambda file: Transform(file, matrixcolor=matrix),
|
|
"default": lambda file: Image(file),
|
|
}
|
|
|
|
sprites = []
|
|
for identifier, (file, zorder) in layers.items():
|
|
|
|
cum_type, name, ltype = identifier.rsplit(" ")
|
|
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():
|
|
if not self._image_cached:
|
|
self._image_cached = True
|
|
|
|
sprites = self.build_image()
|
|
sprites.sort(key=itemgetter(2))
|
|
sprites = [x[1] for x in sprites]
|
|
|
|
self._image = Fixed(*sprites, fit_first=True)
|
|
return self._image
|
|
|
|
def rebuild_image(self):
|
|
self._image_cached = False
|
|
|
|
# def build_image(self):
|
|
# sprites = tuple("{}{}/{}.webp".format(self.imagepath, k, v) for k, v in self.cum.items() if v != None)
|
|
# return sprites
|
|
|
|
# def get_skin(self):
|
|
# return ["{}{}/{}_skin.webp".format(self.imagepath, k, v) for k, v in self.cum.items() if renpy.loadable("{}{}/{}_skin.webp".format(self.imagepath, k, v))]
|
|
|
|
# def set_cum(self, *args, **kwargs):
|
|
# """Takes keyword argument(s) containing string name(s) of cum layers to apply or None. Returns True if image is changed."""
|
|
# changed = False
|
|
|
|
# if args:
|
|
# for k, v in self.cum.items():
|
|
# if v != args[0]:
|
|
# self.cum[k] = args[0]
|
|
# changed = True
|
|
|
|
# for arg, value in kwargs.items():
|
|
# if str(arg) != value:
|
|
# self.cum[str(arg)] = value
|
|
# changed = True
|
|
|
|
# if changed:
|
|
# self.rebuild_image()
|
|
|
|
# return changed
|
|
|
|
# def set_pose(self, pose):
|
|
# if pose is None:
|
|
# self.imagepath = "characters/{}/cum/".format(self.name)
|
|
# else:
|
|
# self.imagepath = "characters/{}/poses/{}/cum/".format(self.name, pose)
|
|
# self.rebuild_image()
|
|
# return
|