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; } }