gitea_ap_art_assets/check_compress_psd.py

386 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/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)