2022-05-16 23:48:22 +00:00
|
|
|
init python:
|
|
|
|
class DollOutfit(DollMethods):
|
|
|
|
default_schedule = {"day": False, "night": False, "cloudy": False, "rainy": False, "snowy": False}
|
|
|
|
|
|
|
|
def __init__(self, group, unlocked=False, name="", desc="", price=0, temp=False, schedule={}, hidden=False, addons=[]):
|
|
|
|
self.group = [x.clone() if not x.parent else x for x in group]
|
|
|
|
self.name = name
|
|
|
|
self.desc = desc
|
|
|
|
self.price = price
|
|
|
|
self.char = self.group[0].char
|
|
|
|
self.unlocked = unlocked
|
2022-09-21 20:57:04 +00:00
|
|
|
self.schedule = dict(list(self.default_schedule.items()) + list(schedule.items()))
|
2022-05-16 23:48:22 +00:00
|
|
|
self.temp = temp
|
|
|
|
self.hidden = hidden
|
|
|
|
self.addons = addons
|
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
|
|
|
self._hash = self.generate_hash()
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not self.temp:
|
|
|
|
|
|
|
|
if unlocked:
|
|
|
|
self.unlock()
|
|
|
|
|
|
|
|
if not self.hidden and not self in self.char.outfits:
|
|
|
|
self.char.outfits.append(self)
|
|
|
|
|
2022-09-29 21:19:55 +00:00
|
|
|
def __hash__(self):
|
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
|
|
|
return self._hash
|
2022-09-29 21:19:55 +00:00
|
|
|
|
2022-05-16 23:48:22 +00:00
|
|
|
def __eq__(self, obj):
|
|
|
|
if not isinstance(obj, DollOutfit):
|
|
|
|
return NotImplemented
|
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
|
|
|
return self._hash == obj._hash
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
def generate_hash(self):
|
2023-01-18 20:22:59 +00:00
|
|
|
salt = str( [self.name, str([x._hash for x in self.group]) ] )
|
2022-05-16 23:48:22 +00:00
|
|
|
return hash(salt)
|
|
|
|
|
|
|
|
def delete(self):
|
|
|
|
if self in self.char.outfits:
|
|
|
|
self.char.outfits.remove(self)
|
|
|
|
|
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
|
|
|
@functools.cache
|
2023-01-18 20:22:59 +00:00
|
|
|
def build_image(self, hash):
|
|
|
|
from itertools import chain
|
2022-11-11 22:24:47 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
matrix = SaturationMatrix(0.0)
|
2022-11-11 22:24:47 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
sprites = list(chain.from_iterable(
|
2023-02-22 17:50:13 +00:00
|
|
|
(self.char.body.build_image(self.char.body._hash, matrix=matrix),
|
|
|
|
*(x.build_image(x._hash, matrix=matrix) for x in self.group))
|
2023-01-18 20:22:59 +00:00
|
|
|
))
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
masks = [sprites.pop(sprites.index(x)) for x in sprites if x[0] == "mask"]
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
sprites.sort(key=itemgetter(2))
|
|
|
|
masks.sort(key=itemgetter(2))
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
back_sprites = [x[1] for x in sprites if x[2] < 0]
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
#Apply alpha mask
|
2022-05-16 23:48:22 +00:00
|
|
|
for m in masks:
|
2023-01-18 20:22:59 +00:00
|
|
|
_, mask, mask_zorder = m
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
for i, s in enumerate(sprites):
|
2023-01-18 20:22:59 +00:00
|
|
|
_, sprite, sprite_zorder = s
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if i < 1 or mask_zorder > sprite_zorder:
|
|
|
|
continue
|
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
masked = AlphaMask(Fixed(*(x[1] for x in sprites[:i]), fit_first=True), mask)
|
2022-05-16 23:48:22 +00:00
|
|
|
sprites = sprites[i:]
|
2023-01-18 20:22:59 +00:00
|
|
|
sprites.insert(0, (None, masked, mask_zorder))
|
2022-05-16 23:48:22 +00:00
|
|
|
break
|
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
sprites = back_sprites + [x[1] for x in sprites]
|
|
|
|
|
|
|
|
return Fixed(*sprites, fit_first=True)
|
2022-05-16 23:48:22 +00:00
|
|
|
|
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
|
|
|
@property
|
|
|
|
def image(self):
|
2023-01-18 20:22:59 +00:00
|
|
|
return self.build_image(self._hash)
|
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
|
|
|
|
2022-05-16 23:48:22 +00:00
|
|
|
def exists(self):
|
|
|
|
return (self in self.char.outfits)
|
|
|
|
|
|
|
|
def export_data(self, filename, tofile=True):
|
|
|
|
"""Exports outfit to .png file or clipboard text."""
|
|
|
|
exported = [self.group[0].name]
|
2023-02-10 23:12:16 +00:00
|
|
|
|
|
|
|
for i in self.group:
|
|
|
|
if i.color:
|
|
|
|
color = [j.hexcode for j in i.color]
|
|
|
|
exported.append([i.id, color])
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
# Encode data
|
|
|
|
if tofile:
|
2023-02-10 23:12:16 +00:00
|
|
|
path = os.path.join(config.gamedir, "outfits")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not os.path.exists(path):
|
|
|
|
os.makedirs(path)
|
|
|
|
|
2023-02-10 23:12:16 +00:00
|
|
|
path = os.path.join(path, "_temp.png")
|
|
|
|
|
2023-01-18 20:22:59 +00:00
|
|
|
d = Transform(self.image, crop=(210, 200, 700, 1000), anchor=(0.5, 1.0), align=(0.5, 1.0), xsize=310, ysize=470, fit="contain")
|
2022-05-16 23:48:22 +00:00
|
|
|
d = Fixed(
|
|
|
|
"interface/wardrobe/export_background.webp",
|
|
|
|
d,
|
|
|
|
"interface/wardrobe/export_frame.webp",
|
|
|
|
Text(active_girl, align=(0.5, 0.995)),
|
|
|
|
Text("Ver. {}".format(config.version), size=10, align=(0.99, 0.99))
|
|
|
|
)
|
|
|
|
|
2023-02-10 23:12:16 +00:00
|
|
|
displayable_to_file(d, path, size=(310, 470) )
|
|
|
|
ImagePayload().inject("_temp.png", filename, str(exported))
|
|
|
|
os.remove(path)
|
2022-05-16 23:48:22 +00:00
|
|
|
else:
|
|
|
|
set_clipboard(exported)
|
|
|
|
renpy.notify("Export successful!")
|
|
|
|
|
|
|
|
def unlock(self):
|
|
|
|
"""Unlocks outfit and respective clothing objects from which they were cloned."""
|
|
|
|
self.unlocked = True
|
|
|
|
for i in self.group:
|
|
|
|
i.unlock()
|
|
|
|
|
|
|
|
for i in self.addons:
|
|
|
|
i.unlock()
|
|
|
|
|
|
|
|
def save(self):
|
|
|
|
"""Overwrites this outfit with clothes currently equipped by the character."""
|
2023-02-07 19:22:05 +00:00
|
|
|
self.group = [x[0].clone() for x in self.char.states.values() if x[0]]
|
2022-05-16 23:48:22 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
def is_modded(self):
|
|
|
|
"""Returns True if one of the group items comes from a mod."""
|
|
|
|
for i in self.group:
|
|
|
|
if i.is_modded():
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def get_modname(self):
|
|
|
|
"""Returns a list of mods contained within the outfit group."""
|
|
|
|
return list(set([i.get_modname() for i in self.group if i.is_modded()]))
|
|
|
|
|
|
|
|
def get_schedule(self):
|
|
|
|
"""Returns a dictionary with the current schedule."""
|
|
|
|
return self.schedule
|
|
|
|
|
|
|
|
def set_schedule(self, **kwargs):
|
2022-09-21 20:57:04 +00:00
|
|
|
for k, v in kwargs.items():
|
2022-05-16 23:48:22 +00:00
|
|
|
self.schedule[k] = v
|
|
|
|
|
|
|
|
def has_type(self, *args):
|
|
|
|
"""Takes argument(s) containing string cloth type(s). Returns True if worn, False otherwise."""
|
|
|
|
types = set(x.type for x in self.group)
|
|
|
|
|
|
|
|
for arg in args:
|
|
|
|
if arg in self.multislots:
|
|
|
|
if not any(x.startswith(arg) for x in types):
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
if not arg in types:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
def has_any_type(self, *args):
|
|
|
|
"""Takes arguments containing string cloth types. Returns True if ANY of them is worn, False otherwise."""
|
|
|
|
if "clothes" in args:
|
2023-02-07 19:22:05 +00:00
|
|
|
for k in self.char.states.keys():
|
2022-05-16 23:48:22 +00:00
|
|
|
if not k.startswith(self.blacklist_toggles):
|
|
|
|
if self.has_type(k):
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
for arg in args:
|
|
|
|
if self.has_type(arg):
|
|
|
|
return True
|
|
|
|
return False
|