96 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			96 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | from .tileset import open_tiles, solid_tiles | ||
|  | 
 | ||
|  | 
 | ||
|  | def tx(x): | ||
|  |     return x * 16 + x // 10 | ||
|  | 
 | ||
|  | 
 | ||
|  | def ty(y): | ||
|  |     return y * 16 + y // 8 | ||
|  | 
 | ||
|  | 
 | ||
|  | class ImageGen: | ||
|  |     def __init__(self, tilesets, the_map, rom): | ||
|  |         self.tilesets = tilesets | ||
|  |         self.map = the_map | ||
|  |         self.rom = rom | ||
|  |         self.image = None | ||
|  |         self.draw = None | ||
|  |         self.count = 0 | ||
|  |         self.enabled = False | ||
|  |         self.__tile_cache = {} | ||
|  | 
 | ||
|  |     def on_step(self, wfc, cur=None, err=None): | ||
|  |         if not self.enabled: | ||
|  |             return | ||
|  |         if self.image is None: | ||
|  |             import PIL.Image | ||
|  |             import PIL.ImageDraw | ||
|  |             self.image = PIL.Image.new("RGB", (self.map.w * 161, self.map.h * 129)) | ||
|  |             self.draw = PIL.ImageDraw.Draw(self.image) | ||
|  |         self.image.paste(0, (0, 0, wfc.w * 16, wfc.h * 16)) | ||
|  |         for y in range(wfc.h): | ||
|  |             for x in range(wfc.w): | ||
|  |                 cell = wfc.cell_data[(x, y)] | ||
|  |                 if len(cell.options) == 1: | ||
|  |                     tile_id = next(iter(cell.options)) | ||
|  |                     room = self.map.get(x//10, y//8) | ||
|  |                     tile = self.get_tile(room.tileset_id, tile_id) | ||
|  |                     self.image.paste(tile, (tx(x), ty(y))) | ||
|  |                 else: | ||
|  |                     self.draw.text((tx(x) + 3, ty(y) + 3), f"{len(cell.options):2}", (255, 255, 255)) | ||
|  |                     if cell.options.issubset(open_tiles): | ||
|  |                         self.draw.rectangle((tx(x), ty(y), tx(x) + 15, ty(y) + 15), outline=(0, 128, 0)) | ||
|  |                     elif cell.options.issubset(solid_tiles): | ||
|  |                         self.draw.rectangle((tx(x), ty(y), tx(x) + 15, ty(y) + 15), outline=(0, 0, 192)) | ||
|  |         if cur: | ||
|  |             self.draw.rectangle((tx(cur[0]),ty(cur[1]),tx(cur[0])+15,ty(cur[1])+15), outline=(0, 255, 0)) | ||
|  |         if err: | ||
|  |             self.draw.rectangle((tx(err[0]),ty(err[1]),tx(err[0])+15,ty(err[1])+15), outline=(255, 0, 0)) | ||
|  |         self.image.save(f"_map/tmp{self.count:08}.png") | ||
|  |         self.count += 1 | ||
|  | 
 | ||
|  |     def get_tile(self, tileset_id, tile_id): | ||
|  |         tile = self.__tile_cache.get((tileset_id, tile_id), None) | ||
|  |         if tile is not None: | ||
|  |             return tile | ||
|  |         import PIL.Image | ||
|  |         tile = PIL.Image.new("L", (16, 16)) | ||
|  |         tileset = self.get_tileset(tileset_id) | ||
|  |         metatile = self.rom.banks[0x1A][0x2749 + tile_id * 4:0x2749 + tile_id * 4+4] | ||
|  | 
 | ||
|  |         def draw(ox, oy, t): | ||
|  |             addr = (t & 0x3FF) << 4 | ||
|  |             tile_data = self.rom.banks[t >> 10][addr:addr+0x10] | ||
|  |             for y in range(8): | ||
|  |                 a = tile_data[y * 2] | ||
|  |                 b = tile_data[y * 2 + 1] | ||
|  |                 for x in range(8): | ||
|  |                     v = 0 | ||
|  |                     bit = 0x80 >> x | ||
|  |                     if a & bit: | ||
|  |                         v |= 0x01 | ||
|  |                     if b & bit: | ||
|  |                         v |= 0x02 | ||
|  |                     tile.putpixel((ox+x,oy+y), (255, 192, 128, 32)[v]) | ||
|  |         draw(0, 0, tileset[metatile[0]]) | ||
|  |         draw(8, 0, tileset[metatile[1]]) | ||
|  |         draw(0, 8, tileset[metatile[2]]) | ||
|  |         draw(8, 8, tileset[metatile[3]]) | ||
|  |         self.__tile_cache[(tileset_id, tile_id)] = tile | ||
|  |         return tile | ||
|  | 
 | ||
|  |     def get_tileset(self, tileset_id): | ||
|  |         subtiles = [0] * 0x100 | ||
|  |         for n in range(0, 0x20): | ||
|  |             subtiles[n] = (0x0F << 10) + (self.tilesets[tileset_id].main_id << 4) + n | ||
|  |         for n in range(0x20, 0x80): | ||
|  |             subtiles[n] = (0x0C << 10) + 0x100 + n | ||
|  |         for n in range(0x80, 0x100): | ||
|  |             subtiles[n] = (0x0C << 10) + n | ||
|  | 
 | ||
|  |         addr = (0x000, 0x000, 0x2B0, 0x2C0, 0x2D0, 0x2E0, 0x2F0, 0x2D0, 0x300, 0x310, 0x320, 0x2A0, 0x330, 0x350, 0x360, 0x340, 0x370)[self.tilesets[tileset_id].animation_id or 3] | ||
|  |         for n in range(0x6C, 0x70): | ||
|  |             subtiles[n] = (0x0C << 10) + addr + n - 0x6C | ||
|  |         return subtiles |