RUResLoader.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "RUResLoader.h"
  2. #include "AudioEngine.h"
  3. #include "RUPlatform.h"
  4. NS_RU_BEGIN
  5. //日志输出宏定义
  6. #define RESLOG_DEBUG
  7. #if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
  8. #define RESLOG(...) do {} while (0)
  9. #else
  10. #ifdef RESLOG_DEBUG
  11. #define RESLOG(format, ...) cocos2d::log("[资源loader日志] " format, ##__VA_ARGS__)
  12. #else
  13. #define RESLOG(...) do {} while (0)
  14. #endif
  15. #endif
  16. #define TEXTURE_LOAD_WEIGHT 100
  17. #define SHADER_COMPILE_WEIGHT 10
  18. #define AUDIO_PRELOAD_WEIGHT 5
  19. #define FUNC_LOAD_WEIGHT 50
  20. std::unordered_map<std::string, ResLoader*> ResLoader::_gResLoaders;
  21. ResLoader* ResLoader::instance(std::string key4Loader) {
  22. auto loaderGot = _gResLoaders.find(key4Loader);
  23. if (loaderGot == _gResLoaders.end()) {
  24. auto loader = new ResLoader();
  25. loader->autorelease();
  26. loader->retain();
  27. loader->_loaderName = key4Loader;
  28. _gResLoaders.insert(pair<std::string, ResLoader*>(key4Loader, loader));
  29. return loader;
  30. }
  31. return loaderGot->second;
  32. }
  33. ResLoader::ResLoader() {
  34. }
  35. ResLoader::~ResLoader() {
  36. }
  37. void ResLoader::addImgs2Load(const vector<string>& imgs)
  38. {
  39. for (string img : imgs) {
  40. _vecImgs.push_back(img);
  41. }
  42. _progresssTotal += imgs.size() * TEXTURE_LOAD_WEIGHT;
  43. }
  44. void ResLoader::addPlists2Load(const vector<string>& plists) {
  45. for (string plist : plists) {
  46. _vecPlists.push_back(plist);
  47. }
  48. _progresssTotal += plists.size() * TEXTURE_LOAD_WEIGHT;
  49. }
  50. void ResLoader::addAudios2Load(const vector<string>& audios) {
  51. for (string audio : audios) {
  52. _vecSounds.push_back(audio);
  53. }
  54. _progresssTotal += audios.size() * AUDIO_PRELOAD_WEIGHT;
  55. }
  56. void ResLoader::addShaders2Compile(const vector<vector<string>>& shaders) {
  57. for (const vector<string>& shader : shaders) {
  58. vector<string> shaderFilePaths;
  59. shaderFilePaths.emplace_back(cocos2d::FileUtils::getInstance()->fullPathForFilename(shader.at(0)));
  60. shaderFilePaths.emplace_back(cocos2d::FileUtils::getInstance()->fullPathForFilename(shader.at(1)));
  61. shaderFilePaths.emplace_back(shader.at(2));
  62. _cfgShaders.push_back(shaderFilePaths);
  63. }
  64. _progresssTotal += shaders.size() * SHADER_COMPILE_WEIGHT;
  65. }
  66. void ResLoader::addFuncs2Load(const std::vector<std::function<void(void)>>& funcs) {
  67. for (std::function<void(void)> func : funcs) {
  68. _vecFuncs.push_back(func);
  69. }
  70. _progresssTotal += funcs.size() * FUNC_LOAD_WEIGHT;
  71. }
  72. void ResLoader::startLoad()
  73. {
  74. auto cacheShader = [](const string& vsh, const string& fsh, const string& name) {
  75. GLProgram* prog = nullptr;
  76. prog = GLProgramCache::getInstance()->getGLProgram(name);
  77. if (prog) {
  78. return;
  79. }
  80. auto fragmentFullPath = cocos2d::FileUtils::getInstance()->fullPathForFilename(fsh);
  81. auto fragSource = cocos2d::FileUtils::getInstance()->getStringFromFile(fragmentFullPath);
  82. if (vsh.size() == 0) {
  83. prog = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
  84. } else {
  85. auto vertexFullPath = cocos2d::FileUtils::getInstance()->fullPathForFilename(vsh);
  86. auto vertexSource = cocos2d::FileUtils::getInstance()->getStringFromFile(vertexFullPath);
  87. prog = GLProgram::createWithByteArrays(vertexSource.c_str(), fragSource.c_str());
  88. }
  89. GLProgramCache::getInstance()->addGLProgram(prog, name);
  90. };
  91. for(auto img : _vecImgs){
  92. Director::getInstance()->getTextureCache()->addImage(img);
  93. }
  94. for(auto plist : _vecPlists){
  95. std::string fn = plist;
  96. int npos = fn.find(".");
  97. std::string fnNew = fn.substr(0, npos);
  98. SpriteFrameCache::getInstance()->addSpriteFramesWithFile(fnNew + ".plist");
  99. }
  100. for(auto sound : _vecSounds){
  101. experimental::AudioEngine::preload(sound);
  102. }
  103. for(auto shader : _cfgShaders){
  104. cacheShader(shader[0], shader[1], shader[2]);
  105. }
  106. for(auto func : _vecFuncs){
  107. func();
  108. }
  109. _state = kLoaderState::LOADED;
  110. }
  111. void ResLoader::startLoadAsync(std::function<void(float)> cbUpdateProgress, std::function<void()> cbWhileFinished) {
  112. RESLOG("ResLoader::startLoadAsync : _state %d", (int)_state);
  113. if (_state != kLoaderState::WAIT) {
  114. return;
  115. }
  116. _progressNow = 0;
  117. _cbWhileFinihsed = cbWhileFinished;
  118. _cbUpdateProgress = cbUpdateProgress;
  119. for(auto img : _vecImgs){
  120. Director::getInstance()->getTextureCache()->addImageAsync(img, CC_CALLBACK_1(ResLoader::_imgTextureAsyncCallback, this));
  121. }
  122. for(auto plist : _vecPlists){
  123. Director::getInstance()->getTextureCache()->addImageAsync(plist, CC_CALLBACK_1(ResLoader::_plistImageAsyncCallback, this));
  124. }
  125. if(_vecImgs.size() == 0 && _vecPlists.size() == 0){
  126. _loadNextResourceAsyns();
  127. }
  128. }
  129. bool ResLoader::isFinished() {
  130. RESLOG("loaderName :%s isFinished %d %d", _loaderName.c_str(), _progressNow, _progresssTotal);
  131. return _state == kLoaderState::LOADED;
  132. }
  133. void ResLoader::_imgTextureAsyncCallback(cocos2d::Texture2D* texture)
  134. {
  135. CCASSERT(texture,"加载失败");
  136. _idx4Img++;
  137. _progressNow += TEXTURE_LOAD_WEIGHT;
  138. if (_cbUpdateProgress) {
  139. _cbUpdateProgress(_progressNow * 100.0 / _progresssTotal);
  140. }
  141. RESLOG("%s load img %d/%lu", _loaderName.c_str(), _idx4Img, _vecImgs.size());
  142. if (_idx4Img == _vecImgs.size() && _idx4Plist == _vecPlists.size()) {
  143. _loadNextResourceAsyns();
  144. }
  145. }
  146. void ResLoader::_plistImageAsyncCallback(cocos2d::Texture2D* texture)
  147. {
  148. CCASSERT(texture,"加载失败");
  149. _idx4Plist++;
  150. _progressNow += TEXTURE_LOAD_WEIGHT;
  151. if (_cbUpdateProgress) {
  152. _cbUpdateProgress(_progressNow * 100.0 / _progresssTotal);
  153. }
  154. RESLOG("%s load plist %d/%lu", _loaderName.c_str(), _idx4Plist, _vecPlists.size());
  155. if (_idx4Plist == _vecPlists.size()) {
  156. for(auto plist : _vecPlists){
  157. std::string fn = plist;
  158. int npos = fn.find(".");
  159. std::string fnNew = fn.substr(0, npos);
  160. SpriteFrameCache::getInstance()->addSpriteFramesWithFile(fnNew + ".plist");
  161. }
  162. }
  163. if (_idx4Img == _vecImgs.size() && _idx4Plist == _vecPlists.size()) {
  164. _loadNextResourceAsyns();
  165. }
  166. }
  167. void ResLoader::_loadNextResourceAsyns() {
  168. RESLOG("ResLoader::_loadNextResourceAsyns : _state %d", (int)_state);
  169. if (_state == kLoaderState::PAUSE) {
  170. return;
  171. }
  172. if (_idx4Sound < _vecSounds.size()) {
  173. RESLOG("%s load audio %d/%lu", _loaderName.c_str(), _idx4Sound, _vecSounds.size());
  174. experimental::AudioEngine::preload(_vecSounds.at(_idx4Sound), [=](bool) {
  175. _idx4Sound ++;
  176. _progressNow += AUDIO_PRELOAD_WEIGHT;
  177. if (_cbUpdateProgress) {
  178. _cbUpdateProgress(_progressNow * 100.0 / _progresssTotal);
  179. }
  180. _loadNextResourceAsyns();
  181. });
  182. } else if (_idx4Shader < _cfgShaders.size()) {
  183. RESLOG("%s load shader %d/%lu", _loaderName.c_str(), _idx4Shader, _cfgShaders.size());
  184. AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_IO, [=](void *) {
  185. GLProgram* prog = nullptr;
  186. prog = GLProgramCache::getInstance()->getGLProgram(_cfgShaders[_idx4Shader][2]);
  187. if (prog == nullptr) {
  188. if (_strVert.size() == 0) {
  189. prog = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, _strFrag.c_str());
  190. } else {
  191. prog = GLProgram::createWithByteArrays(_strVert.c_str(), _strFrag.c_str());
  192. }
  193. GLProgramCache::getInstance()->addGLProgram(prog, _cfgShaders[_idx4Shader][2]);
  194. }
  195. _idx4Shader ++;
  196. _progressNow += SHADER_COMPILE_WEIGHT;
  197. if (_cbUpdateProgress) {
  198. _cbUpdateProgress(_progressNow * 100.0 / _progresssTotal);
  199. }
  200. _loadNextResourceAsyns();
  201. }, nullptr, [=](){
  202. _strFrag = cocos2d::FileUtils::getInstance()->getStringFromFile(_cfgShaders[_idx4Shader][1]);
  203. if (_cfgShaders[_idx4Shader][0].size() != 0) {
  204. _strVert = cocos2d::FileUtils::getInstance()->getStringFromFile(_cfgShaders[_idx4Shader][0]);
  205. } else {
  206. _strVert = "";
  207. }
  208. });
  209. } else if (_idx4Func < _vecFuncs.size()) {
  210. RESLOG("%s load func %d/%lu", _loaderName.c_str(), _idx4Func, _vecFuncs.size());
  211. std::function<void(void)> func = _vecFuncs.at(_idx4Func);
  212. func();
  213. _idx4Func++;
  214. auto scheduler = Director::getInstance()->getScheduler();
  215. scheduler->schedule([=](float dt){
  216. _loadNextResourceAsyns();
  217. }, this, 0, 0, 1.0/60, false, _loaderName);
  218. //add by yuntao
  219. _progressNow += FUNC_LOAD_WEIGHT;
  220. if (_cbUpdateProgress) {
  221. _cbUpdateProgress(_progressNow * 100.0 / _progresssTotal);
  222. }
  223. } else {
  224. _state = kLoaderState::LOADED;
  225. RESLOG("%s load finished", _loaderName.c_str());
  226. if (_cbWhileFinihsed) {
  227. _cbWhileFinihsed();
  228. }
  229. // Director::getInstance()->getScheduler()->schedule([=](float dt) {
  230. // _instance->release();
  231. // _instance = nullptr;
  232. // }, this, 0.1, 0, 0.1, false, "SCH_RM_SELF");
  233. }
  234. }
  235. void ResLoader::pauseLoading() {
  236. if (_state == kLoaderState::LOADING) {
  237. _state = kLoaderState::PAUSE;
  238. }
  239. }
  240. void ResLoader::resumeLoading() {
  241. if (_state == kLoaderState::PAUSE) {
  242. _state = kLoaderState::LOADING;
  243. _loadNextResourceAsyns();
  244. }
  245. }
  246. NS_RU_END