import { SpriteFrame, Vec3, Node, Vec2, Button, v2, sys, instantiate, game, Game, v3, Sprite, misc, UITransform, Layers, Camera, Canvas, director, Director, ImageAsset, renderer, RenderTexture, Size, Texture2D, view, sp } from "cc";
import { PlatformManager } from "../manager/PlatformManager";
import { ResModel } from "../model/ResModel";
import { LoadTools } from "./LoadTools";
import { AStar } from "./AStar";
import { BFSPathfinding } from "./BFS";
import { SplitRenderHelper } from "../SplitRender/SplitRenderHelper";

export type index = {
    x: number;
    y: number;
}

//@ts-ignore
game._calculateDT = function _calculateDT(useFixedDeltaTime: boolean): number {
    this._useFixedDeltaTime = useFixedDeltaTime;

    if (useFixedDeltaTime) {
        this._startTime = performance.now();
        return this.frameTime / 1000;
    }

    const now = performance.now();
    this._deltaTime = now > this._startTime ? (now - this._startTime) / 1000 : 0;
    if (this._deltaTime > Game.DEBUG_DT_THRESHOLD) {
        this._deltaTime = this.frameTime / 1000;
    }
    this._startTime = now;
    return this._deltaTime * Tools.getTimeScale();
}

/** 游戏常用工具类 */
export class Tools {
    private static timeScale = 1;

    private static aStar: AStar = new AStar();

    private static bfs: BFSPathfinding = new BFSPathfinding();

    /**
     * 使用A*算法进行搜索。
     * @param map 二维数字数组，代表地图或其他需要搜索的结构。
     * @param start 搜索的起始点，其格式为 index 类型。
     * @param end 搜索的终点，其格式为 index 类型。
     * @param type 搜索类型，用数字表示，默认为 0。不同的类型可能影响搜索算法的行为。
     * @returns 返回搜索结果，通常是一个路径数组或者搜索到的目标。
     */
    public static aStarSearch(map: number[][], start: index, end: index, type: number = 0) {
        this.aStar.setMap(map);
        return this.aStar.search(start, end, type);
    }

    public static setaStarValue(startValue: number, endValue: number, pathValue: number) {
        this.aStar.setValue(startValue, endValue, pathValue);
    }

    public static setaStarEightDirections(isEightDirections: boolean) {
        this.aStar.setEightDirections(isEightDirections);
    }

    public static setaStarWeightMap(weightMap: number[][]) {
        this.aStar.setWeightMap(weightMap);
    }

    public static setaStarNeighborMap(neighborMap: Map<index, index[]>) {
        this.aStar.setNeighborMap(neighborMap);
    }

    /**
     * 使用广度优先搜索算法在地图上寻找从起点到终点的路径。
     * @param map 二维数字数组表示的地图。
     * @param start 起点的索引。
     * @param end 终点的索引。
     * @returns 返回一个路径数组，如果不存在路径则返回空数组。
     */
    public static bfsSearch(map: number[][], start: index, end: index) {
        this.bfs.setMap(map); // 设置广度优先搜索对象的地图
        return this.bfs.findPath(start, end); // 执行搜索并返回路径
    }

    /**
     * 存储本地数据
     * @param {*} isObject 是否是一个对象或者数组
     */
    public static setStorage(key: string, value: any, isObject = false) {
        PlatformManager.setStorage(key, value, isObject);
    }
    /**
     * 获取存储数据
     * @param {*} isObject 是否是一个对象或者数组
     */
    public static getStorage(key: string, isObject = false) {
        return PlatformManager.getStorage(key, isObject);
    };

    /**
    * 获取时间缩放
    * @returns 时间缩放
    */
    public static getTimeScale() {
        return Tools.timeScale;
    }

    /**
     * 设置时间缩放
     * @param scale 时间缩放
     */
    public static setTimeScale(scale: number) {
        Tools.timeScale = scale;
    }

