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

249 lines
9.2 KiB
Python
Raw 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/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'
tlight_name = 'tlight'
tshadow_name = 'tshadow'
group_name = 'group_'
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 = []
titem_out_path = os.path.join(levels_output_dir, 'titem')
if not os.path.exists(titem_out_path):
os.mkdir(titem_out_path)
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 layer.is_group() and group_name in layer.name:
for child_layer in layer:
piece_data = {}
lt_x, lt_y = child_layer.offset
c_w, c_h = child_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}_{child_layer.name}'
img_cur_layer = child_layer.composite()
img_cur_layer.save(f"{levels_output_dir}/{psd_name}_{child_layer.name}.png")
piece_list.append(piece_data)
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__":
# pass
# PSD测试方法
# parse_psd(sys.argv[1], sys.argv[2], [])
# print(os.getcwd())
# print(os.path.curdir)
# psd_path = "./CheckPsd/main_30point_ws20250422_1.psd"
psd_dir = "./CheckPsd"
psd_files = {}
for filename in os.listdir(psd_dir):
filepath = os.path.join(psd_dir, filename)
if os.path.isfile(filepath) and filename.lower().endswith('.psd'):
file_name = filename.replace('.psd', '')
psd_files[file_name] = filepath
print(psd_files)
for k,v in psd_files.items():
run(v,f'./{k}',f'./{k}/thu')