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 layers_extra = {"extra", "outline", "overlay"} layers_special = {"skin", "mask", "wind_mask", "zorder"} layers_additional = {"back", "front"} blacklist_toggles = ("hair", "glasses", "pubes", "piercing", "makeup", "tattoo", "earrings") blacklist_unequip = {"hair"} 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