    /**
     * 获取截图
     * @param node 截图的节点
     * @param parent 截图的父节点
     * @param pos 截图的位置
     * @param canvas 默认摄像机渲染的canvas
     * @param normalCamera 默认摄像机
     */
    public static getScreenShot(node: Node, parent: Node, pos: Vec3, canvas: Canvas, normalCamera: Camera) {
        const newCamera = new Node("PhotoCamera");

        newCamera.setParent(canvas.node);
        newCamera.setPosition(0, 0, 1000);
        newCamera.addComponent(Camera);
        newCamera.getComponent(Camera).visibility = normalCamera.visibility;
        newCamera.getComponent(Camera).clearFlags = normalCamera.clearFlags;
        newCamera.getComponent(Camera).near = normalCamera.near;
        newCamera.getComponent(Camera).far = normalCamera.far;
        newCamera.getComponent(Camera).projection = renderer.scene.CameraProjection.ORTHO;
        newCamera.getComponent(Camera).orthoHeight = normalCamera.orthoHeight;

        const newRenderTexture = new RenderTexture();
        newRenderTexture.reset({
            width: view.getVisibleSize().width,
            height: view.getVisibleSize().height
        });
        newCamera.getComponent(Camera).targetTexture = newRenderTexture;

        director.once(Director.EVENT_AFTER_DRAW, () => {
            const newSpriteFrame = new SpriteFrame();

            let data = newRenderTexture.readPixels(Math.round(node.getWorldPosition().x - node.getComponent(UITransform).width / 2 * node.scale.x),
                Math.round(node.getWorldPosition().y - node.getComponent(UITransform).height / 2 * node.scale.y),
                node.getComponent(UITransform).width * node.scale.x, node.getComponent(UITransform).height * node.scale.y)

            let image = new ImageAsset();
            image.reset({
                _data: data,
                _compressed: false,
                width: node.getComponent(UITransform).width * node.scale.x,
                height: node.getComponent(UITransform).height * node.scale.y,
                format: Texture2D.PixelFormat.RGBA8888
            })

            let newTexture = new Texture2D();
            newTexture.image = image;
            newSpriteFrame.texture = newTexture;
            newSpriteFrame.packable = false;

            if (sys.isNative && (sys.os === sys.OS.IOS || sys.os === sys.OS.OSX)) {
                newSpriteFrame.flipUVY = false;
            } else {
                newSpriteFrame.flipUVY = true;
            }

            let newSprite = new Node("PhotoSprite");
            newSprite.addComponent(Sprite);
            newSprite.setParent(parent);
            newSprite.setPosition(pos);
            newSprite.layer = Layers.Enum.UI_2D;
            newSprite.getComponent(UITransform)
                .setContentSize(new Size(node.getComponent(UITransform).width,
                    node.getComponent(UITransform).height));
            newSprite.getComponent(Sprite).spriteFrame = newSpriteFrame;

            newCamera.getComponent(Camera).targetTexture = null;
        })
    }

