"use strict";
cc._RF.push(module, 'b57a5V1gv9Nz4po2YAT64Bx', 'bezier_assembler');
// OP13/script/bezier_assembler.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 (Object.prototype.hasOwnProperty.call(b, 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 __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var page_effect_assembler_base_1 = require("./page_effect_assembler_base");
var gfx = cc.gfx;
var vfmtPosUvColorFront = new gfx.VertexFormat([
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
    { name: "a_isFront", type: gfx.ATTR_TYPE_FLOAT32, num: 1 },
]);
var BezierAssembler = /** @class */ (function (_super) {
    __extends(BezierAssembler, _super);
    function BezierAssembler() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.angle = 0;
        return _this;
    }
    BezierAssembler.prototype.updateRenderData = function (comp) {
        if (comp) {
            var pointNum = comp.getPointCount();
            if (pointNum < 2) {
                return;
            }
            var node = comp.node;
            var height = node.height;
            var width = node.width;
            // 左下角的坐标
            var posX = -width * node.anchorX;
            var posY = -height * node.anchorY;
            // 根据角度获得控制点的位置
            var ctrlPosData = this._getCtrlPosByAngle(width);
            var startPos = ctrlPosData.startPos;
            var endPos = ctrlPosData.endPos;
            var ctrlPos1 = ctrlPosData.ctrlPos1;
            var ctrlPos2 = ctrlPosData.ctrlPos2;
            // 记录各个顶点的位置
            var bezierPosList = [];
            bezierPosList[0] = startPos;
            // 当前所有顶点连线的总长
            var realWidth = 0;
            // 上一个点的纹理坐标
            var lastU = 0;
            // 下一个点的纹理坐标
            var nextU = 0;
            var floatsPerVert = this.floatsPerVert;
            var verts = this.renderData.vDatas[0];
            // 写verts时的下标
            var dstOffset = 0;
            for (var i = 1; i < pointNum; i++) {
                var isTail = i === pointNum - 1;
                var lastBezierPos = bezierPosList[i - 1];
                var nextBezierPos = this._getBezierPos(i / (pointNum - 1), startPos, endPos, ctrlPos1, ctrlPos2);
                var fixedData = this._fixWidth(lastBezierPos, nextBezierPos, width, realWidth, isTail);
                var gapWidth = fixedData.gapWidth;
                nextBezierPos = fixedData.nextBezierPos;
                realWidth += gapWidth;
                bezierPosList[i] = nextBezierPos;
                // 根据当前小矩形的宽度占总长度的比例来计算纹理坐标的间隔
                var gapU = gapWidth / width;
                nextU = lastU + gapU;
                /*
                    分别计算小矩形四个顶点的坐标和纹理坐标
                    各顶点的坐标计算方法为在左下角坐标的基础上加上顶点在贝塞尔曲线上的坐标，如果是书页顶部的顶点则还要加上书页的高度
                */
                // 将4个顶点数据写入verts
                dstOffset = floatsPerVert * (i - 1) * 4;
                verts[dstOffset] = posX + lastBezierPos.x;
                verts[dstOffset + 1] = posY + lastBezierPos.y;
                verts[dstOffset + 2] = lastU;
                verts[dstOffset + 3] = 1;
                dstOffset += floatsPerVert;
                verts[dstOffset] = posX + nextBezierPos.x;
                verts[dstOffset + 1] = posY + nextBezierPos.y;
                verts[dstOffset + 2] = nextU;
                verts[dstOffset + 3] = 1;
                dstOffset += floatsPerVert;
                verts[dstOffset] = posX + lastBezierPos.x;
                verts[dstOffset + 1] = posY + height + lastBezierPos.y;
                verts[dstOffset + 2] = lastU;
                verts[dstOffset + 3] = 0;
                dstOffset += floatsPerVert;
                verts[dstOffset] = posX + nextBezierPos.x;
                verts[dstOffset + 1] = posY + height + nextBezierPos.y;
                verts[dstOffset + 2] = nextU;
                verts[dstOffset + 3] = 0;
                lastU = nextU;
            }
            this.updateColor(comp, null);
            this.updateIsFront(comp, 5);
        }
    };
    BezierAssembler.prototype.init = function (comp) {
        _super.prototype.init.call(this, comp);
        //@ts-ignore
        var segmentCount = comp.getPointCount() - 1;
        this.verticesCount = 4 * segmentCount;
        this.indicesCount = 6 * segmentCount;
        this.floatsPerVert = 6;
        this.initData();
    };
    BezierAssembler.prototype.getVfmt = function () {
        return vfmtPosUvColorFront;
    };
    BezierAssembler.prototype._getCtrlPosByAngle = function (width) {
        var startPos = new cc.Vec2(0, 0);
        var endPos = null;
        var ctrlPos1 = null;
        var ctrlPos2 = null;
        var rad = this.angle * Math.PI / 180;
        var per = rad * 2 / Math.PI;
        if (this.angle <= 90) {
            // 终点的x坐标变换 width => 0，速度先慢后快，使用InCubic缓动函数
            var endPosX = width * (1 - Math.pow(per, 3));
            // InCubic
            // 终点的y坐标变换 0 => width / 4, 速度先快后慢，使用OutQuart缓动函数
            var endPosY = width / 4 * (1 - Math.pow(1 - per, 4));
            endPos = new cc.Vec2(endPosX, endPosY);
            // 中间两个控制点坐标匀速变换
            // x坐标 width => width * 3 / 4
            var ctrlPosX = width * (1 - 1 / 4 * per);
            // 控制点1y坐标 0 => width / 16
            var ctrlPos1Y = width * 1 / 16 * per;
            // 控制点2y坐标 0 => width * 3 / 16
            var ctrlPos2Y = width * 3 / 16 * per;
            ctrlPos1 = new cc.Vec2(ctrlPosX, ctrlPos1Y);
            ctrlPos2 = new cc.Vec2(ctrlPosX, ctrlPos2Y);
        }
        else {
            per = per - 1;
            // 终点的x坐标变换 0 => width，速度先快后慢，使用OutCubic缓动函数
            var endPosX = -width * (1 - Math.pow(1 - per, 3));
            // 终点的y坐标变换 width / 4 => 0, 速度先慢后快，使用InQuart缓动函数
            var endPosY = width / 4 * (1 - Math.pow(per, 4));
            endPos = new cc.Vec2(endPosX, endPosY);
            // 控制点1x坐标 width * 3 / 4 => 0
            var ctrlPos1X = width * 3 / 4 * (1 - per);
            // 控制点2x坐标 width * 3 / 4 => 0
            var ctrlPos2X = width * 3 / 4 * Math.pow(1 - per, 3);
            // 控制点1y坐标 width / 16 => 0
            var ctrlPos1Y = width * 1 / 16 * (1 - per);
            // 控制点2y坐标 width * 3 / 16 => 0
            var ctrlPos2Y = width * 3 / 16 * (1 - Math.pow(per, 4));
            ctrlPos1 = new cc.Vec2(ctrlPos1X, ctrlPos1Y);
            ctrlPos2 = new cc.Vec2(ctrlPos2X, ctrlPos2Y);
        }
        return {
            startPos: startPos,
            endPos: endPos,
            ctrlPos1: ctrlPos1,
            ctrlPos2: ctrlPos2
        };
    };
    // 修正宽度
    BezierAssembler.prototype._fixWidth = function (lastBezierPos, nextBezierPos, width, realWidth, isTail) {
        var deltaVector = nextBezierPos.sub(lastBezierPos);
        // 两个顶点的间距
        var gapWidth = deltaVector.mag();
        // 当前的总长
        var curWidth = realWidth + gapWidth;
        if (isTail) {
            // 如果是最后一个顶点则将总长度修正至书页的真实宽度
            gapWidth = width - realWidth;
            var direction = deltaVector.normalize();
            nextBezierPos = lastBezierPos.add(direction.mul(gapWidth));
        }
        else if (curWidth >= width) {
            // 如果当前总长超过了书页的真实宽度，就衰减超过部分的1.1倍
            var delta = curWidth - width;
            gapWidth = gapWidth - delta * 1.1;
            gapWidth = Math.max(0, gapWidth);
            var direction = deltaVector.normalize();
            nextBezierPos = lastBezierPos.add(direction.mul(gapWidth));
        }
        return {
            gapWidth: gapWidth,
            nextBezierPos: nextBezierPos,
        };
    };
    // 贝塞尔曲线公式
    BezierAssembler.prototype._getBezierPos = function (t, startPos, endPos, ctrlPos1, ctrlPos2) {
        startPos = startPos.mul(Math.pow(1 - t, 3));
        ctrlPos1 = ctrlPos1.mul(3 * t * Math.pow(1 - t, 2));
        ctrlPos2 = ctrlPos2.mul(3 * (1 - t) * Math.pow(t, 2));
        endPos = endPos.mul(Math.pow(t, 3));
        return startPos.add(ctrlPos1.add(ctrlPos2.add(endPos)));
    };
    return BezierAssembler;
}(page_effect_assembler_base_1.default));
exports.default = BezierAssembler;

cc._RF.pop();