"use strict";
cc._RF.push(module, 'b71dbmHabZDYbp1mKiWyuvs', 'AutoScroll');
// Script/AutoScroll.ts

"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var _a = cc._decorator, ccclass = _a.ccclass, property = _a.property;
var EPSILON = 1e-4;
var MOVEMENT_FACTOR = .7;
var quintEaseOut = function (time) {
    time -= 1;
    return (time * time * time * time * time + 1);
};
var AutoScroll = /** @class */ (function (_super) {
    __extends(AutoScroll, _super);
    function AutoScroll() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.maxScale = 1.5;
        _this.minScale = .5;
        _this.zoomSpace = 1;
        _this.bigMap = null;
        _this._touchMovePreviousTimestamp = 0;
        //是否在自动滚动
        _this._autoScrolling = false;
        _this._touchMoveDisplacements = [];
        _this._touchMoveTimeDeltas = [];
        _this.brake = 0.75;
        _this._autoScrollAccumulatedTime = 0;
        _this._autoScrollTotalTime = 0;
        _this._autoScrollStartPosition = cc.v2(0, 0);
        _this._autoScrollTargetDelta = cc.Vec2.ZERO;
        _this._isHandleMultiTouch = false;
        //是否在手动聚焦坐标
        _this._isOnDestScrolling = false;
        return _this;
    }
    AutoScroll.prototype.onLoad = function () {
        this.bigMap.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.bigMap.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.bigMap.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.bigMap.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    };
    AutoScroll.prototype.onDestroy = function () {
        this.bigMap.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.bigMap.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.bigMap.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.bigMap.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    };
    AutoScroll.prototype.start = function () {
    };
    AutoScroll.prototype.onTouchStart = function (e) {
        this.resetTouchInfos();
    };
    AutoScroll.prototype.onTouchMove = function (e) {
        if (this._isOnDestScrolling) {
            return;
        }
        var touches = e.getTouches();
        if (touches.length == 1) {
            var deltaMove = e.getDelta();
            this.moveContent(deltaMove);
            this.gatherTouchMove(deltaMove);
        }
        else {
            this._isHandleMultiTouch = true;
            var t0 = touches[0];
            var t1 = touches[1];
            var preSpace = t0.getPreviousLocation().sub(t1.getPreviousLocation()).mag();
            var curSpace = t0.getLocation().sub(t1.getLocation()).mag();
            var space = curSpace - preSpace;
            if (true) {
                var center = t0.getStartLocation().add(t1.getStartLocation()).divide(2);
                var n = this.node.convertToNodeSpaceAR(center);
                var w = this.node.convertToWorldSpaceAR(n);
                var nb = this.bigMap.convertToNodeSpaceAR(w);
                var targetScale = this.bigMap.scale + (space >= 0 ? this.zoomSpace : -this.zoomSpace);
                if (targetScale > this.maxScale) {
                    targetScale = this.maxScale;
                }
                else if (targetScale < this.minScale) {
                    targetScale = this.minScale;
                }
                var scaleSpace = targetScale - this.bigMap.scale;
                var v = nb.mul(-scaleSpace);
                //缩放后地图需要反向移动
                this.bigMap.scale = targetScale;
                this.moveContent(v);
            }
        }
    };
    AutoScroll.prototype.onTouchEnd = function (e) {
        if (this._isOnDestScrolling) {
            return;
        }
        if (!this._isHandleMultiTouch) {
            this.gatherTouchMove(e.getDelta());
            this.startInertiaScroll();
        }
        this._isHandleMultiTouch = false;
    };
    AutoScroll.prototype.onTouchCancel = function (e) {
        if (this._isOnDestScrolling) {
            return;
        }
        if (!this._isHandleMultiTouch) {
            this.gatherTouchMove(e.getDelta());
            this.startInertiaScroll();
        }
        this._isHandleMultiTouch = false;
    };
    AutoScroll.prototype.update = function (dt) {
        if (this._autoScrolling) {
            this.processAutoScrolling(dt);
        }
    };
    AutoScroll.prototype.calculateTouchMoveVelocity = function () {
        var totalTime = 0;
        totalTime = this._touchMoveTimeDeltas.reduce(function (a, b) {
            return a + b;
        }, totalTime);
        if (totalTime <= 0 || totalTime >= 0.5) {
            return cc.v2(0, 0);
        }
        var totalMovement = cc.v2(0, 0);
        totalMovement = this._touchMoveDisplacements.reduce(function (a, b) {
            return a.add(b);
        }, totalMovement);
        return cc.v2(totalMovement.x * (1 - this.brake) / totalTime, totalMovement.y * (1 - this.brake) / totalTime);
    };
    AutoScroll.prototype.processAutoScrolling = function (dt) {
        this._autoScrollAccumulatedTime += dt;
        var percentage = Math.min(1, this._autoScrollAccumulatedTime / this._autoScrollTotalTime);
        percentage = quintEaseOut(percentage);
        var newPosition = this._autoScrollStartPosition.add(this._autoScrollTargetDelta.mul(percentage));
        var reachedEnd = Math.abs(percentage - 1) <= EPSILON;
        if (reachedEnd) {
            this._autoScrolling = false;
        }
        var deltaMove = newPosition.sub(this.bigMap.getPosition());
        this.moveContent(this._clampDelta(deltaMove));
    };
    AutoScroll.prototype.startAttenuatingAutoScroll = function (deltaMove, initialVelocity) {
        var time = Math.sqrt(Math.sqrt(initialVelocity.mag() / 5));
        var targetDelta = deltaMove.normalize();
        var contentSize = this.bigMap.getContentSize();
        var scrollviewSize = this.node.getContentSize();
        var totalMoveWidth = (contentSize.width - scrollviewSize.width);
        var totalMoveHeight = (contentSize.height - scrollviewSize.height);
        var attenuatedFactorX = this.calculateAttenuatedFactor(totalMoveWidth);
        var attenuatedFactorY = this.calculateAttenuatedFactor(totalMoveHeight);
        targetDelta = cc.v2(targetDelta.x * totalMoveWidth * (1 - this.brake) * attenuatedFactorX, targetDelta.y * totalMoveHeight * attenuatedFactorY * (1 - this.brake));
        var originalMoveLength = deltaMove.mag();
        var factor = targetDelta.mag() / originalMoveLength;
        targetDelta = targetDelta.add(deltaMove);
        if (this.brake > 0 && factor > 7) {
            factor = Math.sqrt(factor);
            targetDelta = deltaMove.mul(factor).add(deltaMove);
        }
        if (this.brake > 0 && factor > 3) {
            factor = 3;
            time = time * factor;
        }
        if (this.brake === 0 && factor > 1) {
            time = time * factor;
        }
        this.startAutoScroll(targetDelta, time);
    };
    AutoScroll.prototype.calculateAttenuatedFactor = function (distance) {
        if (this.brake <= 0) {
            return (1 - this.brake);
        }
        return (1 - this.brake) * (1 / (1 + distance * 0.000014 + distance * distance * 0.000000008));
    };
    AutoScroll.prototype.startInertiaScroll = function () {
        var touchMoveVelocity = this.calculateTouchMoveVelocity();
        if (!touchMoveVelocity.fuzzyEquals(cc.v2(0, 0), EPSILON) && this.brake < 1) {
            var inertiaTotalMovement = touchMoveVelocity.mul(MOVEMENT_FACTOR);
            this.startAttenuatingAutoScroll(inertiaTotalMovement, touchMoveVelocity);
        }
    };
    AutoScroll.prototype.startAutoScroll = function (deltaMove, timeInSecond) {
        this._autoScrolling = true;
        this._autoScrollTargetDelta = deltaMove;
        this._autoScrollStartPosition = this.bigMap.getPosition();
        this._autoScrollTotalTime = timeInSecond;
        this._autoScrollAccumulatedTime = 0;
    };
    AutoScroll.prototype._clampDelta = function (delta) {
        var contentSize = this.bigMap.getContentSize();
        var scrollViewSize = this.node.getContentSize();
        if (contentSize.width < scrollViewSize.width) {
            delta.x = 0;
        }
        if (contentSize.height < scrollViewSize.height) {
            delta.y = 0;
        }
        return delta;
    };
    AutoScroll.prototype.moveContent = function (deltaMove, duration) {
        var _this = this;
        if (duration === void 0) { duration = 0; }
        return new Promise(function (resolve) {
            var adjustedMove = deltaMove;
            var newPosition = _this.bigMap.getPosition().add(adjustedMove);
            if (newPosition.x > _this.boundX) {
                newPosition.x = _this.boundX;
                _this._autoScrolling = false;
            }
            else if (newPosition.x < -_this.boundX) {
                newPosition.x = -_this.boundX;
                _this._autoScrolling = false;
            }
            if (newPosition.y > _this.boundY) {
                newPosition.y = _this.boundY;
                _this._autoScrolling = false;
            }
            else if (newPosition.y < -_this.boundY) {
                newPosition.y = -_this.boundY;
                _this._autoScrolling = false;
            }
            if (duration > 0) {
                cc.tween(_this.bigMap)
                    .to(duration, { position: cc.v3(newPosition.x, newPosition.y) })
                    .call(function () {
                    resolve();
                })
                    .start();
            }
            else {
                _this.bigMap.setPosition(newPosition);
                resolve();
            }
        });
    };
    AutoScroll.prototype.getTimeInMilliseconds = function () {
        var currentTime = new Date();
        return currentTime.getMilliseconds();
    };
    AutoScroll.prototype.gatherTouchMove = function (delta) {
        delta = this._clampDelta(delta);
        while (this._touchMoveDisplacements.length >= 5) {
            this._touchMoveDisplacements.shift();
            this._touchMoveTimeDeltas.shift();
        }
        this._touchMoveDisplacements.push(delta);
        var timeStamp = this.getTimeInMilliseconds();
        this._touchMoveTimeDeltas.push((timeStamp - this._touchMovePreviousTimestamp) / 1000);
        this._touchMovePreviousTimestamp = timeStamp;
    };
    Object.defineProperty(AutoScroll.prototype, "boundY", {
        get: function () {
            return this.bigMap.height * this.bigMap.scaleY / 2 - this.node.height / 2;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(AutoScroll.prototype, "boundX", {
        get: function () {
            return this.bigMap.width * this.bigMap.scaleX / 2 - this.node.width / 2;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * 地图滚动
     * @param dest 目标地点
     * @param duration 动画时间
     */
    AutoScroll.prototype.scrollTo = function (dest, duration) {
        var _this = this;
        if (duration === void 0) { duration = 0; }
        this._isOnDestScrolling = true;
        this.resetTouchInfos();
        return new Promise(function (resolve) {
            _this.moveContent(dest.mul(-1), duration).then(function () {
                _this._isOnDestScrolling = false;
                resolve();
            });
        });
    };
    AutoScroll.prototype.resetTouchInfos = function () {
        this._autoScrolling = false;
        this._touchMovePreviousTimestamp = this.getTimeInMilliseconds();
        this._touchMoveDisplacements.length = 0;
        this._touchMoveTimeDeltas.length = 0;
        this._isHandleMultiTouch = false;
    };
    __decorate([
        property({
            tooltip: '最大可放大倍数'
        })
    ], AutoScroll.prototype, "maxScale", void 0);
    __decorate([
        property({
            tooltip: '最小可缩小倍数'
        })
    ], AutoScroll.prototype, "minScale", void 0);
    __decorate([
        property({ tooltip: '多点触摸缩放增量' })
    ], AutoScroll.prototype, "zoomSpace", void 0);
    __decorate([
        property(cc.Node)
    ], AutoScroll.prototype, "bigMap", void 0);
    AutoScroll = __decorate([
        ccclass
    ], AutoScroll);
    return AutoScroll;
}(cc.Component));
exports.default = AutoScroll;

cc._RF.pop();