import { IconUrl } from "../../data/const/ResConst"; import { ResBaseAsset } from "./ResBaseAsset"; const { ccclass, menu, disallowMultiple, requireComponent } = cc._decorator; /** * spine组件,自动管理资源的引用计数 */ @ccclass @disallowMultiple @requireComponent(sp.Skeleton) @menu("UI/ResSpine") export default class ResSpine extends ResBaseAsset { private _spSkeleton: sp.Skeleton = null; private _url: string = ''; get spSkeleton() { return this._spSkeleton || (this._spSkeleton = this.node?.getComponent(sp.Skeleton) || this.node?.addComponent(sp.Skeleton)); } public get skeletonData() { return this.spSkeleton.skeletonData; } // private m_CompleteFunc: Function; /** * 通过 url 设置Spine * @param bundle * @param url spine动画 的json文件 路径 * @param extraData * @returns */ setSpineData(bundle: string, url: string, cb?: (asset: sp.SkeletonData) => void, isPremultipliedAlpha: boolean = true, animationName: string = "standby", loop: boolean = true, speed: number = 1) { this._url = url; this.loadAsset(bundle, url, sp.SkeletonData, (asset: sp.SkeletonData) => { if (asset && this.spSkeleton && this.spSkeleton.isValid) { this.spSkeleton.skeletonData = asset; this.spSkeleton.enableBatch = true; this.spSkeleton.premultipliedAlpha = isPremultipliedAlpha; this.spSkeleton.loop = loop; if (this.spSkeleton.findAnimation(animationName) != null) { this.spSkeleton.animation = animationName; } this.spSkeleton.timeScale = speed; cb && cb(asset); } else { console.warn(`加载 Spine 失败: ${bundle} ${url}`); cb && cb(null); } }); } setRoleSpine(url1: IconUrl, url2: string, cb?: (asset: sp.SkeletonData) => void, isPremultipliedAlpha: boolean = true, animationName: string = "standby", loop: boolean = true, speed: number = 1) { this.setSpineData("spine", url1 + url2 + "/" + url2, cb, isPremultipliedAlpha, animationName, loop, speed); } setAnimation(animationName: string) { if (this.spSkeleton) { this.spSkeleton.animation = animationName; } } /** * 播放动作 * @param aniName 动画名称 * @param loop 是否循环 * @param showLast 显示最后一帧 */ playAnimation(aniName: string, loop: boolean, showLast?: boolean) { if (this.spSkeleton) { if (this.spSkeleton.findAnimation(aniName)) { this.spSkeleton.setAnimation(0, aniName, loop); if (showLast) { this.spSkeleton.timeScale = 100000; } } else { // console.error("动画名称不存在", this._url, aniName); } } } /** 是否存在动画 */ isExistAnimation(aniName: string): boolean { return this.spSkeleton.findAnimation(aniName) ? true : false; } setTimeScale(speed: number) { if (this.spSkeleton) { this.spSkeleton.timeScale = speed; } } enableBatch() { this.spSkeleton.enableBatch = true; } clearTracks() { if (this.spSkeleton) { this.spSkeleton.clearTracks() } } clearRes() { this.spSkeleton.skeletonData = null; this.resetRes(); } /** 设置渲染模式 */ setCacheMode(mode: sp.Skeleton.AnimationCacheMode) { this.spSkeleton.setAnimationCacheMode(mode); } /** 后续废弃 * 添加播放完成监听 */ addCompleteListener(callback: Function) { // this.m_CompleteFunc = callback; this.spSkeleton.setCompleteListener((trackEntry, loopCount) => { // this.spSkeleton.setCompleteListener(null); // if (this.m_CompleteFunc) this.m_CompleteFunc(); // this.m_CompleteFunc = null; callback(trackEntry, loopCount); }); } /** * 添加播放完成监听 */ AddSpineCompleteListener(callback: Function) { // this.m_CompleteFunc = callback; this.spSkeleton.setCompleteListener((trackEntry, loopCount) => { let name = trackEntry.animation ? trackEntry.animation.name : ''; callback(name); }); } /** 移除完成监听 */ removeCompleteListener() { this.spSkeleton?.setCompleteListener(null); } /** 添加事件帧监听 */ addEventListener(callback: Function): void { this.spSkeleton.setEventListener((trackIndex, event: any) => { let name = event.data.name; callback(name); }); } /** 移除事件帧监听 */ removeEventListener() { this.spSkeleton.setEventListener(null); } /** 获取插槽节点世界坐标 */ getSlotWorldPos(slotName: string): cc.Vec2 { if (!slotName) return null; let slot: sp.spine.Slot = this.spSkeleton.findSlot(slotName); // 输出骨骼点的信息 if (slot) { // 获取骨骼点的世界变换信息 const worldX = slot.bone.worldX; const worldY = slot.bone.worldY; return this.node.convertToWorldSpaceAR(cc.v2(worldX, worldY)); //转换世界坐标 } else { // console.error("未找到骨骼点: ", slotName); return null; } } /** 获取骨骼节点世界坐标 */ getBoneWorldPos(boneName: string): cc.Vec2 { if (!boneName) return null; let bone: sp.spine.Bone = this.spSkeleton.findBone(boneName); // 输出骨骼点的信息 if (bone) { // 获取骨骼点的世界变换信息 const worldX = bone.worldX; const worldY = bone.worldY; return this.node.convertToWorldSpaceAR(cc.v2(worldX, worldY)); //转换世界坐标 } else { // console.error("未找到骨骼点: ", boneName); return null; } } PauseAction() { if (this.spSkeleton && this.spSkeleton.isValid) this.spSkeleton.paused = true; } ResumeAction() { if (this.spSkeleton && this.spSkeleton.isValid) this.spSkeleton.paused = false; } StopAction() { if (this.spSkeleton && this.spSkeleton.isValid) this.spSkeleton.clearTracks(); } }