
// import { _decorator, Component, Vec2, SystemEventType, EventTouch, UITransform, EventHandler, Vec3, v3 } from 'cc';
const { ccclass, property } = cc._decorator;
/**
 * @description 触摸辅助器，支持多边形区域点击检测，并且添加ceator不带有的tap事件
 * @author Soonsky
 */
@ccclass//('TouchHelper')
export class TouchHelper extends cc.Component {
    @property({ tooltip: "是否可以点击" }) canTouch: boolean = true;
    @property({ tooltip: "在多边形范围内产生点击", type: cc.Component.EventHandler }) onInPolygon: cc.Component.EventHandler = new cc.Component.EventHandler();
    @property({ tooltip: "在多边形范围外产生点击", type: cc.Component.EventHandler }) onOutPolygon: cc.Component.EventHandler = new cc.Component.EventHandler();
    @property({ tooltip: "在节点范围内产生点击", type: cc.Component.EventHandler }) onTouchTap: cc.Component.EventHandler = new cc.Component.EventHandler();
    @property({ tooltip: "是否与需要多边形检查" }) needPolygon: boolean = false;
    @property({ type: [cc.Vec2], tooltip: "多边形定点位置信息（局部坐标，至少3个点）" }) points: Array<cc.Vec2> = [];
    // @property({ tooltip: "点击在多边形区域内时是否阻止事件冒泡" }) stopPropagation = false;// 无效且报错

    private isMoved = false;
    start() {
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }

    private onTouchEnd(e: cc.Touch): void {
        if (this.canTouch && this.needPolygon && this.points.length >= 3) {
            let touchPoint = e.getLocation();
            let localPoint = this.node.convertToNodeSpaceAR(new cc.Vec2(touchPoint.x, touchPoint.y));
            let result = this.pointInPoly(localPoint, this.points);
            if (!this.isMoved) {
                if (result) {
                    // if (this.stopPropagation) {
                    //     e.propagationStopped = true;
                    // }
                    this.canTouch && this.onInPolygon && this.onInPolygon.emit([]);
                } else {
                    this.canTouch && this.onOutPolygon && this.onOutPolygon.emit([]);
                }
            }
        }
        if (this.canTouch) {
            if (!this.isMoved) {
                this.canTouch && this.onTouchTap && this.onTouchTap.emit([]);
            }
        }
        this.isMoved = false;
    }
    private onTouchMove(e: cc.Event.EventTouch) {
        if (e.getTouches().length > 1) { this.isMoved = true; return }// getAllTouches
        this.isMoved = cc.Vec2.distance(e.getStartLocation(), e.getLocation()) > 20;
    }
    private onTouchCancel(e: cc.Event.EventTouch) {
        this.isMoved = false;
    }

    private pointInPoly(point: cc.Vec2 | cc.Vec3, polyPoints: cc.Vec2[]) {
        for (var c = false, i = -1, l = polyPoints.length, j = l - 1; ++i < l; j = i)
            ((polyPoints[i].y <= point.y && point.y < polyPoints[j].y) || (polyPoints[j].y <= point.y && point.y < polyPoints[i].y))
                && (point.x < (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x)
                && (c = !c);
        return c;
    }
}

