2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
init -1 python:
|
|
|
|
|
|
|
|
### Global Functions ###
|
|
|
|
|
|
|
|
def get_character_emote(char, emote):
|
|
|
|
return "characters/{}/emotes/{}.webp".format(char, emote) if emote else None
|
|
|
|
|
|
|
|
def get_character_pos(char):
|
|
|
|
global sprite_pos
|
|
|
|
|
|
|
|
flip = getattr(renpy.store, char+"_flip", None)
|
|
|
|
use_head = getattr(renpy.store, "use_"+char+"_head", None)
|
|
|
|
|
|
|
|
# Resolve X position for head state
|
|
|
|
if use_head:
|
|
|
|
xpos = sprite_pos["x"]["far_right"] if flip == 1 else sprite_pos["x"]["far_left"]
|
|
|
|
else:
|
|
|
|
xpos = getattr(renpy.store, char+"_xpos", None)
|
|
|
|
ypos = getattr(renpy.store, char+"_ypos", None)
|
|
|
|
|
|
|
|
return (xpos, ypos)
|
|
|
|
|
|
|
|
### Classes ###
|
|
|
|
|
|
|
|
class DollDisplayable(renpy.Displayable):
|
|
|
|
def __init__(self, child, **properties):
|
|
|
|
super(DollDisplayable, self).__init__(**properties)
|
|
|
|
self.focusable = None
|
|
|
|
self.child = child
|
|
|
|
|
|
|
|
def render(self, width, height, st, at):
|
|
|
|
rv = renpy.Render(width, height)
|
|
|
|
c = self.child
|
|
|
|
cr = renpy.render(c, width, height, st, at)
|
|
|
|
|
|
|
|
# We need to find the 'true' size of the displayable
|
|
|
|
# otherwise it may end up being the size of a null,
|
|
|
|
# or any other irrelevant element.
|
|
|
|
|
|
|
|
xsize, ysize = cr.get_size()
|
|
|
|
xoffset, yoffset = c.place(rv, 0, 0, width, height, cr)
|
|
|
|
|
|
|
|
width = max(xoffset + xsize, width)
|
|
|
|
height = max(yoffset + ysize, height)
|
|
|
|
|
|
|
|
rv.width = width
|
|
|
|
rv.height = height
|
|
|
|
|
|
|
|
return rv
|
|
|
|
|
|
|
|
def event(self, ev, x, y, st):
|
|
|
|
return None
|
|
|
|
#raise renpy.IgnoreEvent() # Seems to work similar to NullAction
|
|
|
|
|
|
|
|
def focus(self, default=False):
|
|
|
|
raise Exception("Not Implemented")
|
|
|
|
|
|
|
|
def unfocus(self, default=False):
|
|
|
|
raise Exception("Not Implemented")
|
|
|
|
|
|
|
|
def is_focused(self):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def visit_all(self, callback, seen=None):
|
|
|
|
return
|
|
|
|
|
|
|
|
def visit(self):
|
|
|
|
return []
|
|
|
|
|
|
|
|
class DollMethods(object):
|
|
|
|
"""Container class for commonly used methods and attributes"""
|
|
|
|
sprite = Null()
|
|
|
|
cached = False
|
|
|
|
threadlock = False
|
|
|
|
icon_threadlock = False
|
|
|
|
|
2022-10-19 21:19:05 +00:00
|
|
|
layers_extra = ("extra", "outline", "overlay")
|
|
|
|
layers_special = ("skin", "mask", "wind_mask")
|
|
|
|
layers_additional = ("back", "front")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
blacklist_toggles = ("hair", "glasses", "pubes", "piercing", "makeup", "tattoo", "earrings")
|
2022-10-19 21:19:05 +00:00
|
|
|
blacklist_unequip = ("hair",)
|
2022-05-16 23:48:22 +00:00
|
|
|
multislots = ("makeup", "accessory", "piercing", "tattoo")
|
|
|
|
|
|
|
|
sizes = (1010, 1200) # Default sizes used for defining rare cases
|
|
|
|
|
|
|
|
def rebuild_image(self):
|
|
|
|
# Defers rebuild until next time get_image is called
|
|
|
|
self.cached = False
|
|
|
|
|
|
|
|
def make_image(self):
|
|
|
|
thread = DollThread(target=self.build_image)
|
|
|
|
thread.daemon = True
|
|
|
|
thread.start()
|
|
|
|
|
|
|
|
sprites = thread.join()
|
|
|
|
|
|
|
|
self.sprite = DollDisplayable(Fixed(*sprites, fit_first=True))
|
|
|
|
|
|
|
|
def get_image(self):
|
|
|
|
if not renpy.is_skipping():
|
|
|
|
if not self.cached:
|
|
|
|
self.cached = True
|
|
|
|
|
|
|
|
self.make_image()
|
|
|
|
return self.sprite
|