249 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
#!/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') |