    /**
    * 保存文件。
    * @param textToWrite 要保存的文件内容
    * @param fileNameToSaveAs 要保存的文件名
    * @param fileType 要保存的文件格式,默认为Json
    */
    public static saveForBrowser(textToWrite: any, fileNameToSaveAs: string, fileType: string = 'application/json') {
        if (sys.isBrowser) {
            console.log("浏览器");
            let textFileAsBlob = new Blob([textToWrite], { type: fileType });
            let downloadLink = document.createElement("a");
            downloadLink.download = fileNameToSaveAs;
            downloadLink.innerHTML = "Download File";
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);

            downloadLink.click();
        }
    }

    /**
     * 获取spine指定动画时间,如果没有该动画 则返回0
     * @param spine 骨骼动画
     * @param aniName 动画名称
     * @returns 动画时间
     */
    public static getSpineAnimationTime(spine: sp.Skeleton, aniName: string) {
        const state = spine.getState();
        if (state == undefined) throw `[ERROR SPINE ANIMATION] 无法获取获取动画状态`;
        const { animations } = state.data.skeletonData;
        let result = 0;
        for (const key in animations) {
            if (Object.prototype.hasOwnProperty.call(animations, key)) {
                const element = animations[key];
                if (element.name == aniName) {
                    result = element.duration;
                }
            }
        }
        return result;
    }

    //-----------------------------节点预制体相关-------------------------------
    /**
     * 新建一个预制体在场景里
     * @param preName 预制体名字或url
     * @param callFunc 加载预制体 完成后回调
     * @param parent 存放预制体的父节点
     * @param Pos 预制体的坐标
     * @param zIndex 预制体的层级
     */
    public static newPrefab(preName: string, parent?: Node, Pos?: Vec3, callFunc?: (age?: Node) => void): Node {
        return NodeTools._ins.newPrefab(preName, callFunc, parent, Pos);
    }
    /**
     * 新建一个图片在场景里
     * @param sprName 图片名字或url
     * @param callFunc 加载预制体 完成后回调
     * @param parent 存放预制体的父节点
     * @param Pos 预制体的坐标
     * @param zIndex 预制体的层级
     */
    public static newSprite(sprName: string, parent?: Node, Pos?: Vec3, callFunc?: (age?: Node) => void): Node {
        return NodeTools._ins.newSprite(sprName, callFunc, parent, Pos);
    }
    /**
     * 设置一个节点的SpriteFrame
     * @param nodeT 节点的Node
     * @param sprUrl 图片的url或者存放到resArr的名字
     */
    public static setSpriteFrame(nodeT: Node, sprUrl: string) {
        NodeTools._ins.setSpriteFrame(nodeT, sprUrl);
    }
    /** 设置一个节点的 groupIndex 包含子物体 */
    public static setNodeLayerIndex(nodeT: Node, layer: Layers.Enum) {
        NodeTools._ins.setNodeLayerIndex(nodeT, layer);
    }
    /**
     * 设置一个Button的按下和松开的SpriteFrame
     * @param norUrl 默认状态的名字或者路径
     * @param preUrl 按下状态的名字或者路径
     */
    public static setBtnClickSpr(Btn: Button, norUrl: string, preUrl: string) {
        NodeTools._ins.setBtnClickSpr(Btn, norUrl, preUrl);
    };
    /** 切换父物体 不改变显示位置*/
    public static setNodeParent(node: Node, parent: Node) {
        NodeTools._ins.setNodeParent(node, parent);
    };
    //----------------------------------数学数组相关----------------------------------

    /**
     * 将多维数组展平
     * @param arr 需要展平的多维数组
     * @returns 展平后的数组
     */
    public static flatArray(arr: any[]) {
        return arr.reduce((acc, curr) => {
            return acc.concat(Array.isArray(curr) ? Tools.flatArray(curr) : curr);
        }, []);
    }

    /**
     * 从数组中随机获取元素
     * @param arr 需要随机获取元素的数组
     * @param num 需要获取的元素数量
     * @param sortFunc 排序函数，可选
     * @returns 返回随机获取的元素数组
     */
    public static randomGetElementFromArray(arr: any[], num: number, sortFunc: (a: any, b: any) => number = null) {
        const tempArr = arr.slice();
        const resultArr = [];
        while (resultArr.length < num) {
            const randomIndex = Tools.random(0, tempArr.length - 1);
            resultArr.push(tempArr[randomIndex]);
            tempArr.splice(randomIndex, 1);
        }
        if (sortFunc) {
            resultArr.sort(sortFunc);
        }
        return resultArr;
    }

    /**
     * 获取随机数
     * @param isInteger 是否随机整数  默认整数
     */
    public static random(x1: number, x2: number, isInteger = true): number {
        return MathTools._ins.random(x1, x2, isInteger);
    }
    /**
     * 根据概率数组 随机概率 返回数组的index
     * @param chooseArr 需要随机概率的数组 例如[0.05,0.1,0.2,0.3]
     */
    public static chooseRandom(chooseArr: Array<number>) {
        return MathTools._ins.chooseRandom(chooseArr);
    }
    /** 传入一个弧度 返回一个Y轴折射后的弧度 */
    public static refractionY(rad: number) {
        return MathTools._ins.refractionY(rad);
    };
    /** 传入一个弧度 返回一个轴折射后的弧度 */
    public static refractionX(rad: number) {
        return MathTools._ins.refractionX(rad);
    };
    /** 重新打乱一个数组的顺序  洗牌 */
    public static againSortArr(Arr: Array<any>) {
        MathTools._ins.againSortArr(Arr);
    };
    /**
     * 将一个数组 按照里面的对象排序 
     * @param tempArr 传入的数组
     * @param sortName 对象属性名字
     * @param isReverse 是否倒序
     */
    public static sortArrForObject(tempArr: Array<any>, sortName: string, isReverse = false) {
        MathTools._ins.sortArrForObject(tempArr, sortName, isReverse);
    };
    /**
     * 取一定范围内不重复的数字
     * @param minNum 最小取值范围
     * @param maxNum 最大取值范围
     * @param getNum 取几个数字
     */
    public static getDiffNumRandom(minNum: number, maxNum: number, getNum: number) {
        return MathTools._ins.getDiffNumRandom(minNum, maxNum, getNum);
    };
    //--------------------------------向量坐标计算相关------------------------------------
    /**
     * 根据两个点  求角度
     * @param pos1 起始点坐标
     * @param pos2 结束点坐标
     * @param isVertical 是否以竖直方向为0度开始
     */
    public static getAngleForPos(pos1: Vec2, pos2: Vec2, isVertical = false): number {
        return VecTools._ins.getAngleForPos(pos1, pos2, isVertical);
    };
    /** 获取两个坐标之间的距离 */
    public static getDistance(pos1: Vec3 | Vec2, pos2: Vec3 | Vec2): number {
        if (pos1 instanceof Vec2 && pos2 instanceof Vec2) {
            return Vec2.distance(pos1, pos2);
        }
        if (pos1 instanceof Vec3 && pos2 instanceof Vec3) {
            return Vec3.distance(pos1, pos2);
        }
    };
    /**
     * 根据一个角度和长度 计算相对应的坐标
     * @param angle 角度
     * @param len 该角度上的长度
     * @param startPos 初始的坐标
     */
    public static getPosForAngleLen(angle: number, len: number, startPos: Vec2 = v2(0, 0)) {
        return VecTools._ins.getPosForAngleLen(angle, len, startPos);
    }
    /**
     * 获取节点在另一个节点下的坐标
     * @param obj 节点
     * @param mainObj 相对于的另一个节点
     */
    public static getToNodePosForNode(obj: Node, mainObj: Node): Vec2 {
        return VecTools._ins.getToNodePosForNode(obj, mainObj);
    };
    /** 获取节点的世界坐标 */
    public static getToWorldPosAR(obj: Node) {
        return VecTools._ins.getToWorldPosAR(obj);
    }
    /**
     * 通过世界坐标 获取相对节点的坐标
     * @param worldPos 世界坐标
     * @param obj 相对节点下的
     */
    public static getToNodePosForWorld(worldPos: Vec3, obj: Node) {
        return VecTools._ins.getToNodePosForWorld(worldPos, obj);
    }
    /** 二维向量转三维向量 */
    public static getVec3ForVec2(vec2: Vec2) {
        return VecTools._ins.getVec3ForVec2(vec2);
    }
    /** 三维向量转二维向量 */
    public static getVec2ForVec3(vec3: Vec3) {
        return VecTools._ins.getVec2ForVec3(vec3);
    }
    /** 获取两向量方向 */
    public static getDirection(startPos: Vec3 | Vec2, endPos: Vec3 | Vec2) {
        return VecTools._ins.getDirection(startPos, endPos);
    }
    /** 获取多边形面积 */
    public static getPolygonArea(polygon: Vec2[]) {
        return VecTools._ins.getPolygonArea(polygon);
    }
    //--------------------------------数组操作相关------------------------------------
    /** 根据value值 从数组里面移除 */
    public static removeArrForValue(tempArr: Array<any>, value: any) {
        return tempArr.splice(tempArr.indexOf(value), 1);
    }
    /** 从数组里面添加一个该数组里没有的元素 */
    public static addArrNoValue(tempArr: Array<any>, value: any) {
        if (tempArr.indexOf(value) < 0) {
            tempArr.push(value);
            return true;
        }
        return false;
    }
    /** 从数组指定位置 插入某个元素 */
    public static addArrIndex(tempArr: Array<any>, index: number, value: any) {
        return tempArr.splice(index, 0, value);
    }
    //--------------------------------其他------------------------------------
    /**
     *  字符串指定位置插入新字符 
     * @param source 需要操作的字符串
     * @param start 从那个位置开始插入
     * @param newStr 插入的新的字符
     */
    public static insertStrForIndex(source: string, start: number, newStr: string): string {
        return source.slice(0, start) + newStr + source.slice(start);
    };
    /**
     * 数字整数前边补零 并返回字符串
     * @param num 传入的数字
     * @param length 前边补几个零
     */
    public static prefixInteger(num: number, length = 2): string {
        return (Array(length).join('0') + num).slice(-length);
    };
    /** 获取系统语言 */
    public static getLanguageType(): string {
        var langNumType = "EN";   //默认英语
        if (sys.language == sys.Language.CHINESE) {
            if (sys.languageCode.toLowerCase().indexOf("zh-cn") != -1 ||
                sys.languageCode.toLowerCase().indexOf("zh_cn") != -1 ||
                sys.languageCode.toLowerCase().indexOf("zh-hans-cn") != -1) {
                langNumType = "CN";  //简体
            } else {
                langNumType = "CHT";  //繁体
            }
        }
        // else if ( sys.language == sys.Language.KOREAN ) {
        //     langNumType = "KOR"; //韩语
        // }
        // else if (sys.language == sys.Language.JAPANESE) {
        //     langNumType = "JP"; //日语
        // }
        // else if ( window.navigator.language == "th-TH" ) {
        //     langNumType = "TH"; //泰语
        // }
        return langNumType;
    }
}


