386 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
| #!/usr/bin/python
 | ||
| #encoding:utf-8
 | ||
| import os, sys
 | ||
| 
 | ||
| curr = os.path.dirname(sys.argv[0])
 | ||
| if curr != "":
 | ||
|     os.system("cd " + curr)
 | ||
| 
 | ||
| from psd_tools import PSDImage
 | ||
| from PIL import Image
 | ||
| import hashlib
 | ||
| import utils
 | ||
| import export_outline
 | ||
| import json
 | ||
| 
 | ||
| def parse_psd(path):
 | ||
|     global scale
 | ||
|     global versions
 | ||
| 
 | ||
|     file_name = os.path.split(path)[1]
 | ||
| 
 | ||
|     log = []
 | ||
| 
 | ||
|     log.append("开始检测:{}".format(file_name))
 | ||
| 
 | ||
|     psd = PSDImage.open(path)
 | ||
|     try:
 | ||
|         image = psd.composite()
 | ||
|     except Exception as e:
 | ||
|         log.append("文件无法打开" + repr(e))
 | ||
| 
 | ||
|     has_base = False
 | ||
|     has_finish = False
 | ||
|     has_thumbnail = False
 | ||
|     lines = {}
 | ||
|     patch_stages = {}
 | ||
|     spatch_stages = {}
 | ||
|     bad_stages = {}
 | ||
|     sbad_stages = {}
 | ||
|     auto_stages = {}
 | ||
| 
 | ||
|     patch_names = []
 | ||
|     bad_names = []
 | ||
| 
 | ||
|     spatch_parent_name = []
 | ||
|     sbad_parent_name = []
 | ||
| 
 | ||
|     #patch的末尾数字
 | ||
|     patch_end = []
 | ||
|     spatch_end = []
 | ||
|     bad_end = []
 | ||
|     sbad_end = []
 | ||
|     line_end = []
 | ||
| 
 | ||
|     max_width = 0
 | ||
|     max_height = 0
 | ||
| 
 | ||
|     is_activity_main_psd = path.find("activity/main_psd/") != -1 or path.find("activity\\main_psd\\") != -1
 | ||
|     #活动地图读取整个PSD的宽高
 | ||
|     if is_activity_main_psd:
 | ||
|         max_width = psd.width
 | ||
|         max_height = psd.height
 | ||
|     else:
 | ||
|         #普通资源读取base的宽高
 | ||
|         for item in psd.descendants():
 | ||
|             if not item.is_group():
 | ||
|                 nArr = item.name.split('_')
 | ||
|                 if item.name == "base":
 | ||
|                     max_width = item.width
 | ||
|                     max_height = item.height
 | ||
|                     break
 | ||
| 
 | ||
|     if is_activity_main_psd:
 | ||
|         if max_width < 1024:
 | ||
|             log.append("玩法活动背景过小,宽度不能小于1024")
 | ||
|         if max_height < 2560:
 | ||
|             log.append("玩法活动背景过小,高度不能小于2560")
 | ||
| 
 | ||
|     for item in psd.descendants():
 | ||
|         if not item.is_group():
 | ||
|             nArr = item.name.split('_')
 | ||
| 
 | ||
|             if item.name.strip() != item.name:
 | ||
|                 log.append("命名中存在空格:{}".format(item.name))
 | ||
| 
 | ||
|             if not is_activity_main_psd and nArr[0] == 'base':
 | ||
|                 if has_base:
 | ||
|                     log.append("存在多个base图层")
 | ||
|                 has_base = True
 | ||
|             elif nArr[0] == 'finish':
 | ||
|                 if has_finish:
 | ||
|                     log.append("存在多个finish图层")
 | ||
|                 has_finish = True
 | ||
|             elif nArr[0] == 'line':
 | ||
|                 #以前存在line_1,整图轮廓的情况,这种情况视为无line
 | ||
|                 if len(nArr) > 2:
 | ||
|                     if nArr[1] not in lines:
 | ||
|                         lines[nArr[1]] = []
 | ||
|                     if nArr[2] in lines[nArr[1]]:
 | ||
|                         log.append("存在重复图层:{}".format(item.name))
 | ||
|                     lines[nArr[1]].append(nArr[2])
 | ||
|                 else:
 | ||
|                     pass
 | ||
| 
 | ||
|                 line_end.append(item.name.replace("line", ""))
 | ||
|             elif nArr[0] == 'patch' or nArr[0] == 'patchrp':
 | ||
|                 if nArr[1] not in patch_stages:
 | ||
|                     patch_stages[nArr[1]] = []
 | ||
| 
 | ||
|                 patch_stages[nArr[1]].append(nArr[2])
 | ||
| 
 | ||
|                 if item.name not in patch_names:
 | ||
