HuaweiDemo/assets/script/framework/effectManager.ts

310 lines
11 KiB
TypeScript
Raw Permalink Normal View History

2023-11-07 01:17:57 +00:00
import { _decorator, Node, Prefab, AnimationComponent, ParticleSystemComponent, Vec3, find, AnimationState, AnimationClip, director } from 'cc';
import { PoolManager } from './poolManager';
import { ResourceUtil } from './resourceUtil';
const { ccclass, property } = _decorator;
@ccclass('EffectManager')
export class EffectManager{
private _ndParent: Node = null!;
public get ndParent() {
if (!this._ndParent) {
let ndEffectParent = find("effectManager") as Node;
if (ndEffectParent) {
this._ndParent = ndEffectParent;
} else {
// console.warn("请在场景里添加effectManager节点");
this._ndParent = new Node("effectManager");
director.getScene()?.addChild(this._ndParent);
}
}
return this._ndParent;
}
static _instance: EffectManager;
static get instance () {
if (this._instance) {
return this._instance;
}
this._instance = new EffectManager();
return this._instance;
}
/**
*
* @param {string} path
* @param {string} aniName
* @param {vec3} worPos
* @param {boolean} isLoop
* @param {boolean} isRecycle
* @param {number} [scale=1]
* @param {Function} [callback=()=>{}]
*/
public playAni (path: string, aniName: string, worPos: Vec3 = new Vec3(), isLoop: boolean = false, isRecycle: boolean = false, scale: number = 1, callback: Function = ()=>{}) {
let childName: string = path.split("/")[1];
let ndEffect: Node | null = this.ndParent.getChildByName(childName);
let cb = ()=>{
ndEffect?.setScale(scale, scale, scale);
ndEffect?.setWorldPosition(worPos);
let ani: AnimationComponent= ndEffect?.getComponent(AnimationComponent) as AnimationComponent;
ani.play(aniName);
let aniState: AnimationState= ani.getState(aniName) as AnimationState;
if (aniState) {
if (isLoop) {
aniState.wrapMode = AnimationClip.WrapMode.Loop;
} else {
aniState.wrapMode = AnimationClip.WrapMode.Normal;
}
}
ani.once(AnimationComponent.EventType.FINISHED, ()=>{
callback && callback();
if (isRecycle && ndEffect) {
PoolManager.instance.putNode(ndEffect);
}
})
}
if (!ndEffect) {
ResourceUtil.loadEffectRes(path).then((prefab: unknown)=>{
ndEffect = PoolManager.instance.getNode(prefab as Prefab, this.ndParent) as Node;
ndEffect.setScale(scale, scale, scale);
ndEffect.setWorldPosition(worPos);
cb();
})
} else {
cb();
}
}
/**
*
* @param {string} name
* @param {Node}} ndParent
*/
public removeEffect (name: string, ndParent: Node = this.ndParent) {
let ndEffect: Node | null = ndParent.getChildByName(name);
if (ndEffect) {
let arrAni: AnimationComponent[] = ndEffect.getComponentsInChildren(AnimationComponent);
arrAni.forEach((element: AnimationComponent)=>{
element.stop();
})
let arrParticle: [] = ndEffect?.getComponentsInChildren(ParticleSystemComponent) as any;
arrParticle.forEach((element:ParticleSystemComponent)=>{
element?.clear();
element?.stop();
})
PoolManager.instance.putNode(ndEffect);
}
}
/**
*
* @param {string} path
* @param {vec3}worPos
* @param {number} [recycleTime=0] 0使duration
* @param {number} [scale=1]
* @param {vec3} eulerAngles
* @param {Function} [callback=()=>{}]
*/
public playParticle (path: string, worPos: Vec3, recycleTime: number = 0, scale: number = 1, eulerAngles?: Vec3 | null, callback?: Function) {
ResourceUtil.loadEffectRes(path).then((prefab: any)=>{
let ndEffect: Node = PoolManager.instance.getNode(prefab as Prefab, this.ndParent) as Node;
ndEffect.setScale(scale, scale, scale);
ndEffect.setWorldPosition(worPos);
if (eulerAngles) {
ndEffect.eulerAngles = eulerAngles;
}
let maxDuration: number = 0;
let arrParticle: ParticleSystemComponent[]= ndEffect.getComponentsInChildren(ParticleSystemComponent);
arrParticle.forEach((item: ParticleSystemComponent)=>{
item.simulationSpeed = 1;
item?.clear();
item?.stop();
item?.play()
let duration: number= item.duration;
maxDuration = duration > maxDuration ? duration : maxDuration;
})
let seconds: number = recycleTime && recycleTime > 0 ? recycleTime : maxDuration;
setTimeout(()=>{
if (ndEffect.parent) {
callback && callback();
PoolManager.instance.putNode(ndEffect);
}
}, seconds * 1000)
})
}
/**
*
*
* @param {Node} targetNode
* @param {string} effectPath
* @param {boolean} [isPlayAni=true]
* @param {boolean} [isPlayParticle=true]
* @param {number} [recycleTime=0] 0使duration
* @param {number} [scale=1]
* @param {Vec3} [pos=new Vec3()]
* @param {boolean} [isRecycle=true]
* @param {Function} [callback=()=>{}]
* @returns
* @memberof EffectManager
*/
public playEffect (targetNode: Node, effectPath: string, isPlayAni: boolean = true, isPlayParticle: boolean = true, recycleTime: number = 0, scale: number = 1, pos?: Vec3 | null, eulerAngles?: Vec3 | null, isRecycle: boolean = true, callback?: Function | null) {
if (!targetNode || !targetNode.parent) {//父节点被回收的时候不播放
return;
}
ResourceUtil.loadEffectRes(effectPath).then((prefab: any)=>{
let ndEffect: Node = PoolManager.instance.getNode(prefab as Prefab, targetNode) as Node;
ndEffect.setScale(scale, scale, scale);
if (pos) {
ndEffect.setPosition(pos);
}
if (eulerAngles) {
ndEffect.eulerAngles = eulerAngles;
}
let maxDuration: number = 0;
if (isPlayAni) {
let arrAni: AnimationComponent[] = ndEffect.getComponentsInChildren(AnimationComponent);
if (arrAni.length) {
arrAni.forEach((element: AnimationComponent, idx: number)=>{
element?.play();
let aniName = element?.defaultClip?.name;
if (aniName) {
let aniState = element.getState(aniName);
if (aniState) {
aniState.time = 0;
aniState.sample();
let duration = aniState.duration;
maxDuration = duration > maxDuration ? duration : maxDuration;
aniState.speed = 1;
}
}
})
}
}
if (isPlayParticle) {
let arrParticle: ParticleSystemComponent[]= ndEffect.getComponentsInChildren(ParticleSystemComponent);
if (arrParticle.length) {
arrParticle.forEach((element:ParticleSystemComponent)=>{
element.simulationSpeed = 1;
element?.clear();
element?.stop();
element?.play()
let duration: number= element.duration;
maxDuration = duration > maxDuration ? duration : maxDuration;
})
}
}
let seconds: number = recycleTime && recycleTime > 0 ? recycleTime : maxDuration;
setTimeout(()=>{
if (ndEffect.parent) {
callback && callback();
if (isRecycle) {
PoolManager.instance.putNode(ndEffect);
} else {
ndEffect.destroy();
}
}
}, seconds * 1000)
})
}
/**
* /
*
* @param {Node} ndParent
* @memberof EffectManager
*/
public playTrail (ndParent: Node, recycleTime:number = 0, callback?:Function, speed: number = 1) {
let maxDuration: number = 0;
if (!ndParent.active) {
ndParent.active = true;
}
let arrParticle: ParticleSystemComponent[]= ndParent.getComponentsInChildren(ParticleSystemComponent);
arrParticle.forEach((element:ParticleSystemComponent)=>{
element.simulationSpeed = speed;
element?.clear();
element?.stop();
element?.play();
let duration: number= element.duration;
maxDuration = duration > maxDuration ? duration : maxDuration;
})
if (callback) {
let seconds: number = recycleTime && recycleTime > 0 ? recycleTime : maxDuration;
setTimeout(()=>{
callback();
}, seconds * 1000)
}
}
/**
*
* @param {string} path
* @param {vec3}worPos
* @param {Function} [callback=()=>{}]
*/
public playDisappearEff (path: string, worPos: Vec3, cb: Function) {
ResourceUtil.loadEffectRes(path).then((prefab: any)=>{
let ndEffect: Node = PoolManager.instance.getNode(prefab as Prefab, this.ndParent) as Node;
ndEffect.setWorldPosition(worPos);
let maxDuration: number = 0;
let arrParticle: ParticleSystemComponent[]= ndEffect.getComponentsInChildren(ParticleSystemComponent);
arrParticle.forEach((item: ParticleSystemComponent)=>{
item.simulationSpeed = 1;
item?.clear();
item?.stop();
item?.play()
let duration: number= item.duration;
maxDuration = duration > maxDuration ? duration : maxDuration;
})
setTimeout(()=>{
if (ndEffect && ndEffect.parent) {
PoolManager.instance.putNode(ndEffect);
}
}, maxDuration * 1000)
cb && cb(()=>{
if (ndEffect && ndEffect.parent) {
PoolManager.instance.putNode(ndEffect);
}
});
})
}
}