RedBakeNode.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. //
  2. // RedBakeNode.cpp
  3. // cocos2d_libs
  4. //
  5. // Created by Liang zhong on 2022/11/11.
  6. //
  7. #include "RedBakeNode.h"
  8. #include "RedMixAnimationBakeModel.h"
  9. #include "CommandBuff.h"
  10. #include "RedSpineBakeManage.h"
  11. RedBakeNode *RedBakeNode::create(const std::string aFileName){
  12. RedBakeNode *rb = new RedBakeNode(aFileName);
  13. rb->autorelease();
  14. return rb;
  15. }
  16. RedBakeNode *RedBakeNode::create(){
  17. RedBakeNode *rb = new RedBakeNode();
  18. rb->autorelease();
  19. return rb;
  20. }
  21. RedBakeNode::RedBakeNode() {
  22. zeroPos = Vec2(0,0);
  23. _drawSelf = false;
  24. setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, NULL));
  25. }
  26. RedBakeNode::RedBakeNode(const std::string aFileName){
  27. _fileName = aFileName;
  28. zeroPos = Vec2(0,0);
  29. setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, NULL));
  30. _schUpdate = CC_SCHEDULE_SELECTOR(RedBakeNode::update);
  31. this->schedule(_schUpdate, 0);
  32. }
  33. RedBakeNode::~RedBakeNode(){
  34. CC_SAFE_RELEASE(_texture);
  35. this->unschedule(CC_SCHEDULE_SELECTOR(RedBakeNode::update));
  36. for (int i=0; i<_slotFrameArray.size(); i++) {
  37. delete[] _slotFrameArray[i].triangles.verts;
  38. }
  39. for (V3F_C4B_T2F *item : _vertArr){
  40. delete[] item;
  41. }
  42. _vertArr.clear(); // 清空容器
  43. }
  44. void RedBakeNode::setBakeDataFile(const std::string& aFileName) {
  45. _fileNameFull = aFileName;
  46. if (_fileNameFull.empty()) {
  47. _fileName = "";
  48. _stopSelfDraw();
  49. return;
  50. }
  51. std::string path = "";
  52. auto p = _fileNameFull.rfind("/");
  53. if (p != std::string::npos) {
  54. path = _fileNameFull.substr(0, p+1);
  55. _fileName = _fileNameFull.substr(p+1);
  56. } else {
  57. _fileName = _fileNameFull;
  58. }
  59. if (_fileName.find(".rb") != std::string::npos) {
  60. _fileName = _fileName.substr(0, _fileName.size()-3);
  61. }
  62. // FIXME:
  63. RedSpineBakeManage::getInstance()->loadAnimationFile(_fileName, path);
  64. }
  65. const std::string& RedBakeNode::getBakeDataFile() const {
  66. return _fileNameFull;
  67. }
  68. std::vector<std::string> RedBakeNode::getAnimations() {
  69. std::vector<std::string> anims;
  70. RedSpineBakeManage::getInstance()->fetchAnimations(_fileName, anims);
  71. return anims;
  72. }
  73. void RedBakeNode::setBakeFrame(RedBakeNodeFrame frame) {
  74. _curFrame = frame;
  75. if (_curFrame.animationName.size() == 0) {
  76. // 清空显示
  77. _stopSelfDraw();
  78. } else {
  79. if (switchAnimation(_curFrame.animationName, _curFrame.loop)) {
  80. stopAutoDraw();
  81. _startSelfDraw();
  82. updateSelfFunc(_curFrame.elapsedTime, true);
  83. _firstDraw = false;
  84. }
  85. }
  86. }
  87. RedBakeNodeFrame RedBakeNode::getBakeFrame() {
  88. return _curFrame;
  89. }
  90. float RedBakeNode::getAnimDuration(const std::string& tl) {
  91. auto anim = RedSpineBakeManage::getInstance()->getAnimateByName(_fileName, tl);
  92. if (anim) {
  93. return (float)anim->getTotalBakeFrame() / (float)anim->getCurrentFrameRate();
  94. }
  95. return .0;
  96. }
  97. void RedBakeNode::drawBake (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags){
  98. cocos2d::Texture2D* texture = _texture;
  99. if (_isFlipX) {
  100. newTransform = transform;
  101. newTransform.m[0] *= -1; // 将X轴缩放值取反
  102. }
  103. //如果当前节点没有现实,每次都判断是否在屏幕内,如果已经显示每五帧判断一次
  104. if (isInScreen==true) {
  105. if (_currentBakeFrame%5==0) {
  106. animationIsInscreen();
  107. }
  108. }else{
  109. animationIsInscreen();
  110. }
  111. if (isInScreen) {
  112. Point offsetPos = {0,0};
  113. if (_fatherNode!=nullptr) {
  114. if (_fatherNodePosIndex==-1) {
  115. _fatherNodePosIndex = _fatherNode->getFatherBoneOffsetIndex(_fatherNodeBoneName);
  116. }
  117. Point posInt;
  118. if (_fatherNodePosIndex==-1) {
  119. posInt = _fatherNode->getFatherBoneOffset(_fatherNodeBoneName);
  120. }else{
  121. posInt = _fatherNode->getFatherBoneOffsetByIndex(_fatherNodePosIndex);
  122. }
  123. offsetPos.x = (float)posInt.x + _disPos.x;
  124. offsetPos.y = (float)posInt.y + _disPos.y;
  125. }
  126. for (int i = 0; i<_currentBakeAnimation->getSlotCount(); i++) {
  127. RedSlotBakeModel *slotBake = _currentBakeAnimation->getSlotByDrawOrder(i, _currentBakeFrame,_currentDrawOrderIndex);
  128. const std::string& slotName = slotBake->getSlotName();
  129. BKAE_FRAME_PLAY &bfp = *_slotFrameArrayVect[slotBake->getSlotIndex()];//这行性能远快于下面的map,作用一样
  130. if(_attachNodeMapSize>0){
  131. if(bfp.hasAttachNode){
  132. if (_singleAttachNode==nullptr) {
  133. _attachNodeMap[slotName]->drawSelfFunc(renderer, transform, transformFlags);
  134. }else{
  135. _singleAttachNode->drawSelfFunc(renderer, transform, transformFlags);
  136. }
  137. }
  138. }
  139. if(slotBake->slotShoudBeDrawSlot()){
  140. //判断当前slot在当前帧是否需要跳过渲染,判断是否在屏幕内
  141. if(slotBake->getFrameSkip(_currentBakeFrame)){
  142. slotBake->setFrameSkip(_currentBakeFrame, bfp);
  143. }else{
  144. if (texture==nullptr) {
  145. texture = slotBake->getTexture(_currentBakeFrame);
  146. }
  147. BlendFunc &blendFuc = slotBake->getBlendFunc(_currentBakeFrame);
  148. V3F_C4B_T2F *beginVert = nullptr;
  149. bool shouldMerge = false;
  150. if (_currentBakeFrame>1&&_currentBakeFrame<=_totalBakeFrame) {
  151. shouldMerge = true;
  152. }
  153. beginVert = _vertArr[bfp.vertMapIndex];
  154. slotBake->getTriangles(_currentBakeFrame,bfp, offsetPos, _currentFrameFracpart, beginVert,shouldMerge);
  155. cocos2d::TrianglesCommand::Triangles triangles = bfp.triangles;
  156. triangles.verts = beginVert;
  157. if(slotName == "slot_duihua"){
  158. _speechPos = Vec2(offsetPos.x,offsetPos.y);
  159. // CCLOG("[sc bake : speechPos %f, %f", _speechPos.x, _speechPos.y);
  160. }
  161. #if COCOS2D_VERSION < 0x00040000
  162. if(_isFlipX){
  163. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, _glProgramState, blendFuc, triangles, newTransform, transformFlags);
  164. }else{
  165. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, _glProgramState, blendFuc, triangles, transform, transformFlags);
  166. }
  167. #else
  168. if(_isFlipX){
  169. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, blendFuc, triangles, newTransform, transformFlags);
  170. }else{
  171. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, blendFuc, triangles, transform, transformFlags);
  172. }
  173. #endif
  174. }
  175. }
  176. }
  177. }
  178. }
  179. void RedBakeNode::drawMixBake (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags){
  180. RedMixAnimationBakeModel *mixAni = (RedMixAnimationBakeModel *)_currentBakeAnimation;
  181. if (isInScreen==true) {
  182. if (_currentBakeFrame%5==0) {
  183. animationIsInscreen();
  184. }
  185. }else{
  186. animationIsInscreen();
  187. }
  188. if (isInScreen) {
  189. Point offsetPos = {0,0};
  190. if (_fatherNode!=nullptr) {
  191. Point posInt = _fatherNode->getFatherBoneOffset(_fatherNodeBoneName);
  192. offsetPos.x = (float)posInt.x + _disPos.x;
  193. offsetPos.y = (float)posInt.y + _disPos.y;
  194. // CCLOG("%d/%d---%f,%f",_currentBakeFrame,_totalBakeFrame,offsetPos.x,offsetPos.y);
  195. }
  196. std::vector<int> keys = mixAni->getMixBakeFrameArrAllKey();
  197. for (int i = 0; i<keys.size(); i++) {
  198. int zOrderIndex = keys[i];
  199. cocos2d::Texture2D* texture = mixAni->getTexture(zOrderIndex);
  200. BlendFunc blendFuc = mixAni->getBlendFunc(zOrderIndex);
  201. cocos2d::TrianglesCommand::Triangles triangles = mixAni->getTriangles(zOrderIndex,_realCurrentBakeFrame);
  202. for (int j=0; j<triangles.vertCount; j++) {
  203. triangles.verts[j].vertices.x += offsetPos.x;
  204. triangles.verts[j].vertices.y += offsetPos.y;
  205. }
  206. #if COCOS2D_VERSION < 0x00040000
  207. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, _glProgramState, blendFuc, triangles, transform, transformFlags);
  208. #else
  209. CommandBuff::getInstance()->addCommand(renderer, _globalZOrder, texture, blendFuc, triangles, transform, transformFlags);
  210. #endif
  211. }
  212. }
  213. }
  214. void RedBakeNode::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t transformFlags) {
  215. if (_drawSelf) {
  216. drawSelfFunc(renderer, transform, transformFlags);
  217. }
  218. }
  219. void RedBakeNode::update (float deltaTime){
  220. if (_drawSelf==false) {
  221. return;
  222. }
  223. updateSelfFunc(deltaTime);
  224. // CCLOG("%d",_currentBakeFrame);
  225. }
  226. void RedBakeNode::updateSelfFunc(float deltaTime, bool bInFrameMode){
  227. if (_currentBakeAnimation==nullptr) {
  228. return ;
  229. }
  230. if (_attachNodeMapSize>0) {
  231. if (_singleAttachNode) {
  232. _singleAttachNode->updateSelfFunc(deltaTime, bInFrameMode);
  233. if (_attachNodeMapHasChanged == true) {
  234. _attachNodeMapHasChanged = false;
  235. }
  236. }else{
  237. for (auto it = _attachNodeMap.begin(); it != _attachNodeMap.end(); ++it) {
  238. RedBakeNode* value = it->second;
  239. value->updateSelfFunc(deltaTime, bInFrameMode);
  240. if (_attachNodeMapHasChanged == true) {
  241. _attachNodeMapHasChanged = false;
  242. break;
  243. }
  244. }
  245. }
  246. }
  247. if (_currentAnimationIsFinished==false) {
  248. //如果动画还没播放完毕
  249. if (_currentAnimationIsPaused==false) {
  250. float delta = deltaTime*(float)_currentBakeAnimation->getCurrentFrameRate();
  251. _realCurrentBakeFrame += delta;
  252. // CCLOG("%f",_realCurrentBakeFrame);
  253. float intpart;
  254. _currentFrameFracpart = modf(_realCurrentBakeFrame, &intpart);
  255. // _currentBakeFrame = intpart+1;
  256. _currentBakeFrame = MIN(intpart+1, _totalBakeFrame);
  257. // CCLOG("sc : 帧数 %d", _currentBakeFrame);
  258. // CCLOG("%d",_currentBakeFrame);
  259. // _currentBakeFrame++;//如果没有暂停且时间够一帧就播放一个动画
  260. }
  261. //因为最后一帧的时长不一定是一整帧,我们是按15帧烘培的,spine是按30帧K的,所以可能存在最后一帧误差,烘培的时候算上了这个
  262. if (_realCurrentBakeFrame>=(_totalBakeFrame-1.0+_currentBakeAnimation->getLastDrawOverTime())) {
  263. if (_currentBakeAnimation->isMixAnimation()) {
  264. //如果是动画混合播完,就接下一个动画
  265. RedMixAnimationBakeModel *mixAni = (RedMixAnimationBakeModel *)_currentBakeAnimation;
  266. if (_listener) {
  267. _listener(_currentBakeAnimation->getAimationName(),RBN_STATE::MixPreAniEnd);
  268. }
  269. _currentBakeAnimation = mixAni->getNextAnimation();
  270. delete mixAni;
  271. resetPlayInfo();
  272. _currentAnimationIsFinished = false;
  273. _currentAnimationIsPaused = false;
  274. }else{
  275. if(_isLoop==true){
  276. // 单帧模式下不能每次都设置到第一、二帧
  277. if (bInFrameMode) {
  278. _currentBakeFrame = (int(_realCurrentBakeFrame) % _totalBakeFrame) + 1;
  279. } else {
  280. // float tmp_realCurrentBakeFrame =_realCurrentBakeFrame-_totalBakeFrame;
  281. // resetPlayInfo();//如果循环就重制
  282. _realCurrentBakeFrame = 1+_currentFrameFracpart;//把刚刚上次循环多余的时间也加上
  283. float intpart;
  284. _currentFrameFracpart = modf(_realCurrentBakeFrame, &intpart);
  285. _currentBakeFrame = MIN(intpart+1, _totalBakeFrame);
  286. }
  287. } else {
  288. //如果不循环就停滞,同时通知
  289. _currentBakeFrame = _totalBakeFrame;
  290. _currentAnimationIsFinished = true;
  291. if (_listener) {
  292. _listener(_currentBakeAnimation->getAimationName(),RBN_STATE::Complete);
  293. }
  294. }
  295. }
  296. }
  297. }
  298. }
  299. bool RedBakeNode::switchAnimation(const std::string& animationName, bool loop){
  300. if (_currentAnimationIsFinished==false) {
  301. stopCurrentAnimation();//如果有正在播放的,就先停下来
  302. }
  303. _currentBakeAnimation = RedSpineBakeManage::getInstance()->getAnimateByName(_fileName, animationName);
  304. if (_currentBakeAnimation==nullptr) {
  305. CCASSERT(0, ("动画没有找到" + animationName).c_str());
  306. return false;
  307. }
  308. _isFirstReset = true;
  309. resetPlayInfo();
  310. _isLoop = loop;
  311. _currentAnimationIsFinished = false;
  312. _currentAnimationIsPaused = false;
  313. _reloadVertMap();
  314. return true;
  315. }
  316. bool RedBakeNode::playAnimation (const std::string& animationName, bool loop, float spdRate) {
  317. if (_fileName.empty()) {
  318. _stopSelfDraw();
  319. return false;
  320. }
  321. if (switchAnimation(animationName, loop)) {
  322. startAutoDraw();
  323. }
  324. float frameRate = 15;
  325. frameRate*=spdRate;
  326. if(_currentBakeAnimation){
  327. _currentBakeAnimation->setCurrentFrameRate(frameRate);
  328. handleEvent(_eventCallBack);
  329. }
  330. return true;
  331. }
  332. bool RedBakeNode::stopCurrentAnimation(){
  333. if (_currentAnimationIsFinished) {
  334. return false;
  335. }
  336. _currentAnimationIsFinished = true;
  337. _currentAnimationIsPaused = false;
  338. if (_listener) {
  339. _listener(_currentBakeAnimation->getAimationName(),RBN_STATE::Break);
  340. }
  341. return true;
  342. }
  343. bool RedBakeNode::IscurrentAnimationFinished(){
  344. return _currentAnimationIsFinished;
  345. }
  346. bool RedBakeNode::pauseCurrentAnimation(){
  347. if (_currentAnimationIsFinished) {
  348. return false;
  349. }
  350. _currentAnimationIsPaused = true;
  351. if (_listener) {
  352. _listener(_currentBakeAnimation->getAimationName(),RBN_STATE::Pause);
  353. }
  354. return true;
  355. }
  356. bool RedBakeNode::resumeCurrentAnimation(){
  357. if (_currentAnimationIsFinished) {
  358. return false;
  359. }
  360. _currentAnimationIsPaused = false;
  361. if (_listener) {
  362. _listener(_currentBakeAnimation->getAimationName(),RBN_STATE::Resume);
  363. }
  364. return true;
  365. }
  366. bool RedBakeNode::currentAnimationIsPaused(){
  367. return _currentAnimationIsPaused;
  368. }
  369. bool RedBakeNode::playMixAnimation(const std::string& animationName, bool loop,float aMixTime){
  370. Point pos;
  371. pos.x = 0;
  372. pos.y = 0;
  373. return playMixAnimation(animationName, loop, aMixTime, pos);
  374. }
  375. bool RedBakeNode::playMixAnimation(const std::string& animationName, bool loop,float aMixTime,Point aDis){
  376. if (_currentAnimationIsFinished==false) {
  377. //如果当前动画没有结束
  378. if(_currentBakeAnimation->isMixAnimation()){
  379. return false;
  380. }
  381. }
  382. RedMixAnimationBakeModel *mixAnimation = new RedMixAnimationBakeModel();
  383. const std::map<int,BKAE_FRAME_PLAY> aPreAniBakeFrame = _slotFrameArray;
  384. bool success = mixAnimation->setMixInfo(_currentBakeFrame, aMixTime, aPreAniBakeFrame, animationName,_currentBakeAnimation->getAimationName(), _fileName,aDis);
  385. if (success) {
  386. _currentBakeAnimation = mixAnimation;
  387. _currentBakeFrame = 0;
  388. _isLoop = loop;
  389. _totalBakeFrame = _currentBakeAnimation->getTotalBakeFrame();
  390. _currentAnimationIsFinished = false;
  391. }else{
  392. delete mixAnimation;
  393. playAnimation(animationName, loop);
  394. }
  395. return true;
  396. }
  397. void RedBakeNode::updateLoop(bool loop){
  398. _isLoop = loop;
  399. }
  400. //当前动画是否X翻转
  401. void RedBakeNode::setFlipX(bool aFlipX){
  402. _isFlipX = aFlipX;
  403. }
  404. //当前动画是否翻转
  405. bool RedBakeNode::isFlipX(){
  406. return _isFlipX;
  407. }
  408. void RedBakeNode::setBakeSpineID(std::string aId){
  409. _bakeSpineID = aId;
  410. }
  411. void RedBakeNode::resetPlayInfo(){
  412. _firstDraw = true;
  413. _currentBakeFrame = 1;
  414. _realCurrentBakeFrame = 1.0;
  415. _currentFrameFracpart = 0;
  416. _currentDrawOrderIndex = 0;
  417. _totalBakeFrame = _currentBakeAnimation->getTotalBakeFrame();
  418. if (_slotFrameArray.size()==0||_isFirstReset==true) {
  419. int maxIndex = 1;
  420. for (int i = 0; i<_currentBakeAnimation->getSlotCount(); i++) {
  421. int key = _currentBakeAnimation->getAllSlotKey()[i];
  422. RedSlotBakeModel* slot = _currentBakeAnimation->getSlotFromKey(key);
  423. _slotFrameArray.insert(std::pair<int,BKAE_FRAME_PLAY>(slot->getSlotIndex(), BKAE_FRAME_PLAY()));
  424. if (slot->getSlotIndex()>maxIndex) {
  425. maxIndex = slot->getSlotIndex();
  426. }
  427. }
  428. _slotFrameArrayVect.clear();
  429. _slotFrameArrayVect.resize(maxIndex+1);
  430. for (auto it = _slotFrameArray.begin(); it != _slotFrameArray.end(); ++it){
  431. int key = it->first;
  432. BKAE_FRAME_PLAY &value = it->second;
  433. _slotFrameArrayVect[key] = &value;
  434. }
  435. }
  436. for (int i = 0; i<_currentBakeAnimation->getSlotCount(); i++) {
  437. int key = _currentBakeAnimation->getAllSlotKey()[i];
  438. _currentBakeAnimation->getSlotFromKey(key)->initBKAE_FRAME_PLAY(_slotFrameArray.at(key));
  439. }
  440. _isFirstReset = false;
  441. }
  442. void RedBakeNode::setRBNListener(RBNListener& aListener){
  443. _listener = aListener;
  444. }
  445. //判断某个Slot是否在屏幕内
  446. bool RedBakeNode::animationIsInscreen(){
  447. if(_currentBakeAnimation==nullptr){
  448. isInScreen = false;
  449. return isInScreen;
  450. }
  451. int bigMore = 100;
  452. Vec2 leftBottom = _currentBakeAnimation->getLeftBottomSubSizePos();
  453. Vec2 rightTop = _currentBakeAnimation->getRightTopSubSizePos();
  454. Vec2 globalPos = convertToWorldSpace(zeroPos);
  455. Vec2 leftBottomWorld = leftBottom+globalPos;
  456. Vec2 rightTopWorld = rightTop+globalPos;
  457. auto winSize = Director::getInstance()->getWinSize();
  458. if (leftBottomWorld.x<(0-bigMore)||leftBottomWorld.y<(0-bigMore)||rightTopWorld.x>(winSize.width+bigMore)||rightTopWorld.y>(winSize.height+bigMore)) {
  459. // CCLOG("跑出去了------------%s",_currentBakeAnimation->getAimationName().c_str());
  460. isInScreen = false;
  461. return isInScreen;
  462. }
  463. isInScreen = true;
  464. return isInScreen;
  465. }
  466. void RedBakeNode::mergeTwoVert(V3F_C4B_T2F *beginVert,V3F_C4B_T2F *endVert,int aCount,Point offsetPos){
  467. if (aCount==0) {
  468. return;
  469. }
  470. float dis = _currentFrameFracpart;
  471. if (beginVert[0].colors!=endVert[0].colors) {
  472. for (int i=0; i<aCount; i++) {
  473. beginVert[i].vertices.x = beginVert[i].vertices.x + dis*(endVert[i].vertices.x - beginVert[i].vertices.x)+offsetPos.x;
  474. beginVert[i].vertices.y = beginVert[i].vertices.y + dis*(endVert[i].vertices.y - beginVert[i].vertices.y)+offsetPos.y;
  475. // beginVert[i].vertices.z = beginVert[i].vertices.z + dis*(endVert[i].vertices.z - beginVert[i].vertices.z);
  476. beginVert[i].colors.r = beginVert[i].colors.r + dis*(endVert[i].colors.r - beginVert[i].colors.r);
  477. beginVert[i].colors.g = beginVert[i].colors.g + dis*(endVert[i].colors.g - beginVert[i].colors.g);
  478. beginVert[i].colors.b = beginVert[i].colors.b + dis*(endVert[i].colors.b - beginVert[i].colors.b);
  479. beginVert[i].colors.a = beginVert[i].colors.a + dis*(endVert[i].colors.a - beginVert[i].colors.a);
  480. // endVert[i].texCoords.u = beginVert[i].texCoords.u + dis*(endVert[i].texCoords.u - beginVert[i].texCoords.u);
  481. // endVert[i].texCoords.v = beginVert[i].texCoords.v + dis*(endVert[i].texCoords.v - beginVert[i].texCoords.v);
  482. }
  483. }else{
  484. for (int i=0; i<aCount; i++) {
  485. beginVert[i].vertices.x = beginVert[i].vertices.x + dis*(endVert[i].vertices.x - beginVert[i].vertices.x)+offsetPos.x;
  486. beginVert[i].vertices.y = beginVert[i].vertices.y + dis*(endVert[i].vertices.y - beginVert[i].vertices.y)+offsetPos.y;
  487. }
  488. }
  489. }
  490. //当Attach修改的时候,需要更新下singleattch和attchsize
  491. void RedBakeNode::attachNodeBeUpdated(){
  492. if(_attachNodeMap.size()==1){
  493. _singleAttachNode = _attachNodeMap.at(_attachNodeMap.begin()->first);
  494. }else{
  495. _singleAttachNode = nullptr;
  496. }
  497. _attachNodeMapSize = (int)_attachNodeMap.size();
  498. }
  499. void RedBakeNode::addAttachNodeBeforeSlot(std::string aSlotName,RedBakeNode * aBakeNode){
  500. aBakeNode->_stopSelfDraw();
  501. _attachNodeMap.insert(std::pair<std::string, RedBakeNode *>(aSlotName,aBakeNode));
  502. _attachNodeMapHasChanged = true;
  503. attachNodeBeUpdated();
  504. }
  505. void RedBakeNode::removeAttachNode(std::string aSlotName){
  506. auto iter = _attachNodeMap.find(aSlotName);
  507. if (iter != _attachNodeMap.end()) {
  508. RedBakeNode * aBakeNode = iter->second;
  509. aBakeNode->_startSelfDraw();
  510. _attachNodeMap.erase(iter);
  511. _attachNodeMapHasChanged = true;
  512. }
  513. attachNodeBeUpdated();
  514. }
  515. //删除全部绘制附着slot
  516. void RedBakeNode::removeAllAttachNode(){
  517. for (auto it = _attachNodeMap.begin(); it != _attachNodeMap.end(); ++it) {
  518. RedBakeNode* value = it->second;
  519. value->_startSelfDraw();
  520. }
  521. _attachNodeMap.clear();
  522. _attachNodeMapHasChanged = true;
  523. attachNodeBeUpdated();
  524. }
  525. void RedBakeNode::startAutoDraw() {
  526. _startSelfDraw();
  527. if (_schUpdate == nullptr) {
  528. _schUpdate = CC_SCHEDULE_SELECTOR(RedBakeNode::update);
  529. this->schedule(_schUpdate, 0);
  530. }
  531. }
  532. void RedBakeNode::stopAutoDraw() {
  533. if (_schUpdate) {
  534. this->unschedule(_schUpdate);
  535. _schUpdate = nullptr;
  536. }
  537. }
  538. //关闭自我绘制功能,由其他RedBakeNode来绘制
  539. void RedBakeNode::_stopSelfDraw(){
  540. _drawSelf = false;
  541. }
  542. //开启自我绘制功能
  543. void RedBakeNode::_startSelfDraw(){
  544. _drawSelf = true;
  545. }
  546. void RedBakeNode::drawSelfFunc(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t transformFlags){
  547. if (_currentBakeAnimation==nullptr) {
  548. return ;
  549. }
  550. if (_firstDraw) {
  551. _firstDraw = false;
  552. updateSelfFunc(0);
  553. }
  554. if(_currentBakeAnimation!=nullptr){
  555. if (_totalBakeFrame<1) {
  556. _totalBakeFrame = _currentBakeAnimation->getTotalBakeFrame();
  557. resetPlayInfo();
  558. }
  559. if(_currentBakeAnimation->isMixAnimation()){
  560. drawMixBake(renderer, transform, transformFlags);
  561. }else{
  562. drawBake(renderer, transform, transformFlags);
  563. }
  564. }
  565. }
  566. void RedBakeNode::handleEvent(std::function<void(std::string)> cb){
  567. _currentBakeAnimation->handleEventByFrame(this, cb);
  568. }
  569. //添加父Bakenode,确保自己和父node一起运动,aBoneName是父node关于自己的连接点
  570. void RedBakeNode::addFatherNodeBindMove(std::string aBoneName,RedBakeNode * aBakeNode){
  571. if(aBoneName.length()>0&&aBakeNode){
  572. _fatherNode = aBakeNode;
  573. _fatherNodeBoneName = aBoneName;
  574. _fatherNodePosIndex = -1;
  575. }
  576. }
  577. //添加父Bakenode,确保自己和父node一起运动,aBoneName是父node关于自己的连接点
  578. void RedBakeNode::removeFatherNode(){
  579. _fatherNode = nullptr;
  580. _fatherNodeBoneName = "";
  581. }
  582. //获取父节点对应bone的偏移量
  583. const Point RedBakeNode::getFatherBoneOffset(std::string aBoneName){
  584. // if(_currentBakeAnimation==nullptr){
  585. // return Point(0,0);
  586. // }
  587. if (_currentBakeFrame<=1) {//_currentBakeFrame是从1开始的,getABakeModePoint是从0
  588. return _currentBakeAnimation->getABakeModePoint(aBoneName, 0);
  589. }
  590. const Point &begin = _currentBakeAnimation->getABakeModePoint(aBoneName, _currentBakeFrame-2);
  591. const Point &end = _currentBakeAnimation->getABakeModePoint(aBoneName, _currentBakeFrame-1);
  592. Point res;
  593. res.x = begin.x + _currentFrameFracpart*(end.x - begin.x);
  594. res.y = begin.y + _currentFrameFracpart*(end.y - begin.y);
  595. return res;
  596. }
  597. //获取父节点对应bone的偏移量
  598. const Point RedBakeNode::getFatherBoneOffsetByIndex(int aIndex){
  599. if (_currentBakeFrame<=1) {//_currentBakeFrame是从1开始的,getABakeModePoint是从0
  600. return _currentBakeAnimation->getABakeModePoint(aIndex, 0);
  601. }
  602. const Point &begin = _currentBakeAnimation->getABakeModePoint(aIndex, _currentBakeFrame-2);
  603. const Point &end = _currentBakeAnimation->getABakeModePoint(aIndex, _currentBakeFrame-1);
  604. Point res;
  605. res.x = begin.x + _currentFrameFracpart*(end.x - begin.x);
  606. res.y = begin.y + _currentFrameFracpart*(end.y - begin.y);
  607. return res;
  608. }
  609. //获取父节点对应bone的偏移量对应的数组索引,用来加速性能
  610. int RedBakeNode::getFatherBoneOffsetIndex(std::string aBoneName){
  611. return _currentBakeAnimation->getBoneAttachsSearchIndex(aBoneName);
  612. }
  613. void RedBakeNode::_reloadVertMap(){
  614. for (V3F_C4B_T2F *item : _vertArr){
  615. delete[] item;
  616. }
  617. _vertArr.clear(); // 清空容器
  618. for (int i = 0; i<_currentBakeAnimation->getSlotCount(); i++) {
  619. int key = _currentBakeAnimation->getAllSlotKey()[i];
  620. RedSlotBakeModel *slotBake = _currentBakeAnimation->getSlotFromKey(key);
  621. int vertCount = slotBake->getVertCount();
  622. _vertArr.push_back(new V3F_C4B_T2F[vertCount]);
  623. BKAE_FRAME_PLAY &bfp = _slotFrameArray.at(slotBake->getSlotIndex());
  624. if (_attachNodeMap.count(slotBake->getSlotName()) > 0) {
  625. bfp.hasAttachNode = true;
  626. }
  627. bfp.vertMapIndex =(int)_vertArr.size()-1;
  628. }
  629. }
  630. //用来记录多个spine合并播放时,骨骼连接点初始的位置差
  631. void RedBakeNode::setDisPos(Point aPos){
  632. _disPos.x = aPos.x;
  633. _disPos.y = aPos.y;
  634. }
  635. //用来指定动画起始位子,这样上下半身走路可以同步,不会同手同脚
  636. void RedBakeNode::updateRealCurrentBakeFrame(float aReal){
  637. _realCurrentBakeFrame = aReal;
  638. float intpart;
  639. _currentFrameFracpart = modf(_realCurrentBakeFrame, &intpart);
  640. _currentBakeFrame = MIN(intpart+1, _totalBakeFrame);
  641. }
  642. //获取当前播放的位置
  643. float RedBakeNode::getRealCurrentBakeFrame(){
  644. return _realCurrentBakeFrame;
  645. }
  646. void RedBakeNode::setTexture(Texture2D * texture) {
  647. CC_SAFE_RETAIN(texture);
  648. CC_SAFE_RELEASE(_texture);
  649. _texture = texture;
  650. }
  651. void RedBakeNode::setEventCallBack(std::function<void(std::string)> cb){
  652. _eventCallBack = cb;
  653. }
  654. Vec2 RedBakeNode::getSpeechPos(){
  655. Vec2 pos = _speechPos;
  656. return pos;
  657. }