RedBakeNode.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //
  2. // RedBakeNode.hpp
  3. // cocos2d_libs
  4. //
  5. // Created by Liang zhong on 2022/11/11.
  6. //
  7. #ifndef RedBakeNode_h
  8. #define RedBakeNode_h
  9. #include "2d/CCNode.h"
  10. #include <stdio.h>
  11. #include "cocos2d.h"
  12. #include "RedSpineBakeManage.h"
  13. #if COCOS2D_VERSION < 0x00040000
  14. #include <spine/SkeletonBatch.h>//v3/
  15. #include <spine/SkeletonTwoColorBatch.h>//v3/
  16. #else
  17. #include <spine/v4/SkeletonBatch.h>
  18. #include <spine/v4/SkeletonTwoColorBatch.h>
  19. #endif
  20. using namespace std;
  21. using namespace cocos2d;
  22. struct RedBakeNodeFrame {
  23. std::string animationName; // 时间线名字
  24. float elapsedTime = .0; // 当前播放过的时间
  25. bool loop = true; // 是否循环
  26. RedBakeNodeFrame()
  27. : animationName(""),
  28. elapsedTime(0.0f),
  29. loop(true)
  30. {}
  31. RedBakeNodeFrame(const std::string& _animationName, float _elapsedTime, bool _loop)
  32. : animationName(_animationName),
  33. elapsedTime(_elapsedTime),
  34. loop(_loop)
  35. {}
  36. };
  37. enum RBN_STATE {Unknown,Complete,Break,Pause,Resume,MixPreAniEnd};
  38. typedef std::function<void(std::string animationName,RBN_STATE aState)> RBNListener;
  39. class RedBakeNode : public Node {
  40. public:
  41. static RedBakeNode *create(const std::string aFileName);
  42. static RedBakeNode *create();
  43. RedBakeNode(const std::string aFileName);
  44. RedBakeNode();
  45. ~RedBakeNode();
  46. // 属性设置
  47. void setBakeDataFile(const std::string& aFileName);
  48. const std::string& getBakeDataFile() const; // 当前选中播放中的时间线
  49. // 时间线K帧支持
  50. std::vector<std::string> getAnimations(); // 所有的时间线列表
  51. void setBakeFrame(RedBakeNodeFrame frame); // 设置节点为指定时间线,指定时间的状态
  52. RedBakeNodeFrame getBakeFrame();
  53. // 打开或者关闭自动绘制(每帧自动绘制)
  54. void startAutoDraw();
  55. void stopAutoDraw();
  56. // 获取时间线的长度
  57. float getAnimDuration(const std::string& tl);
  58. bool playAnimation (const std::string& animationName, bool loop, float spdRate = 1.f);
  59. bool stopCurrentAnimation();
  60. bool pauseCurrentAnimation();
  61. bool resumeCurrentAnimation();
  62. bool currentAnimationIsPaused();
  63. bool playMixAnimation(const std::string& animationName, bool loop,float aMixTime);
  64. bool playMixAnimation(const std::string& animationName, bool loop,float aMixTime,Point aDis);//Point aDis用来处理上下节点连接时,初始位置有偏移,单一节点不需要
  65. bool IscurrentAnimationFinished();
  66. void updateLoop(bool loop);
  67. void setFlipX(bool aFlipX); //当前动画是否X翻转
  68. bool isFlipX(); //当前动画是否翻转
  69. void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override;
  70. void drawBake (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) ;
  71. void drawMixBake (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) ;
  72. void setBakeSpineID(std::string aId);
  73. void resetPlayInfo();
  74. void setRBNListener(RBNListener& aListener);
  75. void update (float deltaTime) override;
  76. void updateSelfFunc(float deltaTime, bool bInFrameMode = false);
  77. //组合bakenode的时候调整绘制顺序
  78. void drawSelfFunc(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t transformFlags);
  79. void addAttachNodeBeforeSlot(std::string aSlotName,RedBakeNode * aBakeNode);//添加一个绘制附件,并指定一个slot绑定,绘制层时先绘制bakenode再绘制slot
  80. void removeAttachNode(std::string aSlotName);//删除一个slot
  81. void removeAllAttachNode();//删除全部slot
  82. void attachNodeBeUpdated();//当Attach修改的时候,需要更新下singleattch和attchsize
  83. //组合Bakenode时候父子连动
  84. void addFatherNodeBindMove(std::string aBoneName,RedBakeNode * aBakeNode);//添加父Bakenode,确保自己和父node一起运动,aBoneName是父node关于自己的连接点
  85. void removeFatherNode();//移除父Bakenode,确保自己和父node一起运动,aBoneName是父node关于自己的连接点
  86. const Point getFatherBoneOffset(std::string aBoneName);//获取父节点对应bone的偏移量
  87. const Point getFatherBoneOffsetByIndex(int aIndex);//获取父节点对应bone的偏移量
  88. int getFatherBoneOffsetIndex(std::string aBoneName);//获取父节点对应bone的偏移量对应的数组索引,用来加速性能
  89. //用来记录多个spine合并播放时,骨骼连接点初始的位置差
  90. void setDisPos(Point aPos);
  91. void updateRealCurrentBakeFrame(float aReal);//用来指定动画起始位子,这样上下半身走路可以同步,不会同手同脚
  92. float getRealCurrentBakeFrame();//获取当前播放的位置
  93. // 设置纹理
  94. void setTexture(Texture2D*);
  95. void setEventCallBack(std::function<void(std::string)> cb);
  96. void handleEvent(std::function<void(std::string)> cb);
  97. Vec2 getSpeechPos();
  98. protected:
  99. bool animationIsInscreen(); //判断某个Slot是否在屏幕内
  100. void _stopSelfDraw(); //关闭自我绘制功能,由其他RedBakeNode来绘制
  101. void _startSelfDraw(); //开启自我绘制功能
  102. //通过BakeFrame的小数部分合并两个Traingle中的顶点Vert的数据,相当于给动画做差值,因为帧率没有这么稳定,卡的时候走的可能是一帧半
  103. void mergeTwoVert(V3F_C4B_T2F *beginVert,V3F_C4B_T2F *endVert,int aCount,Point offsetPos);
  104. void _reloadVertMap();
  105. bool switchAnimation(const std::string& animationName, bool loop);
  106. RedBakeNodeFrame _curFrame;
  107. std::vector<V3F_C4B_T2F *> _vertArr;
  108. int _totalBakeFrame = -1; //指定当前的Animation最大的BakeFrame
  109. int _currentBakeFrame = -1; //当前的Animation播放到第几个BakeFrame
  110. float _realCurrentBakeFrame = -1;//当前的Animation播放到第几个BakeFrame,这个是实际值,因为帧无法完全对齐,每帧间隔在卡的时候会变
  111. float _currentFrameFracpart = 0.0; //当前的Animation播放到第几个BakeFrame的小数部分,rs = (1-_currentFrameFracpart)begin+end
  112. std::map<int,BKAE_FRAME_PLAY> _slotFrameArray; //记录当前slot各属性播放进度
  113. std::vector<BKAE_FRAME_PLAY *> _slotFrameArrayVect; //_slotFrameArray的加速版本,解决性能问题
  114. int _currentDrawOrderIndex = 0;
  115. std::string _bakeSpineID;
  116. bool _isLoop = false; //当前动画是否时Loop
  117. bool _firstDraw = true; //当前动画是否是首日调用
  118. bool _currentAnimationIsFinished = true; //当前动画是否播放完
  119. bool _currentAnimationIsPaused = false; //当前动画是否播暂停
  120. bool _isFlipX = false; //当前动画是否X翻转
  121. bool _isFirstReset = false; //每次调用playAnimation的时候设置成ture,每次resetPlayInfo设置成false,这样确保第一次resetPlayInfo能创建没有slot
  122. RedAnimationBakeModel *_currentBakeAnimation = nullptr;
  123. std::string _fileName;
  124. std::string _fileNameFull;
  125. RBNListener _listener = nullptr;
  126. SEL_SCHEDULE _schUpdate = nullptr;
  127. std::map<std::string,RedBakeNode *> _attachNodeMap; //记录挂载的RedBakeNode节点,用来组合RedBakeNode一起绘制的
  128. //判断_attachNodeMap是否改变,updateSelfFunc里面有遍历_attachNodeMap的,但是上半身结束的时候可能会导致下半身的_attachNodeMap重置,导致遍历出问题
  129. bool _attachNodeMapHasChanged = false;
  130. RedBakeNode *_singleAttachNode = nullptr;//当_attachNodeMap中size为1的时候,_singleAttachNode等于这个唯一,用于加速
  131. int _attachNodeMapSize = 0;//表示_attachNodeMap的数量
  132. bool _drawSelf = true; //是否自我绘制,默认true,自己会绘制自己,否就由其他RedBakeNode来调用Draw函数
  133. RedBakeNode *_fatherNode = nullptr; //记录当前节点需要跟随一起动的父节点
  134. std::string _fatherNodeBoneName; //记录当前节点需要跟随一起动的父节点的骨骼名字,这个骨骼定义了自己的偏移
  135. Point _disPos = {0,0}; //用来记录多个spine合并播放时,骨骼连接点初始的位置差
  136. Vec2 zeroPos;//默认的原点
  137. bool isInScreen = true; //当前Node是否在屏幕内
  138. int _fatherNodePosIndex = -1; //用来索引_fatherNode中Bone偏移放在数组的什么位子,这个数组是用来加快性能的,之前是Map,所以需要记录
  139. cocos2d::Mat4 newTransform;//用于draw里面处理flip
  140. Texture2D* _texture = nullptr;
  141. std::function<void(std::string)> _eventCallBack;
  142. Vec2 _speechPos = Vec2(0,0);
  143. };
  144. #endif /* RedBakeNode_h */