257 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
 | 
						|
import { Vec2, Vec3, Vec4, Color, Size, Rect, Quat, Mat4 } from 'cc';
 | 
						|
 | 
						|
import LogUtils from '@max-studio/core/utils/LogUtils';
 | 
						|
 | 
						|
/**
 | 
						|
 * 配置表解析工具类
 | 
						|
 * 提供通用的数据类型解析函数
 | 
						|
 * 
 | 
						|
 * ⚠️ 此文件由配置表生成器自动生成,请勿手动修改!
 | 
						|
 * 如需修改,请编辑 configs/plugins/ConfigTableGenerator.ts 中的 generateConfigParseUtils 方法
 | 
						|
 */
 | 
						|
export class ConfigParseUtils {
 | 
						|
    /**
 | 
						|
     * 解析Vec2类型
 | 
						|
     */
 | 
						|
    public static parseVec2(value: any): Vec2 {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Vec2(parts[0] || 0, parts[1] || 0);
 | 
						|
        }
 | 
						|
        return new Vec2(0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Vec3类型
 | 
						|
     */
 | 
						|
    public static parseVec3(value: any): Vec3 {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Vec3(parts[0] || 0, parts[1] || 0, parts[2] || 0);
 | 
						|
        }
 | 
						|
        return new Vec3(0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Vec4类型
 | 
						|
     */
 | 
						|
    public static parseVec4(value: any): Vec4 {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Vec4(parts[0] || 0, parts[1] || 0, parts[2] || 0, parts[3] || 0);
 | 
						|
        }
 | 
						|
        return new Vec4(0, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Color类型
 | 
						|
     */
 | 
						|
    public static parseColor(value: any): Color {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            if (value.startsWith('#')) {
 | 
						|
                // 十六进制颜色
 | 
						|
                const hex = value.slice(1);
 | 
						|
                const r = Number.parseInt(hex.substring(0, 2), 16);
 | 
						|
                const g = Number.parseInt(hex.substring(2, 4), 16);
 | 
						|
                const b = Number.parseInt(hex.substring(4, 6), 16);
 | 
						|
                const a = hex.length > 6 ? Number.parseInt(hex.substring(6, 8), 16) : 255;
 | 
						|
                return new Color(r, g, b, a);
 | 
						|
            } else {
 | 
						|
                // 逗号分隔的RGBA值
 | 
						|
                const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
                return new Color(parts[0] || 0, parts[1] || 0, parts[2] || 0, parts[3] !== undefined ? parts[3] : 255);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return new Color(0, 0, 0, 255);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Size类型
 | 
						|
     */
 | 
						|
    public static parseSize(value: any): Size {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Size(parts[0] || 0, parts[1] || 0);
 | 
						|
        }
 | 
						|
        return new Size(0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Rect类型
 | 
						|
     */
 | 
						|
    public static parseRect(value: any): Rect {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Rect(parts[0] || 0, parts[1] || 0, parts[2] || 0, parts[3] || 0);
 | 
						|
        }
 | 
						|
        return new Rect(0, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Quat类型
 | 
						|
     */
 | 
						|
    public static parseQuat(value: any): Quat {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            return new Quat(parts[0] || 0, parts[1] || 0, parts[2] || 0, parts[3] !== undefined ? parts[3] : 1);
 | 
						|
        }
 | 
						|
        return new Quat(0, 0, 0, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析Mat4类型
 | 
						|
     */
 | 
						|
    public static parseMat4(value: any): Mat4 {
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const parts = value.split(',').map(v => Number.parseFloat(v.trim()) || 0);
 | 
						|
            const mat = new Mat4();
 | 
						|
            try {
 | 
						|
                mat.set(
 | 
						|
                    parts[0], parts[1], parts[2], parts[3],
 | 
						|
                    parts[4], parts[5], parts[6], parts[7],
 | 
						|
                    parts[8], parts[9], parts[10], parts[11],
 | 
						|
                    parts[12], parts[13], parts[14], parts[15]
 | 
						|
                );
 | 
						|
            } catch (err) {
 | 
						|
                LogUtils.error('ConfigParseUtils', '解析Mat4失败:', err);
 | 
						|
            }
 | 
						|
            return mat;
 | 
						|
        }
 | 
						|
        return new Mat4();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析布尔值
 | 
						|
     */
 | 
						|
    static parseBoolean(value: any): boolean {
 | 
						|
        if (typeof value === 'boolean') {
 | 
						|
            return value;
 | 
						|
        }
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            const lowerValue = value.toLowerCase();
 | 
						|
            return lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes';
 | 
						|
        }
 | 
						|
        if (typeof value === 'number') {
 | 
						|
            return value !== 0;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析整数
 | 
						|
     */
 | 
						|
    public static parseInt(value: string | number): number {
 | 
						|
        if (typeof value === 'number') return Math.floor(value);
 | 
						|
        if (typeof value === 'string') return Number.parseInt(value.trim()) || 0;
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析浮点数
 | 
						|
     */
 | 
						|
    static parseFloat(value: any): number {
 | 
						|
        return Number.parseFloat(value) || 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析字符串
 | 
						|
     */
 | 
						|
    static parseString(value: any): string {
 | 
						|
        return String(value || '');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析字符串数组
 | 
						|
     */
 | 
						|
    static parseStringArray(value: any): string[] {
 | 
						|
        if (Array.isArray(value)) {
 | 
						|
            return value.map(item => String(item || ''));
 | 
						|
        }
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            return value.split(',').map(item => item.trim()).filter(item => item.length > 0);
 | 
						|
        }
 | 
						|
        return [];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 解析数字数组
 | 
						|
     */
 | 
						|
    static parseNumberArray(value: any): number[] {
 | 
						|
        if (Array.isArray(value)) {
 | 
						|
            return value.map(item => Number.parseFloat(item) || 0);
 | 
						|
        }
 | 
						|
        if (typeof value === 'string') {
 | 
						|
            return value.split(',').map(item => Number.parseFloat(item.trim()) || 0);
 | 
						|
        }
 | 
						|
        return [];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 深度冻结对象,确保所有嵌套属性都不可修改
 | 
						|
     */
 | 
						|
    public static deepFreeze<T>(obj: T): T {
 | 
						|
        if (obj === null || typeof obj !== 'object') {
 | 
						|
            return obj;
 | 
						|
        }
 | 
						|
 | 
						|
        // 检查是否为 ArrayBuffer views 或其他不可冻结的对象
 | 
						|
        if (ArrayBuffer.isView(obj) || obj instanceof ArrayBuffer) {
 | 
						|
            return obj;
 | 
						|
        }
 | 
						|
 | 
						|
        // 检查是否为 Date、RegExp 等内置对象
 | 
						|
        if (obj instanceof Date || obj instanceof RegExp) {
 | 
						|
            return obj;
 | 
						|
        }
 | 
						|
 | 
						|
        try {
 | 
						|
            // 递归冻结所有属性(先冻结子对象)
 | 
						|
            Object.getOwnPropertyNames(obj).forEach(prop => {
 | 
						|
                const value = (obj as any)[prop];
 | 
						|
                if (value !== null && typeof value === 'object') {
 | 
						|
                    this.deepFreeze(value);
 | 
						|
                }
 | 
						|
            });
 | 
						|
            
 | 
						|
            // 最后冻结对象本身
 | 
						|
            Object.freeze(obj);
 | 
						|
            
 | 
						|
            // 对于数组,还需要防止索引赋值
 | 
						|
            if (Array.isArray(obj)) {
 | 
						|
                Object.seal(obj);
 | 
						|
            }
 | 
						|
        } catch (err) {
 | 
						|
            // 如果冻结失败,记录警告但不中断程序
 | 
						|
            LogUtils.warn('ConfigParseUtils', '无法冻结对象:', obj, err);
 | 
						|
        }
 | 
						|
 | 
						|
        return obj;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 创建配置数据的只读代理,提供更好的错误提示
 | 
						|
     */
 | 
						|
    public static createReadonlyProxy<T extends object>(obj: T, configName: string = '配置数据'): T {
 | 
						|
        return new Proxy(obj, {
 | 
						|
            set(target, property, value) {
 | 
						|
                const errorMsg = `❌ 禁止修改${configName}的属性 "${String(property)}"!配置数据在运行时应保持不可变。`;
 | 
						|
                LogUtils.error('ConfigParseUtils', errorMsg);
 | 
						|
                throw new Error(errorMsg);
 | 
						|
            },
 | 
						|
            defineProperty(target, property, descriptor) {
 | 
						|
                const errorMsg = `❌ 禁止定义${configName}的属性 "${String(property)}"!配置数据在运行时应保持不可变。`;
 | 
						|
                LogUtils.error('ConfigParseUtils', errorMsg);
 | 
						|
                throw new Error(errorMsg);
 | 
						|
            },
 | 
						|
            deleteProperty(target, property) {
 | 
						|
                const errorMsg = `❌ 禁止删除${configName}的属性 "${String(property)}"!配置数据在运行时应保持不可变。`;
 | 
						|
                LogUtils.error('ConfigParseUtils', errorMsg);
 | 
						|
                throw new Error(errorMsg);
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// 导出便捷的解析函数
 | 
						|
export const { parseVec2, parseVec3, parseVec4, parseColor, parseSize, parseRect, parseQuat, parseMat4, parseBoolean, parseInt, parseFloat, parseString, parseStringArray, parseNumberArray, deepFreeze, createReadonlyProxy } = ConfigParseUtils; |