RUQCoreSpine.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. #include <cstring>
  2. #include "RUQCoreSpine.h"
  3. #include <spine/extension.h>
  4. #include "RUUtils.h"
  5. #include "AudioEngine.h"
  6. #include "RedWise.hpp"
  7. using namespace spine;
  8. NS_RU_BEGIN
  9. std::unordered_map<std::string, Atlas*> _mAtlasMap;
  10. std::unordered_map<std::string, SkeletonData*> _mSkeletonDataMap;
  11. Cocos2dTextureLoader textureLoader;
  12. Atlas* QCoreSpine::getAtlasByName(std::string name){
  13. auto iter = _mAtlasMap.find(name);
  14. if(iter!=_mAtlasMap.end()){
  15. return iter->second;
  16. }else{
  17. Atlas* atlas = new (__FILE__, __LINE__) Atlas(name.c_str(), &textureLoader, true);
  18. CCASSERT(atlas, "Error reading atlas file.");
  19. _mAtlasMap.insert(std::pair<std::string, Atlas*>(name,atlas));
  20. return atlas;
  21. }
  22. return nullptr;
  23. }
  24. SkeletonData* QCoreSpine::getSkeletonDataByName(std::string name,Atlas* atlas){
  25. auto iter = _mSkeletonDataMap.find(name);
  26. if(iter!=_mSkeletonDataMap.end()){
  27. return iter->second;
  28. }else{
  29. auto attachmentLoader = new (__FILE__, __LINE__) Cocos2dAtlasAttachmentLoader(atlas);
  30. // auto attachmentLoader = SUPER(Cocos2dAttachmentLoader_create(atlas));
  31. SkeletonBinary binary(attachmentLoader);
  32. binary.setScale(1.0f);
  33. SkeletonData* skeletonData = binary.readSkeletonDataFile(name.c_str());
  34. CCASSERT(skeletonData, !binary.getError().isEmpty() ? binary.getError().buffer() : "Error reading skeleton data.");
  35. _mSkeletonDataMap.insert(std::pair<std::string, SkeletonData*>(name,skeletonData));
  36. return skeletonData;
  37. }
  38. return nullptr;
  39. }
  40. QCoreSpine* QCoreSpine::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) {
  41. QCoreSpine* node = new QCoreSpine();
  42. node->initWithData(skeletonData, ownsSkeletonData);
  43. // FIXME how to set data name?
  44. node->autorelease();
  45. node->setContent();
  46. return node;
  47. }
  48. QCoreSpine* QCoreSpine::createWithJsonFile (const std::string& skeletonJsonFile, Atlas* atlas, float scale) {
  49. QCoreSpine* node = new QCoreSpine();
  50. node->initWithJsonFile(skeletonJsonFile, atlas, scale);
  51. node->setDataName(skeletonJsonFile);
  52. node->autorelease();
  53. node->setContent();
  54. return node;
  55. }
  56. QCoreSpine* QCoreSpine::createWithJsonFile (const std::string& skeletonJsonFile, const std::string& atlasFile, float scale) {
  57. QCoreSpine* node = new QCoreSpine();
  58. node->initWithJsonFile(skeletonJsonFile, atlasFile.c_str(), scale);
  59. node->setDataName(skeletonJsonFile);
  60. node->autorelease();
  61. node->setContent();
  62. return node;
  63. }
  64. QCoreSpine* QCoreSpine::createWithBinaryFile (const std::string& skeletonBinaryFile, Atlas* atlas, float scale) {
  65. QCoreSpine* node = new QCoreSpine();
  66. node->initWithBinaryFile(skeletonBinaryFile, atlas, scale);
  67. node->setDataName(skeletonBinaryFile);
  68. node->autorelease();
  69. node->setContent();
  70. return node;
  71. }
  72. QCoreSpine* QCoreSpine::createWithBinaryFile (const std::string& skeletonBinaryFile, const std::string& atlasFile, float scale) {
  73. QCoreSpine* node = new QCoreSpine();
  74. node->initWithBinaryFile(skeletonBinaryFile, atlasFile.c_str(), scale);
  75. node->setDataName(skeletonBinaryFile);
  76. node->autorelease();
  77. node->setContent();
  78. return node;
  79. }
  80. QCoreSpine* QCoreSpine::createWithBinaryFileAndCache (const std::string& skeletonBinaryFile, const std::string& atlasFile, float scale) {
  81. Atlas* atlas = getAtlasByName(atlasFile); // Atlas_createFromFile(atlasFile.c_str(), 0);
  82. auto skeletonData = getSkeletonDataByName(skeletonBinaryFile, atlas);
  83. reScaleSkeletonData(skeletonData,scale);
  84. QCoreSpine* node = createWithData(skeletonData,false);
  85. node->setScale(scale);
  86. node->setContent();
  87. return node;
  88. }
  89. QCoreSpine::QCoreSpine ()
  90. {
  91. _cbOnExit = nullptr;
  92. _dataName = "";
  93. }
  94. QCoreSpine::~QCoreSpine()
  95. {
  96. }
  97. void QCoreSpine::onExit() {
  98. if (_cbOnExit != nullptr) {
  99. _cbOnExit(_dataName, this);
  100. }
  101. Node::onExit();
  102. }
  103. SkeletonData* QCoreSpine::getSkeletonData(){
  104. SkeletonData*skData =getSkeleton()->getData();
  105. return skData;
  106. }
  107. float QCoreSpine::getAnimTime(std::string name){
  108. float durTime = 0.0f;
  109. spine::Animation* tAnimation= findAnimation(name);
  110. if (tAnimation) {
  111. durTime = tAnimation->getDuration();
  112. }
  113. return durTime;
  114. }
  115. void QCoreSpine::playBackAnim(const char* name,const std::function<void()> &func, bool isDeleteSelf,bool isLoop){
  116. _mCallFunc = func;
  117. auto track = setAnimation(0, name, isLoop);
  118. if(track){
  119. setTrackCompleteListener(track, [=] (TrackEntry* entry) {
  120. if(_mCallFunc){
  121. this->_mCallFunc();
  122. }
  123. if(isDeleteSelf){
  124. this->runAction(RemoveSelf::create());
  125. }
  126. });
  127. float dur = getAnimTime(name);
  128. track->setTrackTime(dur);
  129. setTimeScale(-1);
  130. }
  131. }
  132. void QCoreSpine::playAnim(string name,const std::function<void()> &func, bool isDeleteSelf ,bool isLoop,float delay,bool delFunc){
  133. if(delay>0){
  134. auto node = Node::create();
  135. this->addChild(node);
  136. node->runAction(Sequence::create(DelayTime::create(delay),CallFunc::create([=](){
  137. resetVar();
  138. _mCallFunc = func;
  139. auto track = setAnimation(0, name, isLoop);
  140. this->setTrackCompleteListener(track, [=](TrackEntry* entry){
  141. if(_mCallFunc){
  142. this->_mCallFunc();
  143. if(delFunc){
  144. _mCallFunc = nullptr;
  145. }
  146. }
  147. if(isDeleteSelf){
  148. this->runAction(RemoveSelf::create());
  149. }
  150. });
  151. }),RemoveSelf::create(),NULL));
  152. }else{
  153. resetVar();
  154. _mCallFunc = func;
  155. auto track = setAnimation(0, name, isLoop);
  156. this->setTrackCompleteListener(track, [=](TrackEntry* entry){
  157. if(_mCallFunc){
  158. if(delFunc){
  159. this->_mCallFunc = nullptr;
  160. }
  161. func();//回调可能会把自己删掉的,所以最后调
  162. }
  163. if(isDeleteSelf){
  164. this->runAction(RemoveSelf::create());
  165. }
  166. });
  167. }
  168. }
  169. void QCoreSpine::playAnimN(string name,const std::function<void(Node*)> &funcN, bool isDeleteSelf ,bool isLoop ){
  170. resetVar();
  171. _mCallFuncN = funcN;
  172. auto track = setAnimation(0, name, isLoop);
  173. this->setTrackCompleteListener(track, [=](TrackEntry* entry){
  174. if(_mCallFuncN){
  175. this->_mCallFuncN(this);
  176. }
  177. if(isDeleteSelf){
  178. this->runAction(RemoveSelf::create());
  179. }
  180. });
  181. }
  182. void QCoreSpine::playAnimInRange(const char* name){
  183. resetVar();
  184. int count = getSkeleton()->getData()->getAnimations().size();
  185. spine::Vector<spine::Animation*> sparr = getSkeleton()->getData()->getAnimations();
  186. for(int i = 0;i<count;i++){
  187. spine::Animation* sp = sparr[i];
  188. int len = strlen(name);
  189. if(len<0)continue;
  190. int p = std::strncmp(sp->getName().buffer(),name,len);
  191. if(p == 0){
  192. _randomNames.push_back(sp->getName().buffer());
  193. }
  194. }
  195. playRandomAnim();
  196. }
  197. void QCoreSpine::playAnimInRangeWithArray(std::vector<std::string> randomNames ,std::vector<int> randomRates){
  198. resetVar();
  199. _randomNames = randomNames;
  200. _randomRates = randomRates;
  201. playRandomAnim();
  202. }
  203. void QCoreSpine::playRandomAnim(){
  204. bool v = false;
  205. if (_randomNames.size() > 0) {
  206. if (_randomRates.size() > 0) {
  207. CCASSERT(_randomNames.size() == _randomRates.size() , "有问题");
  208. string animName = randomObjByRatio(_randomNames,_randomRates);
  209. v = true;
  210. setAnimation(0, animName, false);
  211. }
  212. }
  213. if(v){
  214. _mComplete = [=](){
  215. playRandomAnim();
  216. };
  217. }
  218. }
  219. void QCoreSpine::setContent(){
  220. this->setEventListener([=](spine::TrackEntry* entry, spine::Event* event){
  221. EventData eData = event->getData();
  222. if (eData.getAudioPath().buffer()) {
  223. ///spine的声音事件,强制截取后缀改为redwise事件
  224. // if (RedWise::getInstance()->isSFXEnable()) {
  225. // const std::string& mp3FileName = eData.getName().buffer();
  226. // const std::string& eventName = mp3FileName.substr(0, mp3FileName.rfind("."));
  227. // RedWise::getInstance()->postEvent(eventName);
  228. // }
  229. } else {
  230. ///其他spine事件
  231. const char* evenName = eData.getName().buffer();
  232. if (_mCallEvent) {
  233. _mCallEvent(entry,evenName);
  234. }
  235. }
  236. });
  237. setCompleteListener([=] (TrackEntry* entry) {
  238. if(_mComplete){
  239. _mComplete();
  240. }
  241. });
  242. }
  243. void QCoreSpine::setEventCallBack(const std::function<void(TrackEntry*,const char*)> &func){
  244. _mCallEvent = func;
  245. }
  246. void QCoreSpine::reScaleSkeletonData(SkeletonData* skeletonData,float scale){
  247. return;
  248. int i;
  249. for (i = 0; i < skeletonData->getBones().size(); ++i) {
  250. BoneData* data = skeletonData->getBones()[i];
  251. data->setScaleX(data->getScaleX()* scale);// *= scale;
  252. data->setScaleY(data->getScaleY()* scale);
  253. data->setLength(data->getLength()* scale);
  254. }
  255. // for (i = 0; i < skeletonData->getTransformConstraints().size(); ++i) {
  256. // TransformConstraintData* data = skeletonData->getTransformConstraints()[i];
  257. // data->offsetX *= scale;
  258. // data->offsetY *= scale;
  259. // }
  260. for (i = 0; i < skeletonData->getPathConstraints().size(); ++i) {
  261. PathConstraintData* data = skeletonData->getPathConstraints()[i];
  262. if (data->getPositionMode() == PositionMode_Fixed) data->setPosition(data->getPosition()*scale);// *= scale;
  263. if (data->getSpacingMode() == SpacingMode_Length || data->getSpacingMode() == SpacingMode_Fixed) data->setSpacing(data->getSpacing() * scale);// *= scale;
  264. }
  265. }
  266. void QCoreSpine::changeToOtherParent(Node* newParent)
  267. {
  268. this->retain();
  269. std::function<void(const string&, QCoreSpine*)> cbBack = _cbOnExit;
  270. _cbOnExit = nullptr;
  271. this->removeFromParentAndCleanup(false);
  272. _cbOnExit = cbBack;
  273. newParent->addChild(this);
  274. this->release();
  275. }
  276. std::function<void(const string&, QCoreSpine*)> QCoreSpine::setCbOnExit(std::function<void(const string&, QCoreSpine*)> cb) {
  277. auto t = _cbOnExit;
  278. _cbOnExit = cb;
  279. return t;
  280. }
  281. void QCoreSpine::setDataName(const string& name) {
  282. int pos = name.find(".");
  283. if (pos != -1) {
  284. _dataName = name.substr(0, pos);
  285. } else {
  286. _dataName = name;
  287. }
  288. }
  289. void QCoreSpine::changeSkeleton(const std::string& skeletonJsonFile, const std::string& atlasFile, float scale)
  290. {
  291. if (_ownsAnimationStateData)
  292. {
  293. if (_state)
  294. {
  295. delete _state->getData();
  296. delete _state;
  297. }
  298. }
  299. if (_ownsSkeletonData && _skeleton)
  300. {
  301. delete _skeleton->getData();
  302. }
  303. if (_ownsSkeleton && _skeleton)
  304. {
  305. delete _skeleton;
  306. }
  307. if (_ownsAtlas && _atlas)
  308. {
  309. delete _atlas;
  310. }
  311. if (_attachmentLoader) delete _attachmentLoader;
  312. if (_clipper)
  313. {
  314. delete _clipper;
  315. }
  316. this->initWithBinaryFile(skeletonJsonFile, atlasFile,scale);
  317. this->setDataName(skeletonJsonFile);
  318. }
  319. void QCoreSpine::resetVar(){
  320. clearTracks();
  321. _mCallFunc = nullptr;
  322. _mCallFuncN = nullptr;
  323. _mCallEvent = nullptr;
  324. _mComplete = nullptr;
  325. _randomNames.clear();
  326. _randomRates.clear();
  327. }
  328. string QCoreSpine::getRunningSequenceName(){
  329. if(_state){
  330. auto trackEntry = this->getCurrent();
  331. if(trackEntry){
  332. auto anim = trackEntry->getAnimation();
  333. if(anim){
  334. return string(anim->getName().buffer());
  335. }
  336. }
  337. }
  338. return "";
  339. }
  340. #define PROPERTY_SPINE_JSON_NAME "jsonName"
  341. #define PROPERTY_SPINE_ATLAS_NAME "atlasName"
  342. #define PROPERTY_SPINE_ANIM_NAME "curAnimName"
  343. #define PROPERTY_SPINE_SCALE "spineScale"
  344. #define PROPERTY_SPINE_LOOP "loop"
  345. void QCoreSpineLoader::onHandlePropTypeString(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, const char * pString, redream::REDReader * ccbReader)
  346. {
  347. if(strcmp(pPropertyName, PROPERTY_SPINE_JSON_NAME) == 0) {
  348. _skelName = pString;
  349. checkRefreshSpine(pNode);
  350. } else if(strcmp(pPropertyName, PROPERTY_SPINE_ATLAS_NAME) == 0) {
  351. _atlasName = pString;
  352. checkRefreshSpine(pNode);
  353. } else if(strcmp(pPropertyName, PROPERTY_SPINE_ANIM_NAME) == 0) {
  354. _curAnimName = pString;
  355. checkRefreshSpine(pNode);
  356. } else {
  357. QCoreSpineLoader::onHandlePropTypeString(pNode, pParent, pPropertyName, pString, ccbReader);
  358. }
  359. }
  360. void QCoreSpineLoader::onHandlePropTypeFloat(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, float pFloat, redream::REDReader * ccbReader)
  361. {
  362. if(strcmp(pPropertyName, PROPERTY_SPINE_SCALE) == 0) {
  363. _spineScale = pFloat;
  364. checkRefreshSpine(pNode);
  365. }else {
  366. QCoreSpineLoader::onHandlePropTypeFloatScale(pNode, pParent, pPropertyName, pFloat, ccbReader);
  367. }
  368. }
  369. void QCoreSpineLoader::onHandlePropTypeCheck(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, bool pCheck, redream::REDReader * ccbReader)
  370. {
  371. if(strcmp(pPropertyName, PROPERTY_SPINE_LOOP) == 0) {
  372. _loop = pCheck;
  373. checkRefreshSpine(pNode);
  374. }else {
  375. QCoreSpineLoader::onHandlePropTypeCheck(pNode, pParent, pPropertyName, pCheck, ccbReader);
  376. }
  377. }
  378. void QCoreSpineLoader::checkRefreshSpine(cocos2d::Node * pNode)
  379. {
  380. if (_skelName.length() > 0 && _atlasName.length() > 0 && _spineScale > 0.0f)
  381. {
  382. QCoreSpine* spine = (QCoreSpine*)pNode;
  383. if (spine)
  384. {
  385. spine->changeSkeleton(_skelName,_atlasName,_spineScale);
  386. if (_curAnimName.length() > 0)
  387. {
  388. spine->setAnimation(0, _curAnimName, _loop);
  389. }
  390. }
  391. }
  392. }
  393. float QCoreSpine::getAnimDuration(std::string name){
  394. float durTime = 0.0f;
  395. spine::Animation* tAnimation= findAnimation(name);
  396. if (tAnimation) {
  397. durTime = tAnimation->getDuration();
  398. }
  399. return durTime;
  400. }
  401. NS_RU_END