/** 节点相关 工具类 */
class NodeTools {
    /** 单例模式 */
    private static _instance: NodeTools = new NodeTools();
    private constructor() { }
    public static get _ins() {
        return this._instance;
    }

    /** 新建一个预制体在场景里 */
    public newPrefab(preName: string, callFunc?: (age?: Node) => void, parent?: Node, Pos?: Vec3): Node {
        let prefab = ResModel._ins.PrefabDic.get(preName);
        let clone: Node = null;
        if (prefab != null) {
            clone = instantiate(prefab);
            if (parent) { parent.addChild(clone) };
            if (Pos) { clone.position = v3(Pos.x, Pos.y, Pos.z) };
            if (callFunc != null) {
                callFunc(clone);
            }
        } else {
            LoadTools._ins.loadResPrefab(preName, callFunc, parent, Pos);
        }
        return clone;
    }
    /** 新建一个图片在场景里 */
    public newSprite(sprName: string, callFunc?: (age?: Node) => void, parent?: Node, Pos?: Vec3) {
        let sprite = new Node();
        sprite.name = sprName;
        sprite.layer = Layers.Enum.UI_2D;
        if (ResModel._ins.SpriteFrameDic.get(sprName) != null) {
            sprite.addComponent(Sprite).spriteFrame = ResModel._ins.SpriteFrameDic.get(sprName);
            if (parent) { parent.addChild(sprite) };
            if (Pos) { sprite.position = v3(Pos.x, Pos.y, Pos.z) };
            if (callFunc != null) {
                callFunc(sprite);
            }
        } else {
            sprite.addComponent(Sprite);
            LoadTools._ins.loadResSpriteFrame(sprName, sprite, parent, Pos, callFunc);
        }
        return sprite;
    }
    /** 设置一个节点的SpriteFrame */
    public setSpriteFrame(nodeT: Node, sprUrl: string) {
        if (nodeT.getComponent(Sprite) == null) {
            nodeT.addComponent(Sprite);
        }
        if (ResModel._ins.SpriteFrameDic.get(sprUrl)) {
            nodeT.getComponent(Sprite).spriteFrame = ResModel._ins.SpriteFrameDic.get(sprUrl)
        } else {
            LoadTools._ins.loadResAny(sprUrl, SpriteFrame, (spriteFrame: SpriteFrame) => {
                nodeT.getComponent(Sprite).spriteFrame = spriteFrame;
            })
        }
    }
    /** 设置一个节点的 所属层 包含子物体 */
    public setNodeLayerIndex(nodeT: Node, layer: Layers.Enum) {
        nodeT.layer = layer;
        for (let i = 0; i < nodeT.children.length; i++) {
            this.setNodeLayerIndex(nodeT.children[i], layer);
        }
    }
    /** 设置一个Button的按下和松开的SpriteFrame */
    public setBtnClickSpr(Btn: Button, norUrl: string, preUrl: string) {
        if (ResModel._ins.SpriteFrameDic.get(norUrl)) {
            Btn.getComponent(Button).normalSprite = ResModel._ins.SpriteFrameDic.get(norUrl)
            Btn.getComponent(Button).hoverSprite = ResModel._ins.SpriteFrameDic.get(norUrl)
            Btn.getComponent(Button).pressedSprite = ResModel._ins.SpriteFrameDic.get(preUrl)
        } else {
            LoadTools._ins.loadResAny(norUrl, SpriteFrame, (spr: SpriteFrame) => {
                Btn.getComponent(Button).normalSprite = spr;
                Btn.getComponent(Button).hoverSprite = spr;
            });
            LoadTools._ins.loadResAny(preUrl, SpriteFrame, (spr: SpriteFrame) => {
                Btn.getComponent(Button).pressedSprite = spr;
            });
        }
    };
    /** 切换父物体 不改变坐标 */
    public setNodeParent(node: Node, parent: Node) {
        let Pos = VecTools._ins.getToNodePosForNode(node, parent);
        node.parent = parent;
        node.position = v3(Pos.x, Pos.y);
    };
}

