WTS/game/scripts/doll/cum.rpy
LoafyLemon c1b04f6ccd IO Overhaul, Refactoring, and more
* 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...
2023-01-14 23:04:54 +00:00

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