diff --git a/.gitignore b/.gitignore index fef90a5..be75c74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ scripts/incident_generator/output/ +scripts/art_generator/test/ diff --git a/scripts/art_generator/art_set_generator.py b/scripts/art_generator/art_set_generator.py new file mode 100644 index 0000000..f221737 --- /dev/null +++ b/scripts/art_generator/art_set_generator.py @@ -0,0 +1,108 @@ +# This script generates an entire characters/ folder + +from tt3k_dw9_art_tool import ArtTool +import argparse +import yaml +import pprint +from path_type import PathType +from pathlib import Path + + +class ArtSetGenerator: + + CONFIG_DIR = "config" + PORTRAIT_SET_CONFIG = "portrait_set_config.yaml" + + def read_portrait_set_config(self): + portrait_set_config_path = Path(self.CONFIG_DIR).joinpath(self.PORTRAIT_SET_CONFIG) + + with open(portrait_set_config_path, 'r') as portrait_set_config_file: + portrait_set_config_data = yaml.safe_load(portrait_set_config_file) + + return portrait_set_config_data + + + def read_portrait_set(self, portrait_set_file_name): + portrait_set_path = Path(self.CONFIG_DIR).joinpath(portrait_set_file_name) + + with open(portrait_set_path, 'r') as portrait_set_file: + portrait_set_data = yaml.safe_load(portrait_set_file) + + return portrait_set_data + + + def build_portrait_set(self, build_target, target_dir): + config_data = self.read_portrait_set_config() + + # logic + # get load order, pull load order yaml files + # loop through arts in config data + # check if load order name exists, if it does, run the art tool on the ps_data + load_order = config_data.get("art_set_build_priority").get(build_target).get("priority") + + #create art tool object + art_tool = ArtTool() + + #loop through load order and load each portrait set yaml + #for now just only load the first one + ps_data = {} + for load_order_set in load_order: + portrait_set = self.read_portrait_set(config_data.get("art_sets").get(load_order_set).get("file_name")) + ps_data.update({load_order_set: portrait_set}) + + # loop through arts + arts = config_data.get("arts") + for art, data in arts.items(): + # check to see which art set to load based on priority + selected_art_set = "" + for load_order_set in load_order: + if load_order_set in data.get("art_sets"): + selected_art_set = load_order_set + + # skip this art if there are no matching sets from the priority list + if selected_art_set == "": + continue + + # get art and create it + art_data = ps_data.get(selected_art_set) + character_art_data = art_data.get("arts").get(art) + pp = pprint.PrettyPrinter(indent=4) + #pp.pprint(character_art_data) + + #run art tool here + char_source_dir = Path(config_data.get("source_dir")).joinpath(config_data.get("art_sets").get(selected_art_set).get("dir")).joinpath(character_art_data.get("src_dir")) + char_target_dir = Path(target_dir).joinpath(character_art_data.get("char_dir_name")) + char_card = character_art_data.get("char_file_name") + char_element = character_art_data.get("element") + char_gender = character_art_data.get("gender") + char_type = character_art_data.get("type") + if char_type == "generic": + char_is_generic = True + elif char_type == "ca_unique" or char_type == "unique": + char_is_generic = False + else: + raise Exception("Error when processing character {}. {} is not a valid value for character type.".format(char_source_dir, char_type)) + + print(char_source_dir) + print(char_target_dir) + print(char_card) + print(char_element) + print(char_gender) + print(char_is_generic) + art_tool.build_target_folder_structure(char_source_dir, char_target_dir, char_card, char_element, char_gender, char_is_generic) + +def main(): + build_target = args.build_target + target_dir = args.target_dir + + art_set_generator = ArtSetGenerator() + art_set_generator.build_portrait_set(build_target, target_dir) + pass + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Builds entire portrait set for the TT3K_DW9 mod') + parser.add_argument("--build_target", required=True, help="source folder", type=str) + parser.add_argument("--target_dir", required=True, help="target folder", type=str) + args = parser.parse_args() + main() diff --git a/scripts/art_generator/build_unique_art_from_generic_sets b/scripts/art_generator/build_unique_art_from_generic_sets deleted file mode 100644 index feac60d..0000000 --- a/scripts/art_generator/build_unique_art_from_generic_sets +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -######################################################################################################################## -# This script is used to build unique portrait sets from generics provided by CA -######################################################################################################################## - -import png -import sys -import argparse -from path_type import PathType -from PIL import Image -from pathlib import Path - - -def main(): - pass - - -def build_element_set(): - pass - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Process generic elemental folder and build custom generic/unique folders') - parser.add_argument("--source_dir", required=True, help="source folder, must be the data/UI/characters/ folder and must have the elemental folders", type=str) - parser.add_argument("--target_dir", required=True, help="will output similar to what is in the data/UI/characters/ folder", type=str) - args = parser.parse_args() - main() diff --git a/scripts/art_generator/build_unique_art_from_generic_sets.py b/scripts/art_generator/build_unique_art_from_generic_sets.py new file mode 100644 index 0000000..8cd952e --- /dev/null +++ b/scripts/art_generator/build_unique_art_from_generic_sets.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +######################################################################################################################## +# This script is used to build unique portrait sets from generics provided by CA +######################################################################################################################## + +import png +import sys +import argparse +from path_type import PathType +from PIL import Image +from pathlib import Path + +# Subdirectory names +COMPOSITES_DIR = "composites" +STILLS_DIR = "stills" +BOBBLEHEADS_DIR = "bobbleheads" +HALFBODY_LARGE_DIR = "halfbody_large" +HALFBODY_SMALL_DIR = "halfbody_small" +MINI_DIR = "mini" +UNITCARDS_DIR = "unitcards" +LARGE_PANEL_DIR = "large_panel" +SMALL_PANEL_DIR = "small_panel" +FACES_DIR = "faces" +ANGRY_DIR = "angry" +HAPPY_DIR = "happy" +NORMAL_DIR = "normal" +LARGE_DIR = "large" + +# Sub directory dictionary +SUBDIR_DICTS = [{'dir': BOBBLEHEADS_DIR, 'img_key': BOBBLEHEADS_KEY, 'img_large_key': BOBBLEHEADS_LARGE_KEY}, + {'dir': HALFBODY_LARGE_DIR, 'img_key': HALFBODY_LARGE_KEY, 'img_large_key': HALFBODY_LARGE_LARGE_KEY}, + {'dir': HALFBODY_SMALL_DIR, 'img_key': HALFBODY_SMALL_KEY, 'img_large_key': HALFBODY_SMALL_LARGE_KEY}, + {'dir': MINI_DIR, 'img_key': MINI_LARGE_KEY, 'img_large_key': MINI_LARGE_KEY}, + {'dir': UNITCARDS_DIR, 'img_key': UNITCARD_KEY, 'img_large_key': UNITCARD_LARGE_KEY}] + + +def main(): + pass + + +def build_element_set(element_gender_dir): + composite_dir = element_gender_dir.joinpath(COMPOSITES_DIR) + stills_dir = element_gender_dir.joinpath(STILLS_DIR) + + for subdir_dict in SUBDIR_DICTS: + subdir = stills_dir.joinpath(subdir_dict.get('dir')) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Process generic elemental folder and build custom generic/unique folders') + parser.add_argument("--source_dir", required=True, help="source folder, must be the data/UI/characters/ folder and must have the elemental folders", type=str) + parser.add_argument("--target_dir", required=True, help="will output similar to what is in the data/UI/characters/ folder", type=str) + args = parser.parse_args() + main() diff --git a/scripts/art_generator/config/art_tt3k_dw9_portraits.yaml b/scripts/art_generator/config/art_tt3k_dw9_portraits.yaml new file mode 100644 index 0000000..80a1e3d --- /dev/null +++ b/scripts/art_generator/config/art_tt3k_dw9_portraits.yaml @@ -0,0 +1,1590 @@ +enabled: True +name: tt3k_dw9_portraits +source_dir: /mnt/c/Users/zades/Pictures/tt3k_workspace/dw9/generals/ +arts: + bao_sanniang: + src_dir: bao_sanniang + char_dir_name: 3k_main_hero_special_wood_lady_bao_sanniang + char_file_name: 3k_main_hero_special_wood_lady_bao_sanniang + element: wood + type: unique + gender: female + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cai_wenji: + src_dir: cai_wenji + char_dir_name: 3k_main_hero_special_water_lady_cai_yan + char_file_name: 3k_main_hero_special_water_lady_cai_yan + element: water + type: generic + gender: female + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cao_cao: + src_dir: cao_cao + char_dir_name: 3k_main_hero_special_earth_cao_cao + char_file_name: 3k_main_hero_special_earth_cao_cao + element: earth + type: ca_unique + gender: male + generic_fallback_number: 10 + complex_composite: True + complex_composite_data: + - mood: angry + images: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + - mood: happy + images: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + - mood: norm + images: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cao_pi: + src_dir: cao_pi + char_dir_name: 3k_main_hero_special_earth_cao_pi + char_file_name: 3k_main_hero_special_earth_cao_pi + element: earth + type: generic + gender: male + generic_fallback_number: 05 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cao_ren: + src_dir: cao_ren + char_dir_name: 3k_main_hero_special_earth_cao_ren + char_file_name: 3k_main_hero_special_earth_cao_ren + element: metal + type: unique + gender: male + generic_fallback_number: 06 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cao_xiu: + src_dir: cao_xiu + char_dir_name: 3k_main_hero_special_earth_cao_xiu + char_file_name: 3k_main_hero_special_earth_cao_xiu + element: fire + type: generic + gender: male + generic_fallback_number: 05 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + chen_gong: + src_dir: chen_gong + char_dir_name: 3k_main_hero_special_water_chen_gong + char_file_name: 3k_main_hero_special_water_chen_gong + element: water + type: generic + gender: male + generic_fallback_number: 10 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + cheng_pu: + src_dir: cheng_pu + char_dir_name: 3k_main_hero_special_metal_cheng_pu + char_file_name: 3k_main_hero_special_metal_cheng_pu + element: metal + type: generic + gender: male + generic_fallback_number: 10 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + da_qiao: + src_dir: da_qiao + char_dir_name: 3k_main_hero_special_earth_lady_da_qiao + char_file_name: 3k_main_hero_special_earth_lady_da_qiao + element: earth + type: generic + gender: female + generic_fallback_number: 03 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + deng_ai: + src_dir: deng_ai + char_dir_name: 3k_main_hero_special_metal_deng_ai + char_file_name: 3k_main_hero_special_metal_deng_ai + element: metal + type: generic + gender: male + generic_fallback_number: 12 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + dian_wei: + src_dir: dian_wei + char_dir_name: 3k_main_hero_special_wood_dian_wei + char_file_name: 3k_main_hero_special_wood_dian_wei + element: wood + type: ca_unique + gender: male + generic_fallback_number: 43 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + diao_chan: + src_dir: diao_chan + char_dir_name: 3k_main_hero_special_water_lady_diao_chan + char_file_name: 3k_main_hero_special_water_lady_diao_chan + element: water + type: unique + gender: female + generic_fallback_number: 10 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + ding_feng: + src_dir: ding_feng + char_dir_name: 3k_main_hero_special_metal_ding_feng + char_file_name: 3k_main_hero_special_metal_ding_feng + element: metal + type: generic + gender: male + generic_fallback_number: 13 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + dong_bai: + src_dir: dong_bai + char_dir_name: 3k_main_hero_special_metal_lady_dong_bai + char_file_name: 3k_main_hero_special_metal_lady_dong_bai + element: metal + type: generic + gender: female + generic_fallback_number: 08 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + dong_zhuo: + src_dir: dong_zhuo + char_dir_name: 3k_main_hero_special_fire_dong_zhuo + char_file_name: 3k_main_hero_special_fire_dong_zhuo + element: fire + type: ca_unique + gender: male + generic_fallback_number: 14 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + fa_zheng: + src_dir: fa_zheng + char_dir_name: 3k_main_hero_special_water_fa_zheng + char_file_name: 3k_main_hero_special_water_fa_zheng + element: water + type: generic + gender: male + generic_fallback_number: 22 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + gan_ning: + src_dir: gan_ning + char_dir_name: 3k_main_hero_special_fire_gan_ning + char_file_name: 3k_main_hero_special_fire_gan_ning + element: fire + type: ca_unique + gender: male + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guan_ping: + src_dir: guan_ping + char_dir_name: 3k_main_hero_special_fire_guan_ping + char_file_name: 3k_main_hero_special_fire_guan_ping + element: fire + type: generic + gender: male + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guan_suo: + src_dir: guan_suo + char_dir_name: 3k_main_hero_special_earth_guan_suo + char_file_name: 3k_main_hero_special_earth_guan_suo + element: earth + type: generic + gender: male + generic_fallback_number: 29 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guan_xing: + src_dir: guan_xing + char_dir_name: 3k_main_hero_special_wood_guan_xing + char_file_name: 3k_main_hero_special_wood_guan_xing + element: wood + type: generic + gender: male + generic_fallback_number: 14 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guan_yinping: + src_dir: guan_yinping + char_dir_name: 3k_main_hero_special_wood_lady_guan_yinping + char_file_name: 3k_main_hero_special_wood_lady_guan_yinping + element: wood + type: unique + gender: female + generic_fallback_number: 03 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guan_yu: + src_dir: guan_yu + char_dir_name: 3k_main_hero_special_wood_guan_yu + char_file_name: 3k_main_hero_special_wood_guan_yu + element: wood + type: ca_unique + gender: male + generic_fallback_number: 37 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guo_huai: + src_dir: guo_huai + char_dir_name: 3k_main_hero_special_earth_guo_huai + char_file_name: 3k_main_hero_special_earth_guo_huai + element: earth + type: generic + gender: male + generic_fallback_number: 20 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + guo_jia: + src_dir: guo_jia + char_dir_name: 3k_main_hero_special_water_guo_jia + char_file_name: 3k_main_hero_special_water_guo_jia + element: water + type: generic + gender: male + generic_fallback_number: 25 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + han_dang: + src_dir: han_dang + char_dir_name: 3k_main_hero_special_wood_han_dang + char_file_name: 3k_main_hero_special_wood_han_dang + element: wood + type: generic + gender: male + generic_fallback_number: 27 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + hua_xiong: + src_dir: hua_xiong + char_dir_name: 3k_main_hero_special_fire_hua_xiong + char_file_name: 3k_main_hero_special_fire_hua_xiong + element: fire + type: generic + gender: male + generic_fallback_number: 24 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + huang_gai: + src_dir: huang_gai + char_dir_name: 3k_main_hero_special_wood_huang_gai + char_file_name: 3k_main_hero_special_wood_huang_gai + element: wood + type: unique + gender: male + generic_fallback_number: 03 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + huang_zhong: + src_dir: huang_zhong + char_dir_name: 3k_main_hero_special_metal_huang_zhong + char_file_name: 3k_main_hero_special_metal_huang_zhong + element: metal + type: ca_unique + gender: male + generic_fallback_number: 34 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + huang_zhong_water: + src_dir: huang_zhong + char_dir_name: 3k_main_hero_special_water_huang_zhong + char_file_name: 3k_main_hero_special_water_huang_zhong + element: water + type: ca_unique + gender: male + generic_fallback_number: 34 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + jia_chong: + src_dir: jia_chong + char_dir_name: 3k_main_hero_special_water_jia_chong + char_file_name: 3k_main_hero_special_water_hia_chong + element: water + type: generic + gender: male + generic_fallback_number: 19 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + jia_xu: + src_dir: jia_xu + char_dir_name: 3k_main_hero_special_water_jia_xu + char_file_name: 3k_main_hero_special_water_jia_xu + element: water + type: generic + gender: male + generic_fallback_number: 24 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + jiang_wei: + src_dir: jiang_wei + char_dir_name: 3k_main_hero_special_fire_jiang_wei + char_file_name: 3k_main_hero_special_fire_jiang_wei + element: metal + type: generic + gender: male + generic_fallback_number: 02 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + li_dian: + src_dir: li_dian + char_dir_name: 3k_main_hero_special_metal_li_dian + char_file_name: 3k_main_hero_special_metal_li_dian + element: metal + type: generic + gender: male + generic_fallback_number: 24 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lian_shi: + src_dir: lian_shi + char_dir_name: 3k_main_hero_special_wood_lian_shi + char_file_name: 3k_main_hero_special_wood_lian_shi + element: wood + type: unique + gender: female + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + ling_tong: + src_dir: ling_tong + char_dir_name: 3k_main_hero_special_wood_ling_tong + char_file_name: 3k_main_hero_special_wood_ling_tong + element: wood + type: generic + gender: male + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + liu_bei: + src_dir: liu_bei + char_dir_name: 3k_main_hero_special_earth_liu_bei + char_file_name: 3k_main_hero_special_earth_liu_bei + element: earth + type: ca_unique + gender: male + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + liu_bei_historical: + src_dir: liu_bei + char_dir_name: 3k_main_hero_special_earth_liu_bei_historical + char_file_name: 3k_main_hero_special_earth_liu_bei_historical + element: earth + type: ca_unique + gender: male + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + liu_shan: + src_dir: liu_shan + char_dir_name: 3k_main_hero_special_earth_liu_shan + char_file_name: 3k_main_hero_special_earth_liu_shan + element: earth + type: generic + gender: male + generic_fallback_number: 19 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_bu: + src_dir: lu_bu + char_dir_name: 3k_main_hero_special_fire_lu_bu + char_file_name: 3k_main_hero_special_fire_lu_bu + element: fire + type: ca_unique + gender: male + generic_fallback_number: 41 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_bu_historical: + src_dir: lu_bu + char_dir_name: 3k_main_hero_special_fire_lu_bu_historical + char_file_name: 3k_main_hero_special_fire_lu_bu_historical + element: fire + type: ca_unique + gender: male + generic_fallback_number: 41 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_lingqi: + src_dir: lu_lingqi + char_dir_name: 3k_main_hero_special_fire_lady_lu_lingqi + char_file_name: 3k_main_hero_special_fire_lady_lu_lingqi + element: fire + type: unique + gender: female + generic_fallback_number: 13 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_meng: + src_dir: lu_meng + char_dir_name: 3k_main_hero_special_metal_lu_meng + char_file_name: 3k_main_hero_special_metal_lu_meng + element: metal + type: generic + gender: male + generic_fallback_number: 11 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_su: + src_dir: lu_su + char_dir_name: 3k_main_hero_special_water_lu_su + char_file_name: 3k_main_hero_special_water_lu_su + element: water + type: generic + gender: male + generic_fallback_number: 12 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + lu_xun: + src_dir: lu_xun + char_dir_name: 3k_main_hero_special_water_lu_xun + char_file_name: 3k_main_hero_special_water_lu_xun + element: water + type: generic + gender: male + generic_fallback_number: 46 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + ma_chao: + src_dir: ma_chao + char_dir_name: 3k_main_hero_special_fire_ma_chao + char_file_name: 3k_main_hero_special_fire_ma_chao + element: fire + type: ca_unique + gender: male + generic_fallback_number: 37 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + ma_dai: + src_dir: ma_dai + char_dir_name: 3k_main_hero_special_fire_ma_dai + char_file_name: 3k_main_hero_special_fire_ma_dai + element: fire + type: generic + gender: male + generic_fallback_number: 26 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + man_chong: + src_dir: man_chong + char_dir_name: 3k_main_hero_special_fire_man_chong + char_file_name: 3k_main_hero_special_fire_man_chong + element: earth + type: generic + gender: male + generic_fallback_number: 15 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + meng_huo: + src_dir: meng_huo + char_dir_name: 3k_main_hero_special_wood_meng_huo + char_file_name: 3k_main_hero_special_wood_meng_huo + element: wood + type: generic + gender: male + generic_fallback_number: 10 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + pang_de: + src_dir: pang_de + char_dir_name: 3k_main_hero_special_wood_pang_de + char_file_name: 3k_main_hero_special_wood_pang_de + element: wood + type: ca_unique + gender: male + generic_fallback_number: 14 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + pang_tong: + src_dir: pang_tong + char_dir_name: 3k_main_hero_special_water_pang_tong + char_file_name: 3k_main_hero_special_water_pang_tong + element: water + type: generic + gender: male + generic_fallback_number: 25 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sima_shi: + src_dir: sima_shi + char_dir_name: 3k_main_hero_special_earth_sima_shi + char_file_name: 3k_main_hero_special_earth_sima_shi + element: earth + type: generic + gender: male + generic_fallback_number: 31 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sima_yi: + src_dir: sima_yi + char_dir_name: 3k_main_hero_special_water_sima_yi + char_file_name: 3k_main_hero_special_water_sima_yi + element: water + type: ca_unique + gender: male + generic_fallback_number: 27 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sima_zhao: + src_dir: sima_zhao + char_dir_name: 3k_main_hero_special_earth_sima_zhao + char_file_name: 3k_main_hero_special_earth_sima_zhao + element: earth + type: generic + gender: male + generic_fallback_number: 28 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sun_ce: + src_dir: sun_ce + char_dir_name: 3k_main_hero_special_fire_sun_ce + char_file_name: 3k_main_hero_special_fire_sun_ce + element: fire + type: ca_unique + gender: male + generic_fallback_number: 09 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sun_jian: + src_dir: sun_jian + char_dir_name: 3k_main_hero_special_metal_sun_jian + char_file_name: 3k_main_hero_special_metal_sun_jian + element: metal + type: ca_unique + gender: male + generic_fallback_number: 18 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sun_quan: + src_dir: sun_quan + char_dir_name: 3k_main_hero_special_earth_sun_quan + char_file_name: 3k_main_hero_special_earth_sun_quan + element: earth + type: ca_unique + gender: male + generic_fallback_number: 07 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + sun_shangxiang: + src_dir: sun_shangxiang + char_dir_name: 3k_main_hero_special_fire_lady_sun + char_file_name: 3k_main_hero_special_fire_lady_sun + element: fire + type: ca_unique + gender: female + generic_fallback_number: 04 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + taishi_ci: + src_dir: taishi_ci + char_dir_name: 3k_main_hero_special_metal_taishi_ci + char_file_name: 3k_main_hero_special_metal_taishi_ci + element: metal + type: ca_unique + gender: male + generic_fallback_number: 20 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + wang_yi: + src_dir: wang_yi + char_dir_name: 3k_main_hero_special_fire_lady_wang_yi + char_file_name: 3k_main_hero_special_fire_lady_wang_yi + element: fire + type: unique + gender: female + generic_fallback_number: 29 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + wang_yuanji: + src_dir: wang_yuanji + char_dir_name: 3k_main_hero_special_earth_lady_wang_yuanji + char_file_name: 3k_main_hero_special_earth_lady_wang_yuanji + element: earth + type: generic + gender: female + generic_fallback_number: 09 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + wei_yan: + src_dir: wei_yan + char_dir_name: 3k_main_hero_special_fire_wei_yan + char_file_name: 3k_main_hero_special_fire_wei_yan + element: fire + type: generic + gender: male + generic_fallback_number: 15 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: 30 + y_pos: 25 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + wen_yang: + src_dir: wen_yang + char_dir_name: 3k_main_hero_special_wood_wen_yang + char_file_name: 3k_main_hero_special_wood_wen_yang + element: wood + type: generic + gender: male + generic_fallback_number: 23 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xiahou_ba: + src_dir: xiahou_ba + char_dir_name: 3k_main_hero_special_wood_xiahou_ba + char_file_name: 3k_main_hero_special_wood_xiahou_ba + element: wood + type: generic + gender: male + generic_fallback_number: 15 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xiahou_dun: + src_dir: xiahou_dun + char_dir_name: 3k_main_hero_special_wood_xiahou_dun + char_file_name: 3k_main_hero_special_wood_xiahou_dun + element: wood + type: ca_unique + gender: male + generic_fallback_number: 17 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xiahou_ji: + src_dir: xiahou_ji + char_dir_name: 3k_main_hero_special_water_lady_xiahou_ji + char_file_name: 3k_main_hero_special_water_lady_xiahou_ji + element: water + type: generic + gender: female + generic_fallback_number: 38 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xiahou_yuan: + src_dir: xiahou_yuan + char_dir_name: 3k_main_hero_special_fire_xiahou_yuan + char_file_name: 3k_main_hero_special_fire_xiahou_yuan + element: fire + type: ca_unique + gender: male + generic_fallback_number: 22 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xiao_qiao: + src_dir: xiao_qiao + char_dir_name: 3k_main_hero_special_metal_lady_xiao_qiao + char_file_name: 3k_main_hero_special_metal_lady_xiao_qiao + element: metal + type: generic + gender: female + generic_fallback_number: 21 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xin_xianying: + src_dir: xin_xianying + char_dir_name: 3k_main_hero_special_water_lady_xin_xianying + char_file_name: 3k_main_hero_special_water_lady_xin_xianying + element: water + type: generic + gender: female + generic_fallback_number: 18 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xing_cai: + src_dir: xing_cai + char_dir_name: 3k_main_hero_special_metal_lady_xing_cai + char_file_name: 3k_main_hero_special_metal_lady_xing_cai + element: metal + type: generic + gender: female + generic_fallback_number: 05 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xu_huang: + src_dir: xu_huang + char_dir_name: 3k_main_hero_special_metal_xu_huang + char_file_name: 3k_main_hero_special_metal_xu_huang + element: metal + type: ca_unique + gender: male + generic_fallback_number: 27 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xu_sheng: + src_dir: xu_sheng + char_dir_name: 3k_main_hero_special_fire_xu_sheng + char_file_name: 3k_main_hero_special_fire_xu_sheng + element: fire + type: generic + gender: male + generic_fallback_number: 10 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xu_shu: + src_dir: xu_shu + char_dir_name: 3k_main_hero_special_water_xu_shu + char_file_name: 3k_main_hero_special_water_xu_shu + element: water + type: generic + gender: male + generic_fallback_number: 45 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xu_zhu: + src_dir: xu_zhu + char_dir_name: 3k_main_hero_special_wood_xu_zhu + char_file_name: 3k_main_hero_special_wood_xu_zhu + element: wood + type: ca_unique + gender: male + generic_fallback_number: 30 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xun_you: + src_dir: xun_you + char_dir_name: 3k_main_hero_special_earth_xun_you + char_file_name: 3k_main_hero_special_earth_xun_you + element: water + type: unique + gender: male + generic_fallback_number: 42 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + xun_yu: + src_dir: xun_yu + char_dir_name: 3k_main_hero_special_water_xun_yu + char_file_name: 3k_main_hero_special_water_xun_yu + element: water + type: unique + gender: male + generic_fallback_number: 23 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + yuan_shao: + src_dir: yuan_shao + char_dir_name: 3k_main_hero_special_earth_yuan_shao + char_file_name: 3k_main_hero_special_earth_yuan_shao + element: earth + type: ca_unique + gender: male + generic_fallback_number: 02 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + yuan_shu: + src_dir: yuan_shu + char_dir_name: 3k_main_hero_special_earth_yuan_shu + char_file_name: 3k_main_hero_special_earth_yuan_shu + element: earth + type: ca_unique + gender: male + generic_fallback_number: 03 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + yu_jin: + src_dir: yu_jin + char_dir_name: 3k_main_hero_special_metal_yu_jin + char_file_name: 3k_main_hero_special_metal_yu_jin + element: metal + type: generic + gender: male + generic_fallback_number: 04 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + yue_jin: + src_dir: yue_jin + char_dir_name: 3k_main_hero_special_metal_yue_jin + char_file_name: 3k_main_hero_special_metal_yue_jin + element: metal + type: ca_unique + gender: male + generic_fallback_number: 05 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + yue_ying: + src_dir: yue_ying + char_dir_name: 3k_main_hero_special_wood_lady_huang_yueying + char_file_name: 3k_main_hero_special_wood_lady_huang_yueying + element: wood + type: unique + gender: female + generic_fallback_number: 05 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_bao: + src_dir: zhang_bao + char_dir_name: 3k_main_hero_special_metal_zhang_bao + char_file_name: 3k_main_hero_special_metal_zhang_bao + element: metal + type: generic + gender: male + generic_fallback_number: 20 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_chunhua: + src_dir: zhang_chunhua + char_dir_name: 3k_main_hero_special_metal_lady_zhang_chunhua + char_file_name: 3k_main_hero_special_metal_lady_zhang_chunhua + element: metal + type: generic + gender: female + generic_fallback_number: 15 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_fei: + src_dir: zhang_fei + char_dir_name: 3k_main_hero_special_fire_zhang_fei + char_file_name: 3k_main_hero_special_fire_zhang_fei + element: fire + type: ca_unique + gender: male + generic_fallback_number: 30 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_he: + src_dir: zhang_he + char_dir_name: 3k_main_hero_special_fire_zhang_he + char_file_name: 3k_main_hero_special_fire_zhang_he + element: fire + type: generic + gender: male + generic_fallback_number: 50 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_liao: + src_dir: zhang_liao + char_dir_name: 3k_main_hero_special_metal_zhang_liao + char_file_name: 3k_main_hero_special_metal_zhang_liao + element: metal + type: ca_unique + gender: male + generic_fallback_number: 23 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhang_jiao: + src_dir: zhang_jiao + char_dir_name: 3k_ytr_hero_special_healer_zhang_jiao + char_file_name: 3k_ytr_hero_special_healer_zhang_jiao + element: healer + type: generic + gender: male + generic_fallback_number: 09 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhao_yun: + src_dir: zhao_yun + char_dir_name: 3k_main_hero_special_metal_zhao_yun + char_file_name: 3k_main_hero_special_metal_zhao_yun + element: metal + type: ca_unique + gender: male + generic_fallback_number: 14 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhong_hui: + src_dir: zhong_hui + char_dir_name: 3k_main_hero_special_earth_zhong_hui + char_file_name: 3k_main_hero_special_earth_zhong_hui + element: earth + type: generic + gender: male + generic_fallback_number: 37 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhou_cang: + src_dir: zhou_cang + char_dir_name: 3k_main_hero_special_fire_zhou_cang + char_file_name: 3k_main_hero_special_fire_zhou_cang + element: fire + type: generic + gender: male + generic_fallback_number: 46 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhen_ji: + src_dir: zhen_ji + char_dir_name: 3k_main_hero_special_earth_lady_zhen_ji + char_file_name: 3k_main_hero_special_earth_lady_zhen_ji + element: earth + type: generic + gender: female + generic_fallback_number: 09 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhou_tai: + src_dir: zhou_tai + char_dir_name: 3k_main_hero_special_fire_zhou_tai + char_file_name: 3k_main_hero_special_fire_zhou_tai + element: fire + type: generic + gender: male + generic_fallback_number: 18 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhou_yu: + src_dir: zhou_yu + char_dir_name: 3k_main_hero_special_water_zhou_yu + char_file_name: 3k_main_hero_special_water_zhou_yu + element: water + type: ca_unique + gender: male + generic_fallback_number: 31 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhou_yu_historical: + src_dir: zhou_yu + char_dir_name: 3k_main_hero_special_water_zhou_yu_historical + char_file_name: 3k_main_hero_special_water_zhou_yu_historical + element: water + type: ca_unique + gender: male + generic_fallback_number: 31 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhu_ran: + src_dir: zhu_ran + char_dir_name: 3k_main_hero_special_fire_zhu_ran + char_file_name: 3k_main_hero_special_fire_zhu_ran + element: fire + type: generic + gender: male + generic_fallback_number: 16 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhu_rong: + src_dir: zhu_rong + char_dir_name: 3k_main_hero_special_fire_lady_zhu_rong + char_file_name: 3k_main_hero_special_fire_lady_zhu_rong + element: fire + type: unique + gender: female + generic_fallback_number: 01 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhuge_dan: + src_dir: zhuge_dan + char_dir_name: 3k_main_hero_special_fire_zhuge_dan + char_file_name: 3k_main_hero_special_fire_zhuge_dan + element: fire + type: generic + gender: male + generic_fallback_number: 41 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zhuge_liang: + src_dir: zhuge_liang + char_dir_name: 3k_main_hero_special_water_zhuge_liang + char_file_name: 3k_main_hero_special_water_zhuge_liang + element: water + type: ca_unique + gender: male + generic_fallback_number: 29 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 + zuo_ci: + src_dir: zuo_ci + char_dir_name: 3k_main_hero_special_water_zuo_ci + char_file_name: 3k_main_hero_special_water_zuo_ci + element: water + type: generic + gender: male + generic_fallback_number: 31 + complex_composite: False + simple_composite_data: + - name: head.png + x_pos: -25 + y_pos: -75 + z_order: 0 + x_pivot: 0.5000 + y_pivot: 0.5000 diff --git a/scripts/art_generator/config/portrait_set_config.yaml b/scripts/art_generator/config/portrait_set_config.yaml new file mode 100644 index 0000000..0b71f64 --- /dev/null +++ b/scripts/art_generator/config/portrait_set_config.yaml @@ -0,0 +1,498 @@ +enabled: True +source_dir: /mnt/d/Projects/tt3k_dw9_art/portraits/ +art_sets: + tt3k_dw9_portraits: + dir: dw9 + file_name: art_tt3k_dw9_portraits.yaml + tt3k_dw9_alt: + dir: dw9_alt + file_name: art_tt3k_dw9_portraits_alt.yaml + sad_puzzle: + dir: sad_puzzle + file_name: sad_puzzle_portraits.yaml + generic_placeholder: + dir: generic_placeholder + file_name: generic_placeholder_portraits.yaml +art_set_build_priority: + tt3k_dw9_portraits_only: + priority: + - tt3k_dw9_portraits + tt3k_dw9_portraits_main: + priority: + - tt3k_dw9_portraits + - sad_puzzle + - generic_placeholder + tt3k_dw9_portraits_alt: + priority: + - tt3k_dw9_alt + - sad_puzzle + - generic_placeholder + generic_placeholder: + priority: + - generic_placeholder +arts: + bian_huilan: + art_sets: + ? generic_placeholder + bao_sanniang: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cai_wenji: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cao_cao: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cao_pi: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cao_ren: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cao_xiu: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + chen_gong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + cheng_pu: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + da_qiao: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + deng_ai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + dian_wei: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + diao_chan: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + ding_feng: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + dong_bai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + dong_zhuo: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + fa_zheng: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + gan_ning: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guan_ping: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guan_suo: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guan_xing: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guan_yinping: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guan_yu: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guo_huai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + guo_jia: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + han_dang: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + hua_xiong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + huang_gai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + huang_zhong: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + huang_zhong_water: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + jia_chong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + jia_xu: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + jiang_wei: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + li_dian: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lian_shi: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + ling_tong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + liu_bei: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + liu_bei_historical: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + liu_shan: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_bu: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_bu_historical: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_lingqi: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_meng: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_su: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + lu_xun: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + ma_chao: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + ma_dai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + man_chong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + meng_huo: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + pang_de: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + pang_tong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sima_shi: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sima_yi: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sima_zhao: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sun_ce: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sun_jian: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sun_quan: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + sun_shangxiang: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + taishi_ci: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + wang_yi: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + wang_yuanji: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + wei_yan: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + wen_yang: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xiahou_ba: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xiahou_dun: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xiahou_ji: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xiahou_yuan: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xiao_qiao: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xin_xianying: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xing_cai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xu_huang: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xu_sheng: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xu_shu: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xu_zhu: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xun_you: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + xun_yu: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + yuan_shao: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + yuan_shu: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + yu_jin: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + yue_jin: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + yue_ying: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_bao: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_chunhua: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_fei: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_he: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_liao: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhang_jiao: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhao_yun: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhong_hui: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhou_cang: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhen_ji: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhou_tai: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhou_yu: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhou_yu_historical: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhu_ran: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhu_rong: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhuge_dan: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zhuge_liang: + art_sets: + ? tt3k_dw9_portraits + ? tt3k_dw9_alt + zuo_ci: + art_sets: + ? generic_placeholder + ? tt3k_dw9_portraits + ? tt3k_dw9_alt diff --git a/scripts/art_generator/tt3k_dw9_art_tool.py b/scripts/art_generator/tt3k_dw9_art_tool.py index b25d046..f541493 100644 --- a/scripts/art_generator/tt3k_dw9_art_tool.py +++ b/scripts/art_generator/tt3k_dw9_art_tool.py @@ -1,78 +1,525 @@ -#!/usr/bin/env python3 - ######################################################################################################################## -# This script is used to convert images and build image folders for characters. It can also be used to convert between +# This class is used to convert images and build image folders for characters. It can also be used to convert between # image folders. ######################################################################################################################## import png import sys import argparse +import yaml from path_type import PathType -from PIL import Image +from PIL import Image #this is Pillow and not PIL from pathlib import Path +from distutils.dir_util import copy_tree + + +class ArtTool: + # Image Constants + TRANSPARENT_BACKGROUND = "transparent" + CENTER = "center" + PNG = "PNG" + RGBA = "RGBA" + + # Image sizes + BOBBLEHEADS_LARGE_SIZE = 134, 220 + BOBBLEHEADS_SIZE = 84, 138 + HALFBODY_LARGE_LARGE_SIZE = 499, 400 + HALFBODY_LARGE_SIZE = 312, 250 + HALFBODY_SMALL_LARGE_SIZE = 176, 134 + HALFBODY_SMALL_SIZE = 110, 84 + MINI_LARGE_SIZE = 48, 48 + MINI_SIZE = 30, 30 + UNITCARD_LARGE_SIZE = 131, 435 + UNITCARD_SIZE = 82, 272 + BLANK_SIZE = 1, 1 + + # Subdirectory names + COMPOSITES_DIR = "composites" + STILLS_DIR = "stills" + BOBBLEHEADS_DIR = "bobbleheads" + HALFBODY_LARGE_DIR = "halfbody_large" + HALFBODY_SMALL_DIR = "halfbody_small" + MINI_DIR = "mini" + UNITCARDS_DIR = "unitcards" + LARGE_PANEL_DIR = "large_panel" + SMALL_PANEL_DIR = "small_panel" + FACES_DIR = "faces" + ANGRY_DIR = "angry" + HAPPY_DIR = "happy" + NORMAL_DIR = "norm" + LARGE_DIR = "large" + + # Image references for the dictionary + COMPOSITE_LARGE_KEY = "composite_large_key" + BOBBLEHEADS_LARGE_KEY = "bobbleheads_large_key" + BOBBLEHEADS_KEY = "bobbleheads_key" + HALFBODY_LARGE_LARGE_KEY = "halfbody_large_large_key" + HALFBODY_LARGE_KEY = "halfbody_large_key" + HALFBODY_SMALL_LARGE_KEY = "halfbody_small_large_key" + HALFBODY_SMALL_KEY = "halfbody_small_key" + MINI_LARGE_KEY = "mini_large_key" + MINI_KEY = "mini_key" + UNITCARD_LARGE_KEY = "unitcard_large_key" + UNITCARD_KEY = "unitcard_key" + + # Sub directory dictionary + SUBDIR_DICTS = [{'dir': BOBBLEHEADS_DIR, 'img_key': BOBBLEHEADS_KEY, 'img_large_key': BOBBLEHEADS_LARGE_KEY}, + {'dir': HALFBODY_LARGE_DIR, 'img_key': HALFBODY_LARGE_KEY, + 'img_large_key': HALFBODY_LARGE_LARGE_KEY}, + {'dir': HALFBODY_SMALL_DIR, 'img_key': HALFBODY_SMALL_KEY, + 'img_large_key': HALFBODY_SMALL_LARGE_KEY}, + {'dir': MINI_DIR, 'img_key': MINI_LARGE_KEY, 'img_large_key': MINI_LARGE_KEY}, + {'dir': UNITCARDS_DIR, 'img_key': UNITCARD_KEY, 'img_large_key': UNITCARD_LARGE_KEY}] + + # PNG Chuck Stuff + TEXT_CHUNK_FLAG = b'tEXt' + DEFAULT_X = '-25' + DEFAULT_Y = '-75' + DEFAULT_PIVOT_X = '0.5000' + DEFAULT_PIVOT_Y = '0.5000' + + # Composites information + COMPOSITES_CONFIG_FILE = "composites.yaml" + ENABLED = "enabled" + ARTS = "arts" + FILE = "file" + TYPE = "type" + HAPPY = "happy" + SAD = "sad" + ANGRY = "angry" + TYPE_BLANK = "blank" + TYPE_REPLACE = "replace" + LOCATIONS = "locations" + PATH = "path" + SOURCE = "source" + X_POS = "x_pos" + Y_POS = "y_pos" + Z_ORDER = "z_order" + X_PIVOT = "x_pivot" + Y_PIVOT = "y_pivot" + + + # Takes a folder with base 5 large version of the required images and builds a image dictionary from them + def create_image_dict(self, source_dir): + img_dict = {} + + composite = "head.png" + bobbleheads_large = "bobbleheads_large.png" + halfbody_large_large = "halfbody_large_large.png" + mini_large = "mini_large.png" + unitcard_large = "unitcard_large.png" + + composite_file = Path(source_dir).joinpath(composite) + bobbleheads_large_file = Path(source_dir).joinpath(bobbleheads_large) + halfbody_large_large_file = Path(source_dir).joinpath(halfbody_large_large) + mini_large_file = Path(source_dir).joinpath(mini_large) + unitcard_large_file = Path(source_dir).joinpath(unitcard_large) + + # create full set from starting 5 images + composite_img = Image.open(composite_file) + img_dict.update({self.COMPOSITE_LARGE_KEY: composite_img}) + + bobbleheads_large_img = Image.open(bobbleheads_large_file) + bobbleheads_large_img = bobbleheads_large_img.resize(self.BOBBLEHEADS_LARGE_SIZE) + img_dict.update({self.BOBBLEHEADS_LARGE_KEY: bobbleheads_large_img}) + + bobbleheads_img = Image.open(bobbleheads_large_file) + bobbleheads_img = bobbleheads_img.resize(self.BOBBLEHEADS_SIZE) + img_dict.update({self.BOBBLEHEADS_KEY: bobbleheads_img}) + + halfbody_large_large_img = Image.open(halfbody_large_large_file) + halfbody_large_large_img = halfbody_large_large_img.resize(self.HALFBODY_LARGE_LARGE_SIZE) + img_dict.update({self.HALFBODY_LARGE_LARGE_KEY: halfbody_large_large_img}) + + halfbody_large_img = Image.open(halfbody_large_large_file) + halfbody_large_img = halfbody_large_img.resize(self.HALFBODY_LARGE_SIZE) + img_dict.update({self.HALFBODY_LARGE_KEY: halfbody_large_img}) + + halfbody_small_large_img = Image.open(halfbody_large_large_file) + halfbody_small_large_img = halfbody_small_large_img.resize(self.HALFBODY_SMALL_LARGE_SIZE) + img_dict.update({self.HALFBODY_SMALL_LARGE_KEY: halfbody_small_large_img}) + + halfbody_small_img = Image.open(halfbody_large_large_file) + halfbody_small_img = halfbody_small_img.resize(self.HALFBODY_SMALL_SIZE) + img_dict.update({self.HALFBODY_SMALL_KEY: halfbody_small_img}) + + mini_large_img = Image.open(mini_large_file) + mini_large_img = mini_large_img.resize(self.MINI_LARGE_SIZE) + img_dict.update({self.MINI_LARGE_KEY: mini_large_img}) + + mini_img = Image.open(mini_large_file) + mini_img = mini_img.resize(self.MINI_SIZE) + img_dict.update({self.MINI_KEY: mini_img}) + + unitcard_large_img = Image.open(unitcard_large_file) + unitcard_large_img = unitcard_large_img.resize(self.UNITCARD_LARGE_SIZE) + img_dict.update({self.UNITCARD_LARGE_KEY: unitcard_large_img}) + + unitcard_img = Image.open(unitcard_large_file) + unitcard_img = unitcard_img.resize(self.UNITCARD_SIZE) + img_dict.update({self.UNITCARD_KEY: unitcard_img}) + + return img_dict + + + def create_image_dict_convert_mode(self): + pass -# Image Constants -TRANSPARENT_BACKGROUND = "transparent" -CENTER = "center" -PNG = "PNG" - -# Image sizes -BOBBLEHEADS_LARGE_SIZE = 134, 220 -BOBBLEHEADS_SIZE = 84, 138 -HALFBODY_LARGE_LARGE_SIZE = 499, 400 -HALFBODY_LARGE_SIZE = 312, 250 -HALFBODY_SMALL_LARGE_SIZE = 176, 134 -HALFBODY_SMALL_SIZE = 110, 84 -MINI_LARGE_SIZE = 48, 48 -MINI_SIZE = 30, 30 -UNITCARD_LARGE_SIZE = 131, 435 -UNITCARD_SIZE = 82, 272 - -# Subdirectory names -COMPOSITES_DIR = "composites" -STILLS_DIR = "stills" -BOBBLEHEADS_DIR = "bobbleheads" -HALFBODY_LARGE_DIR = "halfbody_large" -HALFBODY_SMALL_DIR = "halfbody_small" -MINI_DIR = "mini" -UNITCARDS_DIR = "unitcards" -LARGE_PANEL_DIR = "large_panel" -SMALL_PANEL_DIR = "small_panel" -FACES_DIR = "faces" -ANGRY_DIR = "angry" -HAPPY_DIR = "happy" -NORMAL_DIR = "normal" -LARGE_DIR = "large" - -# Image references for the dictionary -COMPOSITE_LARGE_KEY = "composite_large_key" -BOBBLEHEADS_LARGE_KEY = "bobbleheads_large_key" -BOBBLEHEADS_KEY = "bobbleheads_key" -HALFBODY_LARGE_LARGE_KEY = "halfbody_large_large_key" -HALFBODY_LARGE_KEY = "halfbody_large_key" -HALFBODY_SMALL_LARGE_KEY = "halfbody_small_large_key" -HALFBODY_SMALL_KEY = "halfbody_small_key" -MINI_LARGE_KEY = "mini_large_key" -MINI_KEY = "mini_key" -UNITCARD_LARGE_KEY = "unitcard_large_key" -UNITCARD_KEY = "unitcard_key" - -# Sub directory dictionary -SUBDIR_DICTS = [{'dir': BOBBLEHEADS_DIR, 'img_key': BOBBLEHEADS_KEY, 'img_large_key': BOBBLEHEADS_LARGE_KEY}, - {'dir': HALFBODY_LARGE_DIR, 'img_key': HALFBODY_LARGE_KEY, 'img_large_key': HALFBODY_LARGE_LARGE_KEY}, - {'dir': HALFBODY_SMALL_DIR, 'img_key': HALFBODY_SMALL_KEY, 'img_large_key': HALFBODY_SMALL_LARGE_KEY}, - {'dir': MINI_DIR, 'img_key': MINI_LARGE_KEY, 'img_large_key': MINI_LARGE_KEY}, - {'dir': UNITCARDS_DIR, 'img_key': UNITCARD_KEY, 'img_large_key': UNITCARD_LARGE_KEY}] - -# PNG Chuck Stuff -TEXT_CHUNK_FLAG = b'tEXt' -DEFAULT_X = '-25' -DEFAULT_Y = '-75' -DEFAULT_PIVOT_X = '0.5000' -DEFAULT_PIVOT_Y = '0.5000' + + def convert(self): + pass + def build_five_image_folder(self, source_dir, target_dir, character_dir, element, gender, is_generic): + if is_generic: + self.build_generic_five_image_folder(source_dir, target_dir, character_dir, element, gender) + else: + self.build_unique_five_image_folder(source_dir, target_dir, character_dir, element, gender) + + + def build_generic_five_image_folder(self, source_dir, target_dir, character_dir, element, gender): + composite_img = "face.png" + composite_img_path = Path(source_dir).joinpath(self.COMPOSITES_DIR).joinpath(self.FACES_DIR).joinpath(character_dir).joinpath(self.LARGE_PANEL_DIR).joinpath(self.ANGRY_DIR).joinpath(composite_img) + bobbleheads_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.BOBBLEHEADS_DIR).joinpath(self.FACES_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + halfbody_large_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.HALFBODY_LARGE_DIR).joinpath(self.FACES_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + mini_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.MINI_DIR).joinpath(self.FACES_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + unitcards_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.UNITCARDS_DIR).joinpath(self.FACES_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + + composite_img = Image.open(composite_img_path) + bobbleheads_img = Image.open(bobbleheads_large_img_path) + halfbody_img = Image.open(halfbody_large_large_img_path) + mini_img = Image.open(mini_large_img_path) + unitcards_img = Image.open(unitcards_large_img_path) + + composite = "head.png" + bobbleheads_large = "bobbleheads_large.png" + halfbody_large_large = "halfbody_large_large.png" + mini_large = "mini_large.png" + unitcard_large = "unitcard_large.png" + + composite_img.save(Path(target_dir).joinpath(composite), self.PNG) + bobbleheads_img.save(Path(target_dir).joinpath(bobbleheads_large), self.PNG) + halfbody_img.save(Path(target_dir).joinpath(halfbody_large_large), self.PNG) + mini_img.save(Path(target_dir).joinpath(mini_large), self.PNG) + unitcards_img.save(Path(target_dir).joinpath(unitcard_large), self.PNG) + + + def build_unique_five_image_folder(self, source_dir, target_dir, character_dir, element, gender): + composite_img = "head.png" + composite_img_path = Path(source_dir).joinpath(self.COMPOSITES_DIR).joinpath(self.LARGE_PANEL_DIR).joinpath(self.ANGRY_DIR).joinpath(composite_img) + bobbleheads_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.BOBBLEHEADS_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + halfbody_large_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.HALFBODY_LARGE_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + mini_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.MINI_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + unitcards_large_img_path = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(self.UNITCARDS_DIR).joinpath(self.LARGE_DIR).joinpath(character_dir + ".png") + + composite_img = Image.open(composite_img_path) + bobbleheads_img = Image.open(bobbleheads_large_img_path) + halfbody_img = Image.open(halfbody_large_large_img_path) + mini_img = Image.open(mini_large_img_path) + unitcards_img = Image.open(unitcards_large_img_path) + + composite = "head.png" + bobbleheads_large = "bobbleheads_large.png" + halfbody_large_large = "halfbody_large_large.png" + mini_large = "mini_large.png" + unitcard_large = "unitcard_large.png" + + composite_img.save(Path(target_dir).joinpath(composite), self.PNG) + bobbleheads_img.save(Path(target_dir).joinpath(bobbleheads_large), self.PNG) + halfbody_img.save(Path(target_dir).joinpath(halfbody_large_large), self.PNG) + mini_img.save(Path(target_dir).joinpath(mini_large), self.PNG) + unitcards_img.save(Path(target_dir).joinpath(unitcard_large), self.PNG) + + + def build_target_folder_structure(self, source_dir, target_dir, character_dir, element, gender, is_generic): + image_dict = self.create_image_dict(source_dir) + + if is_generic: + self.build_generic_target_folder(source_dir, target_dir, character_dir, image_dict, element, gender) + else: + self.build_unique_target_folder(source_dir, target_dir, character_dir, image_dict) + + + def build_generic_target_folder(self, source_dir, target_dir, character_dir, image_dict, element, gender): + composite_img = "face.png" + composite_faces_dir = Path(target_dir).joinpath(self.COMPOSITES_DIR).joinpath(self.FACES_DIR).joinpath(character_dir) + + composite_large_panel_dir = composite_faces_dir.joinpath(self.LARGE_PANEL_DIR) + composite_large_panel_dir.joinpath(self.ANGRY_DIR).mkdir(parents=True, exist_ok=True) + composite_large_panel_dir.joinpath(self.HAPPY_DIR).mkdir(parents=True, exist_ok=True) + composite_large_panel_dir.joinpath(self.NORMAL_DIR).mkdir(parents=True, exist_ok=True) + + composite_small_panel_dir = composite_faces_dir.joinpath(self.SMALL_PANEL_DIR) + composite_small_panel_dir.joinpath(self.ANGRY_DIR).mkdir(parents=True, exist_ok=True) + composite_small_panel_dir.joinpath(self.HAPPY_DIR).mkdir(parents=True, exist_ok=True) + composite_small_panel_dir.joinpath(self.NORMAL_DIR).mkdir(parents=True, exist_ok=True) + + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img)) + + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img)) + + # TODO: redo composites to take from source values + angry_comment = '[type:angry;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + happy_comment = '[type:happy;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + normal_comment = '[type:norm;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img), angry_comment) + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img), happy_comment) + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img), normal_comment) + + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img), angry_comment) + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img), happy_comment) + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img), normal_comment) + + for subdir_dict in self.SUBDIR_DICTS: + subdir = subdir_dict.get('dir') + img_key = subdir_dict.get('img_key') + img_large_key = subdir_dict.get('img_large_key') + + still_dir = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(subdir) + still_large_dir = still_dir.joinpath(self.LARGE_DIR) + still_face_dir = still_dir.joinpath(self.FACES_DIR) + still_face_large_dir = still_face_dir.joinpath(self.LARGE_DIR) + + still_large_dir.mkdir(parents=True, exist_ok=True) + still_face_large_dir.mkdir(parents=True, exist_ok=True) + + image_dict.get(img_large_key).save(still_face_large_dir.joinpath(character_dir + ".png")) + image_dict.get(img_key).save(still_face_dir.joinpath(character_dir + ".png")) + + # Populate blank ancillaries + ancillary_images = self.get_ancillary_images_list(element, gender) + for ancillary_image in ancillary_images: + blank_png = Image.new('RGBA', (1, 1), (255, 0, 0, 0)) + blank_png.save(still_dir.joinpath(ancillary_image), self.PNG) + blank_png.save(still_large_dir.joinpath(ancillary_image), self.PNG) + + + def build_unique_target_folder(self, source_dir, target_dir, character_dir, image_dict): + composite_dir = Path(target_dir).joinpath(self.COMPOSITES_DIR) + + composite_large_panel_dir = composite_dir.joinpath(self.LARGE_PANEL_DIR) + composite_large_panel_dir.joinpath(self.ANGRY_DIR).mkdir(parents=True, exist_ok=True) + composite_large_panel_dir.joinpath(self.HAPPY_DIR).mkdir(parents=True, exist_ok=True) + composite_large_panel_dir.joinpath(self.NORMAL_DIR).mkdir(parents=True, exist_ok=True) + + composite_small_panel_dir = composite_dir.joinpath(self.SMALL_PANEL_DIR) + composite_small_panel_dir.joinpath(self.ANGRY_DIR).mkdir(parents=True, exist_ok=True) + composite_small_panel_dir.joinpath(self.HAPPY_DIR).mkdir(parents=True, exist_ok=True) + composite_small_panel_dir.joinpath(self.NORMAL_DIR).mkdir(parents=True, exist_ok=True) + + # Check to see if a composites.yaml file exists, if it does load it, if not, preform default behavior + # Load composites.yaml and build composites based on it + composites_config_path = Path(source_dir).joinpath(self.COMPOSITES_CONFIG_FILE) + using_composites_config = False + + if composites_config_path.exists(): + composites_config_data = self.read_composites_config(composites_config_path) + if composites_config_data.get(self.ENABLED): + using_composites_config = True + + if using_composites_config: + composite_character_data = composites_config_data.get(self.ARTS).get(character_dir) + for file_data in composite_character_data: + file = file_data.get(self.FILE) + type = file_data.get(self.TYPE) + if type == self.TYPE_BLANK: + blank_img = Image.new(self.RGBA, self.BLANK_SIZE, (255, 0, 0, 0)) + for location in file_data.get(self.LOCATIONS): + Path(target_dir).joinpath(location.get(self.PATH)).mkdir(parents=True, exist_ok=True) + location_path = Path(target_dir).joinpath(location.get(self.PATH)).joinpath(file) + blank_img.save(location_path, self.PNG) + elif type == self.TYPE_REPLACE: + source_img = Image.open(Path(source_dir).joinpath(file_data.get(self.SOURCE))) + for location in file_data.get(self.LOCATIONS): + Path(target_dir).joinpath(location.get(self.PATH)).mkdir(parents=True, exist_ok=True) + location_path = Path(target_dir).joinpath(location.get(self.PATH)).joinpath(file) + source_img.save(location_path, self.PNG) + img_comment = "[type:{};x:{};y:{};z-order:{};pivot_x:{};pivot_y:{};]".format(location.get(self.TYPE), location.get(self.X_POS), location.get(self.Y_POS), location.get(self.Z_ORDER), location.get(self.X_PIVOT), location.get(self.Y_PIVOT)) + self.insert_text_chunk_to_png(location_path, img_comment) + pass + else: + raise Exception("{} is not a valid type for composite config file data.".format(type)) + else: + composite_img = "head.png" + + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img)) + + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img)) + image_dict.get(self.COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img)) + + # TODO: redo composites to take from source values + angry_comment = '[type:angry;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + happy_comment = '[type:happy;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + normal_comment = '[type:norm;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' + + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img), angry_comment) + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img), happy_comment) + self.insert_text_chunk_to_png(composite_large_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img), normal_comment) + + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.ANGRY_DIR).joinpath(composite_img), angry_comment) + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.HAPPY_DIR).joinpath(composite_img), happy_comment) + self.insert_text_chunk_to_png(composite_small_panel_dir.joinpath(self.NORMAL_DIR).joinpath(composite_img), normal_comment) + + for subdir_dict in self.SUBDIR_DICTS: + subdir = subdir_dict.get('dir') + img_key = subdir_dict.get('img_key') + img_large_key = subdir_dict.get('img_large_key') + + still_dir = Path(target_dir).joinpath(self.STILLS_DIR).joinpath(subdir) + still_large_dir = still_dir.joinpath(self.LARGE_DIR) + + still_large_dir.mkdir(parents=True, exist_ok=True) + + image_dict.get(img_large_key).save(still_dir.joinpath(character_dir + ".png")) + image_dict.get(img_key).save(still_large_dir.joinpath(character_dir + ".png")) + + + def get_ancillary_images_list(self, element, gender): + if gender != "male" and gender != "female": + raise Exception('{} is not a valid gender'.format(gender)) + + if element == 'earth': + ancillary_images = ["3k_main_ancillary_armour_light_armour_earth_metal_and_water_common" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_exceptional_earth_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_unique_earth_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_exceptional_earth_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_unique_earth_" + gender + ".png", + "ep_ancillary_armour_light_leather_partial_exceptional_earth_" + gender + ".png", + "ep_ancillary_armour_light_leather_partial_unique_earth_" + gender + ".png", + "ep_ancillary_armour_medium_leather_exceptional_earth_" + gender + ".png", + "ep_ancillary_armour_medium_leather_unique_earth_" + gender + ".png" + ] + elif element == 'fire': + ancillary_images = ["3k_main_ancillary_armour_heavy_iron_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_exceptional_fire_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_unique_fire_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_exceptional_fire_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_unique_fire_" + gender + ".png", + "ep_ancillary_armour_heavy_iron_exceptional_fire_" + gender + ".png", + "ep_ancillary_armour_heavy_iron_unique_fire_" + gender + ".png", + "ep_ancillary_armour_medium_iron_partial_exceptional_fire_" + gender + ".png", + "ep_ancillary_armour_medium_iron_partial_unique_fire_" + gender + ".png" + ] + elif element == 'metal': + ancillary_images = ["3k_main_ancillary_armour_light_leather_partial_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_exceptional_metal_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_light_leather_partial_unique_metal_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_exceptional_metal_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_leather_unique_metal_" + gender + ".png", + "ep_ancillary_armour_light_leather_partial_exceptional_metal_" + gender + ".png", + "ep_ancillary_armour_light_leather_partial_unique_metal_" + gender + ".png", + "ep_ancillary_armour_medium_leather_exceptional_metal_" + gender + ".png", + "ep_ancillary_armour_medium_leather_unique_metal_" + gender + ".png" + ] + elif element == 'water': + ancillary_images = ["3k_main_ancillary_armour_light_tunic_common_water_" + gender + ".png", + "3k_main_ancillary_armour_light_tunic_exceptional_water_" + gender + ".png", + "3k_main_ancillary_armour_light_tunic_refined_water_" + gender + ".png", + "3k_main_ancillary_armour_light_tunic_unique_water_" + gender + ".png", + "ep_ancillary_armour_light_tunic_exceptional_water_" + gender + ".png", + "ep_ancillary_armour_light_tunic_unique_water_" + gender + ".png" + ] + elif element == 'wood': + ancillary_images = ["3k_main_ancillary_armour_heavy_iron_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_exceptional_wood_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_heavy_iron_unique_wood_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_common_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_exceptional_wood_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_refined_shared_" + gender + ".png", + "3k_main_ancillary_armour_medium_iron_partial_unique_wood_" + gender + ".png", + "ep_ancillary_armour_heavy_iron_exceptional_wood_" + gender + ".png", + "ep_ancillary_armour_heavy_iron_unique_wood_" + gender + ".png", + "ep_ancillary_armour_medium_iron_partial_exceptional_wood_" + gender + ".png", + "ep_ancillary_armour_medium_iron_partial_unique_wood_" + gender + ".png" + ] + elif element == "healer": + ancillary_images = ["3k_ytr_ancillary_armour_healer_yellow_turban_common.png", + "3k_ytr_ancillary_armour_healer_yellow_turban_exceptional.png", + "3k_ytr_ancillary_armour_healer_yellow_turban_refined.png", + "3k_ytr_ancillary_armour_healer_yellow_turban_unique.png" + ] + elif element == "scholar": + ancillary_images = ["3k_ytr_ancillary_armour_scholar_medium_yellow_turban_common.png", + "3k_ytr_ancillary_armour_scholar_medium_yellow_turban_exceptional.png", + "3k_ytr_ancillary_armour_scholar_medium_yellow_turban_refined.png", + "3k_ytr_ancillary_armour_scholar_medium_yellow_turban_unique.png" + ] + elif element == "veteran": + ancillary_images = ["3k_ytr_ancillary_armour_veteran_medium_yellow_turban_common.png", + "3k_ytr_ancillary_armour_veteran_medium_yellow_turban_exceptional.png", + "3k_ytr_ancillary_armour_veteran_medium_yellow_turban_refined.png", + "3k_ytr_ancillary_armour_veteran_medium_yellow_turban_unique.png" + ] + else: + raise Exception('{} is not a valid element'.format(element)) + return ancillary_images + + + def generate_chunk_tuple(self, type_flag, content): + return tuple([type_flag, content]) + + + def generate_text_chunk_tuple(self, str_info): + type_flag = self.TEXT_CHUNK_FLAG + comment_ba = bytearray(bytes("Comment", "utf-8")) + comment_ba.extend(b'\x00') + comment_ba.extend(bytes(str_info, "utf-8")) + + return tuple([type_flag, bytes(comment_ba)]) + + + def insert_text_chunk(self, target, text, index=1): + if index < 0: + raise Exception('The index value {} less than 0!'.format(index)) + + reader = png.Reader(filename=str(target)) + chunks = reader.chunks() + chunk_list = list(chunks) + + # add non comment chunks to new list, basically removes all existing comments + new_chunk_list = [] + for chunk in chunk_list: + if b'tEXt' not in chunk[0]: + new_chunk_list.append(chunk) + + # add the new comment with postions + chunk_item = self.generate_text_chunk_tuple(text) + new_chunk_list.insert(index, chunk_item) + + with open(str(target), 'wb') as dst_file: + png.write_chunks(dst_file, new_chunk_list) + + + def insert_text_chunk_to_png(self, src, message): + # src = r'E:\temp\png\register_05.png' + self.insert_text_chunk(src, message) + + + def read_composites_config(self, composites_config_path): + with open(composites_config_path, 'r') as composites_config_file: + composites_config_data = yaml.safe_load(composites_config_file) + + return composites_config_data + def main(): source_dir = args.source_dir target_dir = args.target_dir @@ -80,299 +527,15 @@ def main(): character_element = args.character_element character_gender = args.character_gender is_generic = args.is_generic - build_target_folder_structure(source_dir, target_dir, character_folder, character_element, character_gender, is_generic) - pass - - -# Takes a folder with base 5 large version of the required images and builds a image dictionary from them -def create_image_dict(source_dir): - img_dict = {} - - composite = "head.png" - bobbleheads_large = "bobbleheads_large.png" - halfbody_large_large = "halfbody_large_large.png" - mini_large = "mini_large.png" - unitcard_large = "unitcard_large.png" - - composite_file = Path(source_dir).joinpath(composite) - bobbleheads_large_file = Path(source_dir).joinpath(bobbleheads_large) - halfbody_large_large_file = Path(source_dir).joinpath(halfbody_large_large) - mini_large_file = Path(source_dir).joinpath(mini_large) - unitcard_large_file = Path(source_dir).joinpath(unitcard_large) - - # create full set from starting 5 images - composite_img = Image.open(composite_file) - img_dict.update({COMPOSITE_LARGE_KEY: composite_img}) - - bobbleheads_large_img = Image.open(bobbleheads_large_file) - bobbleheads_large_img = bobbleheads_large_img.resize(BOBBLEHEADS_LARGE_SIZE) - img_dict.update({BOBBLEHEADS_LARGE_KEY: bobbleheads_large_img}) - - bobbleheads_img = Image.open(bobbleheads_large_file) - bobbleheads_img = bobbleheads_img.resize(BOBBLEHEADS_SIZE) - img_dict.update({BOBBLEHEADS_KEY: bobbleheads_img}) - - halfbody_large_large_img = Image.open(halfbody_large_large_file) - halfbody_large_large_img = halfbody_large_large_img.resize(HALFBODY_LARGE_LARGE_SIZE) - img_dict.update({HALFBODY_LARGE_LARGE_KEY: halfbody_large_large_img}) - - halfbody_large_img = Image.open(halfbody_large_large_file) - halfbody_large_img = halfbody_large_img.resize(HALFBODY_LARGE_SIZE) - img_dict.update({HALFBODY_LARGE_KEY: halfbody_large_img}) - - halfbody_small_large_img = Image.open(halfbody_large_large_file) - halfbody_small_large_img = halfbody_small_large_img.resize(HALFBODY_SMALL_LARGE_SIZE) - img_dict.update({HALFBODY_SMALL_LARGE_KEY: halfbody_small_large_img}) - - halfbody_small_img = Image.open(halfbody_large_large_file) - halfbody_small_img = halfbody_small_img.resize(HALFBODY_SMALL_SIZE) - img_dict.update({HALFBODY_SMALL_KEY: halfbody_small_img}) - - mini_large_img = Image.open(mini_large_file) - mini_large_img = mini_large_img.resize(MINI_LARGE_SIZE) - img_dict.update({MINI_LARGE_KEY: mini_large_img}) - - mini_img = Image.open(mini_large_file) - mini_img = mini_img.resize(MINI_SIZE) - img_dict.update({MINI_KEY: mini_img}) - - unitcard_large_img = Image.open(unitcard_large_file) - unitcard_large_img = unitcard_large_img.resize(UNITCARD_LARGE_SIZE) - img_dict.update({UNITCARD_LARGE_KEY: unitcard_large_img}) - - unitcard_img = Image.open(unitcard_large_file) - unitcard_img = unitcard_img.resize(UNITCARD_SIZE) - img_dict.update({UNITCARD_KEY: unitcard_img}) - - return img_dict - - -def create_image_dict_convert_mode(): - pass - - -def convert(): - pass - - -def build_target_folder_structure(source_dir, target_dir, character_dir, element, gender, is_generic): - image_dict = create_image_dict(source_dir) - - if is_generic: - build_generic_target_folder(target_dir, character_dir, image_dict, element, gender) - else: - build_unique_target_folder(target_dir, character_dir, image_dict) - - -def build_generic_target_folder(target_dir, character_dir, image_dict, element, gender): - composite_img = "face.png" - composite_faces_dir = Path(target_dir).joinpath(COMPOSITES_DIR).joinpath(FACES_DIR).joinpath(character_dir) + is_invert = args.is_invert - composite_large_panel_dir = composite_faces_dir.joinpath(LARGE_PANEL_DIR) - composite_large_panel_dir.joinpath(ANGRY_DIR).mkdir(parents=True, exist_ok=True) - composite_large_panel_dir.joinpath(HAPPY_DIR).mkdir(parents=True, exist_ok=True) - composite_large_panel_dir.joinpath(NORMAL_DIR).mkdir(parents=True, exist_ok=True) + art_tool = ArtTool() - composite_small_panel_dir = composite_faces_dir.joinpath(SMALL_PANEL_DIR) - composite_small_panel_dir.joinpath(ANGRY_DIR).mkdir(parents=True, exist_ok=True) - composite_small_panel_dir.joinpath(HAPPY_DIR).mkdir(parents=True, exist_ok=True) - composite_small_panel_dir.joinpath(NORMAL_DIR).mkdir(parents=True, exist_ok=True) - - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img)) - - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img)) - - # TODO: redo composites to take from source values - angry_comment = '[type:angry;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - happy_comment = '[type:happy;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - normal_comment = '[type:norm;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img), angry_comment) - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img), happy_comment) - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img), normal_comment) - - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img), angry_comment) - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img), happy_comment) - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img), normal_comment) - - for subdir_dict in SUBDIR_DICTS: - subdir = subdir_dict.get('dir') - img_key = subdir_dict.get('img_key') - img_large_key = subdir_dict.get('img_large_key') - - still_dir = Path(target_dir).joinpath(STILLS_DIR).joinpath(subdir) - still_large_dir = still_dir.joinpath(LARGE_DIR) - still_face_dir = still_dir.joinpath(FACES_DIR) - still_face_large_dir = still_face_dir.joinpath(LARGE_DIR) - - still_large_dir.mkdir(parents=True, exist_ok=True) - still_face_large_dir.mkdir(parents=True, exist_ok=True) - - image_dict.get(img_large_key).save(still_face_large_dir.joinpath(character_dir + ".png")) - image_dict.get(img_key).save(still_face_dir.joinpath(character_dir + ".png")) - - # Populate blank ancillaries - ancillary_images = get_ancillary_images_list(element, gender) - for ancillary_image in ancillary_images: - blank_png = Image.new('RGBA', (1, 1), (255, 0, 0, 0)) - blank_png.save(still_dir.joinpath(ancillary_image), PNG) - blank_png.save(still_large_dir.joinpath(ancillary_image), PNG) - - -def build_unique_target_folder(target_dir, character_dir, image_dict): - composite_img = "head.png" - composite_dir = Path(target_dir).joinpath(COMPOSITES_DIR) - - composite_large_panel_dir = composite_dir.joinpath(LARGE_PANEL_DIR) - composite_large_panel_dir.joinpath(ANGRY_DIR).mkdir(parents=True, exist_ok=True) - composite_large_panel_dir.joinpath(HAPPY_DIR).mkdir(parents=True, exist_ok=True) - composite_large_panel_dir.joinpath(NORMAL_DIR).mkdir(parents=True, exist_ok=True) - - composite_small_panel_dir = composite_dir.joinpath(SMALL_PANEL_DIR) - composite_small_panel_dir.joinpath(ANGRY_DIR).mkdir(parents=True, exist_ok=True) - composite_small_panel_dir.joinpath(HAPPY_DIR).mkdir(parents=True, exist_ok=True) - composite_small_panel_dir.joinpath(NORMAL_DIR).mkdir(parents=True, exist_ok=True) - - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_large_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img)) - - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img)) - image_dict.get(COMPOSITE_LARGE_KEY).save(composite_small_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img)) - - # TODO: redo composites to take from source values - angry_comment = '[type:angry;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - happy_comment = '[type:happy;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - normal_comment = '[type:norm;x:-25;y:-75;z-order:0;pivot_x:0.5000;pivot_y:0.5000;]' - - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img), angry_comment) - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img), happy_comment) - insert_text_chunk_to_png(composite_large_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img), normal_comment) - - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(ANGRY_DIR).joinpath(composite_img), angry_comment) - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(HAPPY_DIR).joinpath(composite_img), happy_comment) - insert_text_chunk_to_png(composite_small_panel_dir.joinpath(NORMAL_DIR).joinpath(composite_img), normal_comment) - - for subdir_dict in SUBDIR_DICTS: - subdir = subdir_dict.get('dir') - img_key = subdir_dict.get('img_key') - img_large_key = subdir_dict.get('img_large_key') - - still_dir = Path(target_dir).joinpath(STILLS_DIR).joinpath(subdir) - still_large_dir = still_dir.joinpath(LARGE_DIR) - - still_large_dir.mkdir(parents=True, exist_ok=True) - - image_dict.get(img_large_key).save(still_dir.joinpath(character_dir + ".png")) - image_dict.get(img_key).save(still_large_dir.joinpath(character_dir + ".png")) - - -def get_ancillary_images_list(element, gender): - if gender != "male" and gender != "female": - raise Exception('{} is not a valid gender'.format(gender)) - - if element == 'earth': - ancillary_images = ["3k_main_ancillary_armour_light_armour_earth_metal_and_water_common" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_exceptional_earth_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_unique_earth_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_exceptional_earth_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_unique_earth_" + gender + ".png" - ] - elif element == 'fire': - ancillary_images = ["3k_main_ancillary_armour_heavy_iron_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_exceptional_fire_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_unique_fire_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_exceptional_fire_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_unique_fire_" + gender + ".png" - ] - elif element == 'metal': - ancillary_images = ["3k_main_ancillary_armour_light_leather_partial_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_exceptional_metal_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_light_leather_partial_unique_metal_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_exceptional_metal_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_leather_unique_metal_" + gender + ".png" - ] - elif element == 'water': - ancillary_images = ["3k_main_ancillary_armour_light_tunic_common_water_" + gender + ".png", - "3k_main_ancillary_armour_light_tunic_exceptional_water_" + gender + ".png", - "3k_main_ancillary_armour_light_tunic_refined_water_" + gender + ".png", - "3k_main_ancillary_armour_light_tunic_unique_water_" + gender + ".png" - ] - elif element == 'wood': - ancillary_images = ["3k_main_ancillary_armour_heavy_iron_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_exceptional_wood_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_heavy_iron_unique_wood_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_common_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_exceptional_wood_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_refined_shared_" + gender + ".png", - "3k_main_ancillary_armour_medium_iron_partial_unique_wood_" + gender + ".png" - ] - elif element == "healer": - pass - elif element == "veteran": - pass - elif element == "colonel": - pass + if is_invert: + art_tool.build_five_image_folder(source_dir, target_dir, character_folder, character_element, character_gender, is_generic) else: - raise Exception('{} is not a valid element'.format(element)) - return ancillary_images - - -def generate_chunk_tuple(type_flag, content): - return tuple([type_flag, content]) - - -def generate_text_chunk_tuple(str_info): - type_flag = TEXT_CHUNK_FLAG - comment_ba = bytearray(bytes("Comment", "utf-8")) - comment_ba.extend(b'\x00') - comment_ba.extend(bytes(str_info, "utf-8")) - - return tuple([type_flag, bytes(comment_ba)]) - - -def insert_text_chunk(target, text, index=1): - if index < 0: - raise Exception('The index value {} less than 0!'.format(index)) - - reader = png.Reader(filename=str(target)) - chunks = reader.chunks() - chunk_list = list(chunks) - - # add non comment chunks to new list, basically removes all existing comments - new_chunk_list = [] - for chunk in chunk_list: - if b'tEXt' not in chunk[0]: - new_chunk_list.append(chunk) - - # add the new comment with postions - chunk_item = generate_text_chunk_tuple(text) - new_chunk_list.insert(index, chunk_item) - - with open(str(target), 'wb') as dst_file: - png.write_chunks(dst_file, new_chunk_list) - - -def insert_text_chunk_to_png(src, message): - # src = r'E:\temp\png\register_05.png' - insert_text_chunk(src, message) - + art_tool.build_target_folder_structure(source_dir, target_dir, character_folder, character_element, character_gender, is_generic) + pass if __name__ == '__main__': parser = argparse.ArgumentParser(description='Processes or converts image files around to create character folders') @@ -384,6 +547,7 @@ def insert_text_chunk_to_png(src, message): parser.add_argument("--composite_x", required=False, help="x offset of the composite image", type=str) parser.add_argument("--composite_y", required=False, help="y offset of the composite image", type=str) parser.add_argument("--is_generic", help="this is a generic character", action='store_true') + parser.add_argument("--is_invert", help="switches to dumping a character folder into the 5 image folder", action='store_true') parser.add_argument("--is_convert", help="switches to convert mode", action='store_true') parser.add_argument("--is_vanilla_unique", help="enable debug logging", action='store_true') parser.add_argument("--verbose", help="enable debug logging", action='store_true')