/** 数学数组计算相关 工具类 */
class MathTools {
    /** 单例模式 */
    private static _instance: MathTools = new MathTools();
    private constructor() { }
    public static get _ins() {
        return this._instance;
    }

    /** 获取随机数 */
    public random(x1: number, x2: number, isInteger = true): number {
        if (isInteger) {
            return x1 + Math.floor(Math.random() * (x2 - x1 + 1));
        }
        return Math.random() * (x2 - x1) + x1;
    }
    /**  根据概率数组 随机概率 返回数组的index */
    public chooseRandom(chooseArr: Array<number>) {
        let total = 0;  //概率总值
        //首先计算出概率的总值，用来计算随机范围
        for (let i = 0; i < chooseArr.length; i++) {
            total += chooseArr[i];
        }
        let randNum = this.random(0, total, false)
        for (let i = 0; i < chooseArr.length; i++) {
            if (randNum < chooseArr[i] && chooseArr[i] > 0) {
                return i;
            } else {
                randNum -= chooseArr[i];
            }
        }
        return chooseArr.length - 1;
    }
    /** 弧度折射Y轴 */
    public refractionY(rad: number) {
        return Math.atan2(Math.sin(rad), -Math.cos(rad));
    };
    /** 弧度折射X轴 */
    public refractionX(rad: number) {
        return Math.atan2(-Math.sin(rad), Math.cos(rad));
    };
    /** 重新洗牌 一个数组 */
    public againSortArr(Arr: Array<any>) {
        for (let i = 0; i < Arr.length; i++) {
            let tempR = Tools.random(0, Arr.length - 1);
            if (tempR != i) {
                let temp = Arr[i];
                Arr[i] = Arr[tempR];
                Arr[tempR] = temp;
            }
        }
    }
    /** 数组 对象排序  对象属性  是否倒序 */
    public sortArrForObject(tempArr: Array<any>, sortName: string, isReverse = false) {
        if (!isReverse) {
            tempArr.sort((a, b) => {
                return a[sortName] - b[sortName];
            });
        } else {
            tempArr.sort((a, b) => {
                return b[sortName] - a[sortName];
            });
        }
    };
    /** 取一定范围内不重复的数字 */
    public getDiffNumRandom(minNum: number, maxNum: number, getNum: number) {
        var arr = [];
        for (let i = minNum; i <= maxNum; i++) {
            arr.push(i);
        }
        const tempLen = arr.length - getNum;
        for (let i = 0; i < tempLen; i++) {
            let tempI = Tools.random(0, arr.length - 1);
            arr.splice(tempI, 1);
        }
        return arr;
    };
}