|                     patch_names.append(item.name)
 | ||
| 
 | ||
|                 patch_end.append(item.name.replace("patch", ""))
 | ||
|             elif nArr[0] == 'spatch':
 | ||
|                 if nArr[1] not in spatch_stages:
 | ||
|                     spatch_stages[nArr[1]] = []
 | ||
| 
 | ||
|                 spatch_stages[nArr[1]].append(nArr[2])
 | ||
| 
 | ||
|                 #检测父节点
 | ||
|                 #通过正则表达式,筛选出#开头与#结尾的字符串
 | ||
|                 parr = item.name.split('#')
 | ||
|                 if len(parr) != 3:
 | ||
|                     log.append("spatch图层命名错误,找不到父节点:{}".format(item.name))
 | ||
|                 else:
 | ||
|                     parent = parr[1]
 | ||
|                     if parent not in spatch_parent_name:
 | ||
|                         spatch_parent_name.append(parent)
 | ||
|                     tarr = parent.split('_')
 | ||
|                     if tarr[0] != "patch":
 | ||
|                         log.append("spatch图层命名错误,父节点不是patch:{}".format(item.name))
 | ||
| 
 | ||
|                 spatch_end.append(item.name.replace("spatch", "").replace(f"_#{parent}#", ""))
 | ||
|             elif nArr[0] == 'bad':
 | ||
|                 if nArr[1] not in bad_stages:
 | ||
|                     bad_stages[nArr[1]] = []
 | ||
| 
 | ||
|                 bad_stages[nArr[1]].append(nArr[2])
 | ||
| 
 | ||
|                 if item.name not in bad_names:
 | ||
|                     bad_names.append(item.name)
 | ||
| 
 | ||
|                 bad_end.append(item.name.replace("bad", ""))
 | ||
|             elif nArr[0] == 'sbad':
 | ||
|                 if nArr[1] not in sbad_stages:
 | ||
|                     sbad_stages[nArr[1]] = []
 | ||
| 
 | ||
|                 sbad_stages[nArr[1]].append(nArr[2])
 | ||
| 
 | ||
|                 #检测父节点
 | ||
|                 #通过正则表达式,筛选出#开头与#结尾的字符串
 | ||
|                 parr = item.name.split('#')
 | ||
|                 if len(parr) != 3:
 | ||
|                     log.append("sbad图层命名错误,找不到父节点:{}".format(item.name))
 | ||
|                 else:
 | ||
|                     parent = parr[1]
 | ||
|                     if parent not in sbad_parent_name:
 | ||
|                         sbad_parent_name.append(parent)
 | ||
|                     tarr = parent.split('_')
 | ||
|                     if tarr[0] != "bad":
 | ||
|                         log.append("sbad图层命名错误,父节点不是bad:{}".format(item.name))
 | ||
| 
 | ||
| 
 | ||
|                 sbad_end.append(item.name.replace("sbad", "").replace(f"_#{parent}#", ""))
 | ||
|             elif nArr[0] == 'auto':
 | ||
|                 if nArr[1] not in auto_stages:
 | ||
|                     auto_stages[nArr[1]] = []
 | ||
| 
 | ||
|                 auto_stages[nArr[1]].append(nArr[2])
 | ||
|             elif nArr[0] == 'thumbnail' or nArr[0] == 'role' or nArr[0] == 'rptmp':
 | ||
|                 if nArr[0] == 'thumbnail':
 | ||
|                     has_thumbnail = True
 | ||
|             elif is_activity_main_psd and nArr[0] == 'entry':
 | ||
|                 if len(nArr) != 3:
 | ||
|                     log.append("活动子点位,命名错误:{}".format(item.name))
 | ||
|             elif is_activity_main_psd and nArr[0] == 'base':
 | ||
|                 if nArr[1] == '1':
 | ||
|                     has_base = True
 | ||
|             else:
 | ||
|                 log.append("命名错误:{}\n".format(item.name))
 | ||
| 
 | ||
|             #空图层检测
 | ||
|             if item.width <= 0 or item.height <= 0:
 | ||
|                 log.append("存在空图层:{}\n".format(item.name))
 | ||
| 
 | ||
|             #横坐标越界检测
 | ||
|             if item.offset[0] < 0 or (item.offset[0] + item.width) > max_width:
 | ||
|                 log.append("横坐标越界{}\n".format(item.name))
 | ||
| 
 | ||
|             #纵坐标越界检测
 | ||
|             if item.offset[1] < 0 or (item.offset[1] + item.height) > max_height:
 | ||
|                 log.append("纵坐标越界{}\n".format(item.name))
 | ||
| 
 | ||
|     if not has_base:
 | ||
|         log.append("未检测到base图层\n")
 | ||
