def build_sheets(structures): '''Build sprite sheet(s) containing all the images for the provided structures. This also updates each part's `sheet_idx` and `offset` field with its position in the generated sheet(s). ''' parts = [p for s in structures for p in s.parts] all_imgs = [p.get_sheet_image() for p in parts] imgs, idx_map = util.dedupe(all_imgs, [i.hash() for i in all_imgs]) boxes = [tuple((x + TILE_SIZE - 1) // TILE_SIZE for x in i.size) for i in imgs] num_sheets, offsets = util.pack_boxes(SHEET_SIZE, boxes) sheets = [Image.new('RGBA', (SHEET_PX, SHEET_PX)) for _ in range(num_sheets)] for img, (j, offset) in zip(imgs, offsets): x, y = offset x *= TILE_SIZE y *= TILE_SIZE sheets[j].paste(img.raw().raw(), (x, y)) for part, img in zip(parts, all_imgs): idx = idx_map[id(img)] j, offset = offsets[idx] part.sheet_idx = j part.offset = geom.mul(offset, TILE_SIZE) return sheets
def get_image(self): """Obtain a reasonable depiction of this structure as a still image.""" if self.image is not None: return self.image.still() elif self.shape is not None: sx, sy, sz = self.shape.size if len(self.parts) == 0: return image2.Image(size=(sx, sy + sz), unit=TILE_SIZE) size = geom.mul((sx, sy + sz), TILE_SIZE) layers = [] for model, img in self.parts: b_min, b_max = model.bounds bx, by = util.project(b_min) layers.append(img.still().pad(size, offset=(bx, by))) return layers[0].stack(layers) else: return image2.Image(size=(1, 1), unit=TILE_SIZE)
def get_image(self): if self.image is not None: return self.image elif self.anim_frames is not None and len(self.anim_frames) > 0: return self.anim_frames[0] elif self.shape is not None: sx, sy, sz = self.shape.size if len(self.parts) == 0: return image2.Image(size=(sx, sy + sz), unit=TILE_SIZE) size = geom.mul((sx, sy + sz), TILE_SIZE) layers = [] for model, img in self.parts: b_min, b_max = model.bounds bx, by = util.project(b_min) layers.append(img.pad(size, offset=(bx, by))) return layers[0].stack(layers) else: return image2.Image(size=(1, 1), unit=TILE_SIZE)