/** 向量坐标转换相关工具类 */
class VecTools {
    /** 单例模式 */
    private static _instance: VecTools = new VecTools();
    private constructor() { }
    public static get _ins() {
        return this._instance;
    }

    /** 根据两个点  求角度 */
    public getAngleForPos(pos1: Vec2, pos2: Vec2, isVertical = false): number {
        let rad = 0;
        if (isVertical) {
            rad = -Math.atan2(pos2.x - pos1.x, pos2.y - pos1.y);
        } else {
            rad = Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x);
        }
        return misc.radiansToDegrees(rad);
    }
    /** 根据一个角度和长度 计算相对应的坐标 */
    public getPosForAngleLen(angle: number, len: number, startPos: Vec2 = v2(0, 0)) {
        let rad = misc.degreesToRadians(angle);
        return v2(startPos.x + Math.cos(rad) * len, startPos.y + Math.sin(rad) * len);
    }
    /** 获取节点在另一个节点下的坐标 */
    public getToNodePosForNode(obj: Node, mainObj: Node): Vec2 {
        let worldPos = obj.parent.getComponent(UITransform).convertToWorldSpaceAR(obj.position);
        let nodePos = mainObj.getComponent(UITransform).convertToNodeSpaceAR(worldPos)
        return v2(nodePos.x, nodePos.y);
    };
    /** 获取节点的世界坐标 */
    public getToWorldPosAR(obj: Node) {
        return obj.parent.getComponent(UITransform).convertToWorldSpaceAR(obj.position);
    }
    /** 通过世界坐标 获取相对节点的坐标 */
    public getToNodePosForWorld(worldPos: Vec3, obj: Node) {
        return obj.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
    }

    /** 二维向量转三维向量 */
    public getVec3ForVec2(vec2: Vec2) {
        return v3(vec2.x, vec2.y, 0);
    }

    /** 三维向量转二维向量 */
    public getVec2ForVec3(vec3: Vec3) {
        return v2(vec3.x, vec3.y);
    }

    /** 获取两向量方向和距离
     * @param startPos 起始位置
     * @param endPos 结束位置
     */
    public getDirection(startPos: Vec3 | Vec2, endPos: Vec3 | Vec2) {
        if (startPos instanceof Vec2 && endPos instanceof Vec2) {
            const deltaPos = endPos.clone().subtract(startPos);
            const direction = deltaPos.normalize();
            return direction;
        } else if (startPos instanceof Vec3 && endPos instanceof Vec3) {
            const deltaPos = endPos.clone().subtract(startPos);
            const direction = deltaPos.normalize();
            return direction;
        }
    }

    public getPolygonArea(polygon: Vec2[]) {
        return SplitRenderHelper.calculatePolygonArea(polygon);
    }
}
