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""" _image = Null() _image_cached = False blacklist_toggles = ("hair", "glasses", "pubes", "piercing", "makeup", "tattoo", "earrings") blacklist_unequip = ("hair",) multislots = ("makeup", "accessory", "piercing", "tattoo") extensions = {".webp", ".png", ".jxl"} sizes = (1010, 1200) # Default sizes used for defining rare cases def rebuild_image(self): self._image_cached = True @property def image(self): if not renpy.is_skipping(): if not self._image_cached: self._image_cached = True self._image = self.build_image() return self._image