AzurLaneAutoScript/dev_tools/button_extract.py

227 lines
7.8 KiB
Python
Raw Permalink Normal View History

2020-03-29 01:22:46 +08:00
import os
2021-11-08 23:29:19 +08:00
import imageio
2020-03-29 01:22:46 +08:00
import numpy as np
2022-01-02 00:40:38 +08:00
from tqdm.contrib.concurrent import process_map
2020-03-29 01:22:46 +08:00
2022-04-15 03:37:54 +08:00
from module.base.utils import get_bbox, get_color, image_size, load_image
2022-01-02 00:40:38 +08:00
from module.config.config_manual import ManualConfig as AzurLaneConfig
from module.config.server import VALID_SERVER
2020-03-29 01:22:46 +08:00
from module.logger import logger
MODULE_FOLDER = './module'
BUTTON_FILE = 'assets.py'
IMPORT_EXP = """
from module.base.button import Button
from module.base.template import Template
# This file was automatically generated by dev_tools/button_extract.py.
2020-07-15 23:33:38 +08:00
# Don't modify it manually.
2020-03-29 01:22:46 +08:00
"""
IMPORT_EXP = IMPORT_EXP.strip().split('\n') + ['']
class ImageExtractor:
2021-11-08 23:29:19 +08:00
def __init__(self, module, file):
2020-03-29 01:22:46 +08:00
"""
Args:
module(str):
2021-11-08 23:29:19 +08:00
file(str): xxx.png or xxx.gif
2020-03-29 01:22:46 +08:00
"""
self.module = module
2020-07-24 11:13:23 +08:00
self.name, self.ext = os.path.splitext(file)
2020-05-25 22:05:42 +08:00
self.area, self.color, self.button, self.file = {}, {}, {}, {}
for server in VALID_SERVER:
self.load(server)
2020-03-29 01:22:46 +08:00
2020-05-25 22:05:42 +08:00
def get_file(self, genre='', server='cn'):
2021-11-08 23:29:19 +08:00
for ext in ['.png', '.gif']:
file = f'{self.name}.{genre}{ext}' if genre else f'{self.name}{ext}'
file = os.path.join(AzurLaneConfig.ASSETS_FOLDER, server, self.module, file).replace('\\', '/')
if os.path.exists(file):
return file
ext = '.png'
file = f'{self.name}.{genre}{ext}' if genre else f'{self.name}{ext}'
file = os.path.join(AzurLaneConfig.ASSETS_FOLDER, server, self.module, file).replace('\\', '/')
2020-03-29 01:22:46 +08:00
return file
2021-11-08 23:29:19 +08:00
def extract(self, file):
if os.path.splitext(file)[1] == '.gif':
# In a gif Button, use the first image.
bbox = None
mean = None
for image in imageio.mimread(file):
image = image[:, :, :3] if len(image.shape) == 3 else image
new_bbox, new_mean = self._extract(image, file)
if bbox is None:
bbox = new_bbox
elif bbox != new_bbox:
logger.warning(f'{file} has multiple different bbox, this will cause unexpected behaviour')
if mean is None:
mean = new_mean
return bbox, mean
else:
2022-01-29 23:49:15 +08:00
image = load_image(file)
2021-11-08 23:29:19 +08:00
return self._extract(image, file)
2020-03-29 01:22:46 +08:00
@staticmethod
2021-11-08 23:29:19 +08:00
def _extract(image, file):
2022-01-29 23:49:15 +08:00
size = image_size(image)
if size != (1280, 720):
logger.warning(f'{file} has wrong resolution: {size}')
bbox = get_bbox(image)
2020-03-29 01:22:46 +08:00
mean = get_color(image=image, area=bbox)
mean = tuple(np.rint(mean).astype(int))
return bbox, mean
2020-05-25 22:05:42 +08:00
def load(self, server='cn'):
2021-11-08 23:29:19 +08:00
file = self.get_file(server=server)
if os.path.exists(file):
area, color = self.extract(file)
2020-05-25 22:05:42 +08:00
button = area
2021-11-08 23:29:19 +08:00
override = self.get_file('AREA', server=server)
if os.path.exists(override):
area, _ = self.extract(override)
override = self.get_file('COLOR', server=server)
if os.path.exists(override):
_, color = self.extract(override)
override = self.get_file('BUTTON', server=server)
if os.path.exists(override):
button, _ = self.extract(override)
2020-05-25 22:05:42 +08:00
self.area[server] = area
self.color[server] = color
self.button[server] = button
2021-11-08 23:29:19 +08:00
self.file[server] = file
2020-05-25 22:05:42 +08:00
else:
logger.attr(server, f'{self.name} not found, use cn server assets')
self.area[server] = self.area['cn']
self.color[server] = self.color['cn']
self.button[server] = self.button['cn']
self.file[server] = self.file['cn']
2020-03-29 01:22:46 +08:00
@property
def expression(self):
2020-05-25 22:05:42 +08:00
return '%s = Button(area=%s, color=%s, button=%s, file=%s)' % (
self.name, self.area, self.color, self.button, self.file)
2020-03-29 01:22:46 +08:00
class TemplateExtractor(ImageExtractor):
# def __init__(self, module, file, config):
# """
# Args:
# module(str):
# file(str): xxx.png
# config(AzurLaneConfig):
# """
# self.module = module
# self.file = file
# self.config = config
@staticmethod
def extract(file):
2022-01-29 23:49:15 +08:00
image = load_image(file)
bbox = get_bbox(image)
mean = get_color(image=image, area=bbox)
mean = tuple(np.rint(mean).astype(int))
return bbox, mean
2020-03-29 01:22:46 +08:00
@property
def expression(self):
2020-05-25 22:05:42 +08:00
return '%s = Template(file=%s)' % (
self.name, self.file)
# return '%s = Template(area=%s, color=%s, button=%s, file=\'%s\')' % (
# self.name, self.area, self.color, self.button,
# self.config.ASSETS_FOLDER + '/' + self.module + '/' + self.name + '.png')
2020-03-29 01:22:46 +08:00
# class OcrExtractor(ImageExtractor):
# @property
# def expression(self):
# return '%s = OcrArea(area=%s, color=%s, button=%s, file=\'%s\')' % (
# self.name, self.area, self.color, self.button,
# self.config.ASSETS_FOLDER + '/' + self.module + '/' + self.name + '.png')
class ModuleExtractor:
2021-11-08 23:29:19 +08:00
def __init__(self, name):
2020-03-29 01:22:46 +08:00
self.name = name
2021-11-08 23:29:19 +08:00
self.folder = os.path.join(AzurLaneConfig.ASSETS_FOLDER, 'cn', name)
2020-03-29 01:22:46 +08:00
@staticmethod
def split(file):
name, ext = os.path.splitext(file)
name, sub = os.path.splitext(name)
return name, sub, ext
def is_base_image(self, file):
_, sub, _ = self.split(file)
return sub == ''
@property
def expression(self):
exp = []
for file in os.listdir(self.folder):
if file[0].isdigit():
continue
if file.startswith('TEMPLATE_'):
2021-11-08 23:29:19 +08:00
exp.append(TemplateExtractor(module=self.name, file=file).expression)
2020-03-29 01:22:46 +08:00
continue
# if file.startswith('OCR_'):
# exp.append(OcrExtractor(module=self.name, file=file, config=self.config).expression)
# continue
if self.is_base_image(file):
2021-11-08 23:29:19 +08:00
exp.append(ImageExtractor(module=self.name, file=file).expression)
2020-03-29 01:22:46 +08:00
continue
exp.sort()
2020-03-29 01:22:46 +08:00
logger.info('Module: %s(%s)' % (self.name, len(exp)))
exp = IMPORT_EXP + exp
return exp
def write(self):
folder = os.path.join(MODULE_FOLDER, self.name)
if not os.path.exists(folder):
os.mkdir(folder)
2022-04-23 16:05:03 +08:00
with open(os.path.join(folder, BUTTON_FILE), 'w', newline='') as f:
2020-03-29 01:22:46 +08:00
for text in self.expression:
f.write(text + '\n')
2022-01-02 00:40:38 +08:00
def worker(module):
me = ModuleExtractor(name=module)
me.write()
2020-03-29 01:22:46 +08:00
class AssetExtractor:
"""
Extract Asset to asset.py.
All the filename of assets should be in uppercase.
Asset name starts with digit will be ignore.
E.g. 2020XXXX.png.
Asset name starts with 'TEMPLATE_' will treat as template.
E.g. TEMPLATE_AMBUSH_EVADE_SUCCESS.png
> TEMPLATE_AMBUSH_EVADE_SUCCESS = Template(file='./assets/handler/TEMPLATE_AMBUSH_EVADE_SUCCESS.png')
Asset name starts other will treat as button.
E.g. GET_MISSION.png
> Button(area=(553, 482, 727, 539), color=(93, 142, 203), button=(553, 482, 727, 539), name='GET_MISSION')
Asset name like XXX.AREA.png, XXX.COLOR.png, XXX.BUTTON.png, will overwrite the attribute of XXX.png.
E.g. BATTLE_STATUS_S.BUTTON.png overwrites the attribute 'button' of BATTLE_STATUS_S
Asset name starts with 'OCR_' will be treat as button.
E.g. OCR_EXERCISE_TIMES.png.
"""
2021-11-08 23:29:19 +08:00
def __init__(self):
2020-03-29 01:22:46 +08:00
logger.info('Assets extract')
2020-05-25 22:05:42 +08:00
2022-01-02 00:40:38 +08:00
modules = [m for m in os.listdir(AzurLaneConfig.ASSETS_FOLDER + '/cn')
if os.path.isdir(os.path.join(AzurLaneConfig.ASSETS_FOLDER + '/cn', m))]
2024-06-28 03:19:37 +08:00
process_map(worker, modules)
2020-03-29 01:22:46 +08:00
2020-07-15 23:33:38 +08:00
if __name__ == '__main__':
2021-11-08 23:29:19 +08:00
ae = AssetExtractor()