185 lines
5.3 KiB
TypeScript
185 lines
5.3 KiB
TypeScript
import { CoroutineV2 } from "../../CatanEngine/CoroutineV2/CoroutineV2";
|
|
|
|
const { ccclass, property, requireComponent, menu, executeInEditMode } = cc._decorator;
|
|
|
|
// /** Clipname */
|
|
// export enum Clipname {
|
|
// None,
|
|
// }
|
|
|
|
@ccclass("SPState")
|
|
export class SPState {
|
|
@property()
|
|
public name: string = "";
|
|
public clip: cc.AnimationClip = null;
|
|
@property({ displayName: "Spine動畫名稱", tooltip: "Spine動畫名稱" })
|
|
public clipname: string = "";
|
|
// @property({ displayName: "clipname1", type: cc.Enum(Clipname) })
|
|
// public clipname1: Clipname = Clipname.None;
|
|
@property()
|
|
public isloop: boolean = false;
|
|
@property()
|
|
public transitionTo: string = "";
|
|
}
|
|
@ccclass
|
|
// @executeInEditMode
|
|
@menu("Plug-in/Animation/SPAnimator")
|
|
@requireComponent(sp.Skeleton)
|
|
export class SPAnimator extends cc.Component {
|
|
|
|
@property({ displayName: "Default State" })
|
|
public defaultState: string = "";
|
|
|
|
@property({ type: SPState })
|
|
public states: SPState[] = [];
|
|
public nowPlayName: string = "";
|
|
private _isInit: boolean = false;
|
|
_animation: sp.Skeleton = null;
|
|
|
|
/** 動畫速度 */
|
|
private _speed: number = 1;
|
|
get animation(): sp.Skeleton {
|
|
if (this._animation == null) {
|
|
this._animation = this.node.getComponent(sp.Skeleton);
|
|
}
|
|
return this._animation;
|
|
}
|
|
|
|
protected onLoad(): void {
|
|
if (this._isInit) {
|
|
return;
|
|
}
|
|
if (!this.node.activeInHierarchy) {
|
|
cc.error(`node: ${this.node.name}, activeInHierarchy: ${this.node.activeInHierarchy}, 動畫沒有打開無法初始化`);
|
|
return;
|
|
}
|
|
let animationClip: cc.AnimationClip[] = this.animation["skeletonData"]["_skeletonCache"].animations;
|
|
// if (CC_EDITOR) {
|
|
// for (let i: number = 0; i < animationClip.length; i++) {
|
|
// const clip: cc.AnimationClip = animationClip[i];
|
|
// Clipname[clip.name] = i;
|
|
// Clipname[i.toString()] = clip.name;
|
|
// cc.log(`[${i}] ${clip.name}`);
|
|
// }
|
|
// return;
|
|
// }
|
|
for (let s of this.states) {
|
|
let state: SPState = null;
|
|
for (let i: number = 0; i < animationClip.length; i++) {
|
|
const clip: cc.AnimationClip = animationClip[i];
|
|
if (s.clipname === clip.name && s.clipname != null) {
|
|
s.clip = clip;
|
|
state = s;
|
|
break;
|
|
}
|
|
}
|
|
if (CC_DEV) {
|
|
if (state === null) {
|
|
console.error(`node: ${this.node.name}, anim: ${s.clipname}, 動畫沒有掛在Animation上面`);
|
|
}
|
|
}
|
|
}
|
|
this._isInit = true;
|
|
}
|
|
|
|
protected onEnable(): void {
|
|
this.stopState();
|
|
if (this.defaultState !== "") {
|
|
this.playState(this.defaultState);
|
|
}
|
|
}
|
|
protected onDisable(): void {
|
|
this.stopState();
|
|
}
|
|
|
|
/**
|
|
* runStateAndWait(動作機只會接一次動畫)
|
|
* @param name 動畫State的名稱
|
|
* @param callback callback 沒有transitionTo才會觸發
|
|
*/
|
|
public *runStateAndWait(name: string, callback: Function = null): any {
|
|
if (!this._isInit) {
|
|
this.onLoad();
|
|
}
|
|
if (name === "") {
|
|
return;
|
|
}
|
|
this.animation.setToSetupPose();
|
|
let lastPlayName: string = "";
|
|
for (let s of this.states) {
|
|
if (s.name === this.nowPlayName && s.clipname != null) {
|
|
lastPlayName = s.clipname;
|
|
break;
|
|
}
|
|
}
|
|
this.nowPlayName = name;
|
|
let state: SPState = null;
|
|
for (let s of this.states) {
|
|
if (s.name === name && s.clipname != null) {
|
|
state = s;
|
|
break;
|
|
}
|
|
}
|
|
if (state == null) {
|
|
return;
|
|
}
|
|
// let animationState: cc.AnimationState = this.animation.play(state.clipname);
|
|
if (lastPlayName) {
|
|
this.animation.setMix(lastPlayName, state.clipname, 0.5);
|
|
}
|
|
this.animation.setAnimation(0, state.clipname, state.isloop);
|
|
// let animationState: sp.spine.TrackEntry = this.animation.setAnimation(0, state.clipname, state.isloop);
|
|
// animationState.speed = this.animation.currentClip.speed * this._speed;
|
|
// this.animation.sample(animationState.name);
|
|
if (state.clip.duration) {
|
|
yield CoroutineV2.WaitTime(state.clip.duration);
|
|
}
|
|
if (callback && !state.transitionTo) {
|
|
callback();
|
|
}
|
|
yield* this.runStateAndWait(state.transitionTo, callback);
|
|
}
|
|
|
|
/** playState(動作機只會接一次動畫) */
|
|
public playState(name: string, callback: Function = null): void {
|
|
if (!this.node.activeInHierarchy) {
|
|
cc.warn(`SPAnimator error name: ${this.node.name}, activeInHierarchy: ${this.node.activeInHierarchy}`);
|
|
}
|
|
CoroutineV2.Single(this.runStateAndWait(name, callback)).Start(this);
|
|
}
|
|
|
|
// /** playState(隨機) */
|
|
// public playRandomState(callback: Function = null): void {
|
|
// let random: number = RandomEx.GetInt(0, this.states.length);
|
|
// let state: SPState = this.states[random];
|
|
// this.playState(state.name, callback);
|
|
// }
|
|
|
|
public stopState(): void {
|
|
CoroutineV2.StopCoroutinesBy(this);
|
|
this.nowPlayName = "";
|
|
this.animation.clearTracks();
|
|
}
|
|
|
|
// /**
|
|
// * 設定動畫速率(原有動畫的Speed在乘上倍率)
|
|
// * @param speed 速率
|
|
// */
|
|
// public SetSpeed(speed: number): void {
|
|
// this._speed = speed;
|
|
// }
|
|
|
|
public getAnimTime(name: string, isGetNext: boolean = false): number {
|
|
for (let s of this.states) {
|
|
if (s.name === name && s.clipname != null) {
|
|
let time: number = s.clip.duration / this._speed;
|
|
if (isGetNext && s.transitionTo !== "") {
|
|
time += this.getAnimTime(s.transitionTo, true);
|
|
}
|
|
return time;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|