find-object-bundle-builder/FindVerticalBundleBuilder/Tools/psd_convert/parse_psd.py

223 lines
8.2 KiB
Python
Raw Normal View History

2025-04-18 07:35:35 +00:00
#!/usr/bin/env python
# coding:utf-8
import os
import sys
curr_dir = os.path.split(os.path.abspath(__file__))[0]
sys.path.append(os.path.join(curr_dir, '../'))
sys.path.append(os.path.join(curr_dir, '../config_convert'))
import utils as utils
import config as config
import json
import re
import numpy as np
from psd_tools import PSDImage
from PIL import Image
from config_convert.game_play_type import MainPlayType
levels_root_path = os.path.join(curr_dir, "../../Assets/AssetRaw/UIRaw/Raw/Level/")
thumbnail_root_path = os.path.join(curr_dir, "../../Assets/AssetRaw/UIRaw/Raw/Thum/")
version_path = os.path.join(curr_dir, "../../../../../unity_ap_bundle_resource/psd_version.json")
# 游戏玩法的设计分辨率
design_width = 1040
design_height = 1280
thumbnail_size = (1500,1000)
crop_rect = (250,0,1250,1000)
crop_size = (1000,1000)
#psd需要用到的一些命名规则
titem_group = 'titem'
nouse_group = 'nouse'
tfull_layer = 'tfull'
base_layer = 'base'
mask_layer = 'tmask'
json_level_id = 'levelId'
json_list = 'JsonPiecesDataList'
json_x_pos = 'XPos'
json_y_pos = 'YPos'
json_name = 'Name'
scale = 0
version = {}
def run(psd_path, levels_output_dir, thumbnail_output_dir):
"""
解析PSD文件
:param path: psd文件路径
:param levels_output_dir: 关卡资源输出文件夹路径,
:param thumbnail_output_dir: 缩略图资源输出文件夹路径
:return:
"""
print(f'开始解析:{psd_path}')
psd_name = os.path.split(psd_path)[1].replace('.psd','')
psd_type = psd_name.split('_')[0]
# export_dir = os.path.join(levels_root_path,psd_type)
if not os.path.exists(levels_output_dir):
os.mkdir(levels_output_dir)
if not os.path.exists(thumbnail_output_dir):
os.mkdir(thumbnail_output_dir)
psd = PSDImage.open(psd_path)
level_info_json_data = {}
level_info_json_data[json_level_id] = psd_name
piece_list = []
2025-04-18 10:26:23 +00:00
titem_out_path = os.path.join(levels_output_dir, 'titem')
if not os.path.exists(titem_out_path):
os.mkdir(titem_out_path)
2025-04-18 07:35:35 +00:00
for layer in psd:
layer.visible = True
if layer.name == nouse_group and layer.is_group():
# layer.visible = False
continue
if layer.name == titem_group and layer.is_group():
for item_layer in layer:
piece_data = {}
item_layer.visible = True
# lt_x, lt_y = layer.offset
# c_w, c_h = layer.size
# c_x, c_y = lt_x + c_w / 2, lt_y + c_h / 2
# piece_data[json_x_pos] = c_x
# piece_data[json_y_pos] = c_y
piece_data[json_name] = f'{psd_name}_{item_layer.name}'
piece_list.append(piece_data)
img_cur_item_layer = item_layer.composite()
img_cur_item_layer.save(f"{titem_out_path}/{psd_name}_{item_layer.name}.png")
if not layer.is_group():
piece_data = {}
lt_x, lt_y = layer.offset
c_w, c_h = layer.size
c_x, c_y = lt_x + c_w / 2, lt_y + c_h / 2
piece_data[json_x_pos] = c_x
piece_data[json_y_pos] = c_y
piece_data[json_name] = f'{psd_name}_{layer.name}'
img_cur_layer = layer.composite()
img_cur_layer.save(f"{levels_output_dir}/{psd_name}_{layer.name}.png")
piece_list.append(piece_data)
level_info_json_data[json_list] = piece_list
json_path = os.path.join(levels_output_dir, f'{psd_name}.json')
with open(json_path, "w") as f:
f.write(json.dumps(level_info_json_data))
# print(level_info_json_data)
thumbnail_path = os.path.join(thumbnail_output_dir, f'{psd_name}_thum.png')
psd_image = psd.composite(layer_filter=lambda
mix_layer : mask_layer in (mix_layer.name) or tfull_layer in (mix_layer.name) or base_layer in (mix_layer.name))
# psd_image = psd.composite()
psd_image.thumbnail(thumbnail_size)
crop_image = psd_image.crop(crop_rect)
crop_image.save(thumbnail_path)
print(f'解析完毕:{psd_path}')
pass
def make_version_file(remake):
"""
生成version文件
:param remake: 重新生成
:return:
"""
version_file = os.path.join(curr_dir, version_path)
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)
version_file = os.path.join(curr_dir, version_path)
with open(version_file, "r") as f:
try:
versions = json.load(f)
except Exception as e:
print(e)
# 删除版本文件并重新生成
make_version_file(True)
def write_version():
version_file = os.path.join(curr_dir, version_path)
with open(version_file, "w") as f:
json.dump(versions, f, sort_keys=True, indent=4)
def parse_psd(path, output_root, specific_files, platform):
"""
解析psd文件
:param path: psd文件路径
:param output_root: 资源输出路径
:param specific_files: 需要解析文件列表 如果为[]则解析所有文件否则只解析列表中的文件
:return: 所有解析psd name
"""
print("解析指定文件", specific_files)
mainPlayType = MainPlayType()
global levels_root_path, thumbnail_root_path, version_path
# 重置保存路径
levels_root_path = os.path.join(output_root, "Raw/Level")
thumbnail_root_path = os.path.join(output_root, "Raw/Thum")
utils.mkdirs(levels_root_path)
utils.mkdirs(thumbnail_root_path)
version_path = os.path.join(output_root, f"../psd_version.json")
load_version()
all_parse_asset_names = []
for root, dirs, files in os.walk(path):
for name in files:
if name.endswith(".zip"):
src_filename = os.path.join(root, name)
file_name = os.path.split(src_filename)[1]
asset_id = file_name.split(".")[0]
if asset_id not in specific_files:
continue
hash_old = ""
if asset_id in versions:
hash_old = versions[asset_id]
hash_now = utils.calc_hash(src_filename)
print("文件:" + src_filename + " => old = " + hash_old + " now = " + hash_now)
if hash_old != hash_now:
print("文件更改:" + src_filename + " => old = " + hash_old + " now = " + hash_now)
levels_output_dir = None
thumbnail_output_dir = None
for gameplay in mainPlayType.all_main_play_type_list:
if gameplay in asset_id:
gameplay_dir = os.path.join(levels_root_path, gameplay)
if not os.path.exists(gameplay_dir):
os.mkdir(gameplay_dir)
levels_output_dir = os.path.join(gameplay_dir, asset_id)
thumbnail_output_dir = os.path.join(thumbnail_root_path, gameplay)
utils.clear_dirs(levels_output_dir)
break
if levels_output_dir is None or thumbnail_output_dir is None:
print(asset_id + "资源命名异常找不到对应玩法gameplay")
continue
psd_zip_filename = os.path.join(root, name)
utils.unzip_file(psd_zip_filename)
psd_filename = "{}.psd".format(os.path.splitext(os.path.join(root, name))[0])
run(psd_filename, levels_output_dir, thumbnail_output_dir)
all_parse_asset_names.append(asset_id)
versions[asset_id] = hash_now
write_version()
os.remove(psd_filename)
return all_parse_asset_names
if __name__ == "__main__":
2025-04-18 10:26:23 +00:00
# pass
2025-04-18 07:35:35 +00:00
# PSD测试方法
# parse_psd(sys.argv[1], sys.argv[2], [])
# print(os.getcwd())
# print(os.path.curdir)
2025-04-18 10:26:23 +00:00
psd_path = "./CheckPsd/tidyup_ws20250418_1.psd"
run(psd_path,'./test','./test/thu')