2022-07-15 18:23:35 +08:00
|
|
|
import { _decorator, Component } from 'cc';
|
2022-07-13 18:35:31 +08:00
|
|
|
import * as cc from 'cc';
|
|
|
|
import BezierCurve from './BezierCurve';
|
2022-07-16 01:54:43 +08:00
|
|
|
const { ccclass, property, help } = _decorator;
|
2022-07-13 18:35:31 +08:00
|
|
|
|
|
|
|
/** 缓动枚举 */
|
|
|
|
let easingEnum = {};
|
|
|
|
{
|
|
|
|
let tempN = 0;
|
|
|
|
for (let kS in cc.easing) {
|
2022-07-15 18:23:35 +08:00
|
|
|
if (Object.prototype.hasOwnProperty.call(cc.easing, kS)) {
|
|
|
|
easingEnum[kS] = tempN;
|
|
|
|
easingEnum[tempN] = kS;
|
|
|
|
tempN++;
|
|
|
|
}
|
2022-07-13 18:35:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 缓动单元 */
|
|
|
|
@ccclass('BezierCurveAnimationTweenUnit')
|
|
|
|
class BezierCurveAnimationTweenUnit {
|
|
|
|
/* --------------- 属性 --------------- */
|
|
|
|
/** 自定义缓动曲线 */
|
|
|
|
@property({ displayName: '自定义缓动曲线' })
|
|
|
|
customCurveB = false;
|
|
|
|
|
|
|
|
/** 缓动曲线 */
|
|
|
|
@property({
|
|
|
|
displayName: '缓动曲线',
|
|
|
|
type: cc.Enum(easingEnum),
|
|
|
|
visible: function (this: BezierCurveAnimationTweenUnit) {
|
|
|
|
return !this.customCurveB;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
easing = 0;
|
|
|
|
|
|
|
|
/** 缓动控制点 */
|
|
|
|
@property({
|
|
|
|
displayName: '控制点',
|
|
|
|
type: [cc.Vec3],
|
|
|
|
visible: function (this: BezierCurveAnimationTweenUnit) {
|
|
|
|
return this.customCurveB;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
controlPointV3S: cc.Vec3[] = [];
|
|
|
|
|
|
|
|
/** 时间(秒) */
|
|
|
|
@property({ displayName: '时间(秒)' })
|
|
|
|
timeSN = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 贝塞尔曲线通用动画组件 */
|
|
|
|
@ccclass('BezierCurveAnimation')
|
2022-07-16 01:54:43 +08:00
|
|
|
@help('https://www.desmos.com/calculator/cahqdxeshd?lang=zh-CN')
|
2022-07-13 18:35:31 +08:00
|
|
|
export class BezierCurveAnimation extends Component {
|
|
|
|
/* --------------- 属性 --------------- */
|
|
|
|
/** 缓动单元 */
|
|
|
|
@property({ displayName: '缓动单元', type: [BezierCurveAnimationTweenUnit] })
|
2022-07-15 18:23:35 +08:00
|
|
|
tweenUnitAS: BezierCurveAnimationTweenUnit[] = [];
|
2022-07-13 18:35:31 +08:00
|
|
|
|
|
|
|
/** 缓动切换事件 */
|
2022-07-15 18:23:35 +08:00
|
|
|
@property({ displayName: '缓动切换事件', tooltip: '(当前缓动下标_indexN)', type: [cc.EventHandler] })
|
|
|
|
tweenSwitchEventAS: cc.EventHandler[] = [];
|
2022-07-13 18:35:31 +08:00
|
|
|
|
|
|
|
/** 更新事件 */
|
2022-07-14 17:42:02 +08:00
|
|
|
@property({
|
|
|
|
displayName: '更新事件',
|
2022-07-16 20:33:24 +08:00
|
|
|
tooltip: '(当前缓动曲线Y_yN, 当前缓动下标_indexN, 总曲线Y_yN)',
|
2022-07-15 18:23:35 +08:00
|
|
|
type: [cc.EventHandler]
|
2022-07-14 17:42:02 +08:00
|
|
|
})
|
2022-07-15 18:23:35 +08:00
|
|
|
updateEventAS: cc.EventHandler[] = [];
|
2022-07-13 18:35:31 +08:00
|
|
|
|
|
|
|
/** 结束事件 */
|
2022-07-15 18:23:35 +08:00
|
|
|
@property({ displayName: '结束事件', type: [cc.EventHandler] })
|
|
|
|
endEventAS: cc.EventHandler[] = [];
|
2022-07-13 18:35:31 +08:00
|
|
|
/* --------------- private --------------- */
|
2022-07-15 18:23:35 +08:00
|
|
|
/* ------------------------------- 功能 ------------------------------- */
|
|
|
|
/** 触发事件 */
|
|
|
|
emit(eventKey_: keyof BezierCurveAnimation, ...argsAS_: any[]): void {
|
|
|
|
let eventAS = this[eventKey_] as cc.EventHandler[];
|
|
|
|
if (!eventAS) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
eventAS.forEach((v) => {
|
|
|
|
v.emit(argsAS_);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-14 17:42:02 +08:00
|
|
|
/**
|
|
|
|
* 开始缓动
|
|
|
|
* @param startIndexN_ 缓动开始下标
|
|
|
|
* @param endIndexN_ 缓动结束下标
|
|
|
|
* @returns
|
|
|
|
*/
|
2022-07-16 04:02:04 +08:00
|
|
|
startTween(startIndexN_?: number): cc.Tween<any>;
|
|
|
|
startTween(tweenNS_?: number[]): cc.Tween<any>;
|
|
|
|
startTween(args_?: number | number[]): cc.Tween<any> {
|
|
|
|
/** 缓动队列 */
|
2022-07-15 18:23:35 +08:00
|
|
|
let tweenUnitAs = this.tweenUnitAS;
|
2022-07-16 04:02:04 +08:00
|
|
|
|
|
|
|
// 获取缓动队列
|
|
|
|
if (args_ !== undefined) {
|
|
|
|
if (typeof args_ === 'number') {
|
|
|
|
tweenUnitAs = tweenUnitAs.slice(args_, 1);
|
|
|
|
} else {
|
|
|
|
tweenUnitAs = [];
|
|
|
|
args_.forEach((vN) => {
|
|
|
|
tweenUnitAs.push(this.tweenUnitAS[vN]);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
tweenUnitAs = tweenUnitAs.filter((v) => Boolean(v));
|
2022-07-14 17:42:02 +08:00
|
|
|
}
|
2022-07-16 04:02:04 +08:00
|
|
|
if (!tweenUnitAs.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-13 18:35:31 +08:00
|
|
|
/** 总时间(秒) */
|
2022-07-14 17:42:02 +08:00
|
|
|
let totalTimeSN = tweenUnitAs.reduce((preValue, currValue) => preValue + currValue.timeSN, 0);
|
2022-07-13 18:35:31 +08:00
|
|
|
/** 时间占比 */
|
|
|
|
let timeRatioNs: number[] = [];
|
|
|
|
{
|
|
|
|
let currN = 0;
|
2022-07-14 17:42:02 +08:00
|
|
|
tweenUnitAs.forEach((v, kN) => {
|
2022-07-13 18:35:31 +08:00
|
|
|
let ratioN = v.timeSN / totalTimeSN;
|
|
|
|
currN += ratioN;
|
|
|
|
timeRatioNs.push(currN);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
/** 曲线函数 */
|
2022-07-14 17:42:02 +08:00
|
|
|
let curveFS = tweenUnitAs.map((v) => {
|
2022-07-13 18:35:31 +08:00
|
|
|
if (v.customCurveB) {
|
|
|
|
let curve = new BezierCurve(v.controlPointV3S);
|
2022-07-14 17:42:02 +08:00
|
|
|
return (kN: number) => {
|
|
|
|
return curve.point(kN).y;
|
|
|
|
};
|
2022-07-13 18:35:31 +08:00
|
|
|
} else {
|
|
|
|
return cc.easing[easingEnum[v.easing]].bind(cc.easing) as (kN: number) => number;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
/** 上次缓动下标 */
|
|
|
|
let lastTweenIndexN = 0;
|
|
|
|
/** 缓动对象 */
|
|
|
|
let tweenTarget = { valueN: 0 };
|
|
|
|
/** 缓动 */
|
|
|
|
let tween = cc
|
|
|
|
.tween(tweenTarget)
|
|
|
|
.to(
|
|
|
|
totalTimeSN,
|
|
|
|
{
|
|
|
|
valueN: 1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
onUpdate: (target: typeof tweenTarget, ratioN: number) => {
|
|
|
|
/** 当前缓动下标 */
|
|
|
|
let tweenIndexN = timeRatioNs.findIndex((vN) => ratioN <= vN);
|
|
|
|
if (tweenIndexN === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** 上个时间占比 */
|
|
|
|
let lastTimeRatioN = tweenIndexN ? timeRatioNs[tweenIndexN - 1] : 0;
|
|
|
|
/** 当前时间范围 */
|
|
|
|
let timeRangeN = timeRatioNs[tweenIndexN] - lastTimeRatioN;
|
|
|
|
/** 曲线位置 */
|
|
|
|
let posN = (ratioN - lastTimeRatioN) / timeRangeN;
|
2022-07-16 20:33:24 +08:00
|
|
|
/** 当前曲线 Y */
|
|
|
|
let currCurveYN = curveFS[tweenIndexN](posN);
|
|
|
|
/** 总曲线 Y */
|
|
|
|
let totalCurveYN = currCurveYN * timeRangeN + lastTimeRatioN;
|
2022-07-13 18:35:31 +08:00
|
|
|
// 缓动切换事件触发
|
|
|
|
if (lastTweenIndexN !== tweenIndexN) {
|
2022-07-15 18:23:35 +08:00
|
|
|
this.emit('tweenSwitchEventAS', lastTweenIndexN);
|
2022-07-13 18:35:31 +08:00
|
|
|
}
|
|
|
|
// 更新事件触发
|
2022-07-16 20:33:24 +08:00
|
|
|
this.emit('updateEventAS', currCurveYN, tweenIndexN, totalCurveYN);
|
2022-07-13 18:35:31 +08:00
|
|
|
// 更新缓动下标
|
|
|
|
lastTweenIndexN = tweenIndexN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
.call(() => {
|
|
|
|
// 结束事件触发
|
2022-07-15 18:23:35 +08:00
|
|
|
this.emit('endEventAS');
|
2022-07-13 18:35:31 +08:00
|
|
|
})
|
|
|
|
.start();
|
|
|
|
return tween;
|
|
|
|
}
|
|
|
|
}
|