| 
 | ||
|     if not is_activity_main_psd and not has_finish:
 | ||
|         log.append("未检测到finish图层\n")
 | ||
| 
 | ||
|     if is_activity_main_psd and not has_thumbnail:
 | ||
|         log.append("未检测到 缩略图 图层\n")
 | ||
| 
 | ||
|     for stage in patch_stages: 
 | ||
|         tmp = {}
 | ||
|         for item in patch_stages[stage]:
 | ||
|             if item in tmp:
 | ||
|                 log.append("存在重复图层:patch_{}_{}".format(stage, item))
 | ||
|             else:
 | ||
|                 tmp[item] = 0
 | ||
| 
 | ||
|     for stage in auto_stages: 
 | ||
|         tmp = {}
 | ||
|         for item in auto_stages[stage]:
 | ||
|             if item in tmp:
 | ||
|                 log.append("存在重复图层:auto_{}_{}".format(stage, item))
 | ||
|             else:
 | ||
|                 tmp[item] = 0
 | ||
| 
 | ||
|     if not is_activity_main_psd:
 | ||
|         if len(lines) > 0 and len(patch_stages) != len(lines):
 | ||
|             log.append("阶段与线稿不对应,线稿:{}  关卡:".format(len(lines), len(patch_stages)))
 | ||
| 
 | ||
|         for item in patch_end:
 | ||
|             if item not in line_end:
 | ||
|                 log.append("patch图层找不到描线:patch{}".format(item))
 | ||
| 
 | ||
|         for item in line_end:
 | ||
|             if item not in patch_end:
 | ||
|                 log.append("描线找不到patch图层:line{}".format(item))
 | ||
| 
 | ||
|     if is_activity_main_psd:
 | ||
|         for item in bad_end:
 | ||
|             if item not in patch_end:
 | ||
|                 log.append("bad图层找不到拼图图层:bad{}".format(item))
 | ||
| 
 | ||
|         for item in patch_end:
 | ||
|             if item not in bad_end:
 | ||
|                 log.append("拼图图层找不到bad图层:patch{}".format(item))
 | ||
| 
 | ||
|         for item in sbad_end:
 | ||
|             if item not in spatch_end:
 | ||
|                 log.append("sbad图层找不到拼图图层:sbad{}".format(item))
 | ||
| 
 | ||
|         for item in spatch_end:
 | ||
|             if item not in sbad_end:
 | ||
|                 log.append("拼图图层找不到sbad图层:spatch{}".format(item))
 | ||
| 
 | ||
|         for stage in spatch_stages:
 | ||
|             tmp = {}
 | ||
|             for item in spatch_stages[stage]:
 | ||
|                 if item in tmp:
 | ||
|                     log.append("存在重复图层:spatch_{}_{}".format(stage, item))
 | ||
|                 else:
 | ||
|                     tmp[item] = 0
 | ||
| 
 | ||
|         for stage in sbad_stages:
 | ||
|             tmp = {}
 | ||
|             for item in sbad_stages[stage]:
 | ||
|                 if item in tmp:
 | ||
|                     log.append("存在重复图层:sbad_{}_{}".format(stage, item))
 | ||
|                 else:
 | ||
|                     tmp[item] = 0
 | ||
|         
 | ||
|         #检测sbad的父节点是否存在
 | ||
|         for a_sbad_name in sbad_parent_name:
 | ||
|             if a_sbad_name not in bad_names:
 | ||
|                 log.append(f"sbad中配置的主节点{a_sbad_name} 实际找不到")
 | ||
| 
 | ||
|         #检测spatch的父节点是否存在
 | ||
|         for a_spatch_name in spatch_parent_name:
 | ||
|             if a_spatch_name not in patch_names:
 | ||
|                 log.append(f"spatch中配置的主节点{a_spatch_name} 实际找不到")
 | ||
| 
 | ||
|     log.append("检测结束")
 | ||
| 
 | ||
|     if len(log) == 2:
 | ||
|         return True
 | ||
|     else:
 | ||
|         for a_log in log:
 | ||
|             print(a_log)
 | ||
|         return False
 | ||
| 
 | ||
| def convert_2_zip_file(path, is_activity_psd):
 | ||
|     file_info_arr = os.path.split(path)
 | ||
|     file_path = file_info_arr[0]
 | ||
|     file_name = os.path.split(path)[1]
 | ||
| 
 | ||
|     #检测成功,压缩到zip
 | ||
|     os.chdir(file_path)
 | ||
|     file_name_without_ex = file_name.split(".")[0]
 | ||
|     utils.zip_file("{}.psd".format(file_name_without_ex), "{}.zip".format(file_name_without_ex))
 | ||
