/****************************************************************** * Copyright(C) 2019 - 2020 Nx Studio * * Spine强化 * * 2023.11.01 ******************************************************************/ cc.Class( { extends: cc.Component, properties: { spNode: { default: null, type: sp.Skeleton }, spAction: { default: "", displayName: "动作名" }, spRK: { default: "", displayName: "资源键值" }, spLoop: { default: true, displayName: "循环" }, isAntialias: { default: true, displayName: "抗锯齿" }, }, // 编辑器特性 editor: { // 允许当前组件在编辑器模式下运行 executeInEditMode: false, // 当本组件添加到节点上后,禁止同类型(含子类)的组件再添加到同一个节点,防止逻辑发生冲突 disallowMultiple: true, // menu 用来将当前组件添加到组件菜单中,方便用户查找 menu: "Nx/本地化|骨骼动画", }, // 加载 onLoad: function() { // SP事件绑定 this.spEvent(); // 语言改变 this.onLanguageChanged(); }, // 销毁 onDestroy: function() { // 资源释放 if( this.spSkeleton && window.nx ) { nx.assets.uncacheAsset( this.spSkeleton ); this.spSkeleton = null; } }, // 播放 play: function( _rkey, _action, _cb, _loop ) { // 直接播放 if( this.key == _rkey && this.spNode.skeletonData ) { this.action( _action, _loop, _cb ); return; } // 先停止 this.stop(); // 再加载 let self = this; this.load( _rkey, ( _e, _p ) => { // 失败处理 if( _e ) { nx.dt.fnInvoke( _cb, _e ); return; } // 最后播放 self.action( _action, _loop, _cb ); } ); }, // 停止 stop: function( _release = true ) { this.spCB = null; if( !this.spNode ) { return; } // 动画停止 this.spNode.node.opacity = 0; this.spNode.animation = ""; if( _release && this.spNode.skeletonData ) { this.spNode.skeletonData.reset(); this.spNode.skeletonData = null; nx.assets.uncacheAsset( this.spSkeleton ); this.spSkeleton = null; } }, // 加载SPINE文件 load: function( _rkey, _cb ) { // 完成处理 // 记录当前文件信息 let self = this; let done = function() { self.key = _rkey; self.spRK = _rkey; }; // 統一返回 let notify = function( _p1, _p2 ) { if( !self || !self.spNode ) { nx.warn( `NxSpine:节点已经不存在,回调忽略!` ); return; } nx.dt.fnInvoke( _cb, _p1, _p2 ); }; // 读取 let path = nx.res.fmtPath( _rkey ); nx.res.loadSpine( path, function( _e, _p ) { if( _e ) { notify( _e ); return; } // 抗锯齿 if( nx.dt.arrNEmpty( _p.textures ) ) { let minF = self.isAntialias ? cc.Texture2D.Filter.LINEAR : cc.Texture2D.Filter.NEAREST; let magF = self.isAntialias ? cc.Texture2D.Filter.LINEAR : cc.Texture2D.Filter.NEAREST; for( let i in _p.textures ) { let tex = _p.textures[ i ]; if( tex ) { tex.setFilters( minF, magF ); } } } // 资源绑定 if( self.spNode ) { nx.assets.cacheAsset( _p, path ); self.spNode.skeletonData = _p; nx.assets.uncacheAsset( self.spSkeleton ); self.spSkeleton = _p; self.spNode.node.opacity = 255; } done(); notify(); } ); }, // 直接播放动作 action: function( _action, _loop, _cb, _scale = 1.0 ) { if( !this.spNode ) { nx.warn( "节点丢失,播放动作失败!" + _action ); return; } // 如果已经丢失数据,则重载播放 if( !this.spNode.skeletonData ) { this.play( this.spRK, _action, _loop, _cb ); return; } this.spCB = _cb; this.spAction = _action; this.spLoop = !!_loop; // 播放 this.spNode.loop = !!_loop; this.spNode.animation = _action; this.spNode.node.opacity = 255; this.spNode.timeScale = _scale; }, // 修改播放速度 setTimeScale: function( _scale = 1.0 ) { if( this.spNode ) { this.spNode.timeScale = _scale; } }, // SP事件绑定 spEvent: function() { if( !this.spNode ) { return; } let self = this; let tracker = function( _key, _tracker, _custom = false ) { let name = _tracker.animation ? _tracker.animation.name : ""; self._notify( _key, name, _custom ); }; // 监听 this.spNode.setStartListener( _tk => { tracker( "start", _tk ); } ); this.spNode.setInterruptListener( _tk => { tracker( "interrupt", _tk ); } ); this.spNode.setEndListener( _tk => { tracker( "end", _tk ); } ); this.spNode.setDisposeListener( _tk => { tracker( "disposed", _tk ); } ); this.spNode.setCompleteListener( _tk => { tracker( "complete", _tk ); } ); this.spNode.setEventListener( ( _tk, _event ) => { tracker( _event.data.name, _tk, true ); } ); }, // 当前语种改变 onLanguageChanged: function( _lang ) { if( nx.dt.strEmpty( this.spRK ) || nx.dt.strEmpty( this.spAction ) ) { return; } // 播放 this.play( this.spRK, this.spAction, this.spCB, this.spLoop ); }, // 通告 _notify: function( event, anim, custom ) { // nx.debug( "[SPINE]Event:%s %s", event, anim ); nx.dt.fnInvoke( this.spCB, event, anim, custom ); }, } );