|     os.chdir("../")
 | ||
|     if is_activity_psd:
 | ||
|         os.chdir("../")
 | ||
| 
 | ||
|     os.remove(path)
 | ||
| 
 | ||
| ###生成version文件
 | ||
| def make_version_file(remake):
 | ||
|     version_file = 'version.json';
 | ||
|     
 | ||
|     if remake:
 | ||
|         if os.path.exists(version_file):
 | ||
|             os.remove(version_file)
 | ||
|     
 | ||
|     if not os.path.exists(version_file):
 | ||
|         with open(version_file, 'w') as f:
 | ||
|             json.dump({}, f, sort_keys=True, indent=4)
 | ||
| 
 | ||
| ###加载版本文件
 | ||
| def load_version():
 | ||
|     global versions
 | ||
|     make_version_file(False);
 | ||
|     with open('version.json', 'r') as f:
 | ||
|         try:
 | ||
|             versions = json.load(f)
 | ||
|         except:
 | ||
|             #删除版本文件并重新生成
 | ||
|             make_version_file(True);
 | ||
| 
 | ||
| def write_version():
 | ||
|     with open('version.json', 'w') as f:
 | ||
|         json.dump(versions, f, sort_keys=True, indent=4)
 | ||
| 
 | ||
| if __name__ == '__main__':
 | ||
|     load_version()
 | ||
|     deal_psdid = []
 | ||
|     is_force = sys.argv[1] if len(sys.argv) > 1 else False
 | ||
|     for root , dirs, files in os.walk('./'):
 | ||
|         for name in files:
 | ||
|             src_file = os.path.join(root, name)
 | ||
| 
 | ||
|             if name.endswith('.psd') or name.endswith('.zip'):
 | ||
|                 file_info_arr = os.path.split(src_file)
 | ||
|                 file_path = file_info_arr[0]
 | ||
|                 file_name = file_info_arr[1]
 | ||
|                 key = file_name.split("_")[0]
 | ||
|                 try:
 | ||
|                     i_key = int(key)
 | ||
|                 except Exception as e:
 | ||
|                     print("资源命名错误,请查询是否存在特殊字符:{}".format(name))
 | ||
|                     continue
 | ||
| 
 | ||
|                 if key not in deal_psdid:
 | ||
|                     deal_psdid.append(key)
 | ||
|                 else:
 | ||
|                     print("存在重复关卡:{}".format(key))
 | ||
| 
 | ||
|             if name.endswith('.psd') or (name.endswith('.zip') and is_force):
 | ||
|                 file_info_arr = os.path.split(src_file)
 | ||
|                 file_path = file_info_arr[0]
 | ||
|                 file_name = file_info_arr[1]
 | ||
| 
 | ||
|                 key = file_name.split("_")[0]
 | ||
|                 hash_old = ""
 | ||
|                 if key in versions:
 | ||
|                     hash_old = versions[key]
 | ||
| 
 | ||
|                 if os.path.exists(src_file):
 | ||
|                     hash_now = ""
 | ||
|                     if name.endswith('.psd'):
 | ||
|                         hash_now = utils.calc_hash(src_file)
 | ||
| 
 | ||
|                     if hash_now != hash_old or is_force:
 | ||
|                         psd_file = src_file
 | ||
|                         if name.endswith('.zip'):
 | ||
|                             utils.unzip_file(src_file)
 | ||
|                             psd_file = "{}.psd".format(os.path.splitext(psd_file)[0])
 | ||
|                             hash_now = utils.calc_hash(psd_file)
 | ||
| 
 | ||
|                         try:
 | ||
|                             ret = parse_psd(psd_file)
 | ||
|                             is_activity_psd = psd_file.find("activity/main_psd/") != -1 or psd_file.find("activity\\main_psd\\") != -1 or psd_file.find("activity/level_psd/") != -1 or psd_file.find("activity\\level_psd\\") != -1
 | ||
|                             if ret:
 | ||
|                                 #检测成功,压缩到zip
 | ||
|                                 convert_2_zip_file(psd_file, is_activity_psd)
 | ||
|                                 versions[key] = hash_now
 | ||
|                                 write_version()
 | ||
|                         except Exception as e:
 | ||
|                             print(name + " 解析失败:" + repr(e) + ",请检查命名规范,比如auto_1_1=>auto_1 或 patch_1_1=>patch_1")
 | ||
|                     elif hash_now == hash_old:
 | ||
|                         is_activity_psd = src_file.find("activity/main_psd/") != -1 or src_file.find("activity\\main_psd\\") != -1 or src_file.find("activity/level_psd/") != -1 or src_file.find("activity\\level_psd\\") != -1
 | ||
|                         convert_2_zip_file(src_file, is_activity_psd)
 |