CCDirector.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2010-2013 cocos2d-x.org
  4. Copyright (c) 2011 Zynga Inc.
  5. Copyright (c) 2013-2016 Chukong Technologies Inc.
  6. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
  7. http://www.cocos2d-x.org
  8. Permission is hereby granted, free of charge, to any person obtaining a copy
  9. of this software and associated documentation files (the "Software"), to deal
  10. in the Software without restriction, including without limitation the rights
  11. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the Software is
  13. furnished to do so, subject to the following conditions:
  14. The above copyright notice and this permission notice shall be included in
  15. all copies or substantial portions of the Software.
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. THE SOFTWARE.
  23. ****************************************************************************/
  24. // cocos2d includes
  25. #include "base/CCDirector.h"
  26. // standard includes
  27. #include <string>
  28. #include "2d/CCDrawingPrimitives.h"
  29. #include "2d/CCSpriteFrameCache.h"
  30. #include "platform/CCFileUtils.h"
  31. #include "2d/CCActionManager.h"
  32. #include "2d/CCFontFNT.h"
  33. #include "2d/CCFontAtlasCache.h"
  34. #include "2d/CCAnimationCache.h"
  35. #include "2d/CCTransition.h"
  36. #include "2d/CCFontFreeType.h"
  37. #include "2d/CCLabelAtlas.h"
  38. #include "renderer/CCGLProgramCache.h"
  39. #include "renderer/CCGLProgramStateCache.h"
  40. #include "renderer/CCTextureCache.h"
  41. #include "renderer/ccGLStateCache.h"
  42. #include "renderer/CCRenderer.h"
  43. #include "renderer/CCRenderState.h"
  44. #include "renderer/CCFrameBuffer.h"
  45. #include "2d/CCCamera.h"
  46. #include "base/CCUserDefault.h"
  47. #include "base/ccFPSImages.h"
  48. #include "base/CCScheduler.h"
  49. #include "base/ccMacros.h"
  50. #include "base/CCEventDispatcher.h"
  51. #include "base/CCEventCustom.h"
  52. #include "base/CCConsole.h"
  53. #include "base/CCAutoreleasePool.h"
  54. #include "base/CCConfiguration.h"
  55. #include "base/CCAsyncTaskPool.h"
  56. #include "base/ObjectFactory.h"
  57. #include "platform/CCApplication.h"
  58. #if CC_ENABLE_SCRIPT_BINDING
  59. #include "base/CCScriptSupport.h"
  60. #endif
  61. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  62. #include "platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxEngineDataManager.h"
  63. #endif
  64. /**
  65. Position of the FPS
  66. Default: 0,0 (bottom-left corner)
  67. */
  68. #ifndef CC_DIRECTOR_STATS_POSITION
  69. #define CC_DIRECTOR_STATS_POSITION Director::getInstance()->getVisibleOrigin()
  70. #endif // CC_DIRECTOR_STATS_POSITION
  71. using namespace std;
  72. NS_CC_BEGIN
  73. // FIXME: it should be a Director ivar. Move it there once support for multiple directors is added
  74. // singleton stuff
  75. static Director *s_SharedDirector = nullptr;
  76. #define kDefaultFPS 60 // 60 frames per second
  77. extern const char* cocos2dVersion(void);
  78. const char *Director::EVENT_BEFORE_SET_NEXT_SCENE = "director_before_set_next_scene";
  79. const char *Director::EVENT_AFTER_SET_NEXT_SCENE = "director_after_set_next_scene";
  80. const char *Director::EVENT_PROJECTION_CHANGED = "director_projection_changed";
  81. const char *Director::EVENT_AFTER_DRAW = "director_after_draw";
  82. const char *Director::EVENT_AFTER_VISIT = "director_after_visit";
  83. const char *Director::EVENT_BEFORE_UPDATE = "director_before_update";
  84. const char *Director::EVENT_AFTER_UPDATE = "director_after_update";
  85. const char *Director::EVENT_RESET = "director_reset";
  86. const char *Director::EVENT_BEFORE_DRAW = "director_before_draw";
  87. Director* Director::getInstance()
  88. {
  89. if (!s_SharedDirector)
  90. {
  91. s_SharedDirector = new (std::nothrow) Director;
  92. CCASSERT(s_SharedDirector, "FATAL: Not enough memory");
  93. s_SharedDirector->init();
  94. }
  95. return s_SharedDirector;
  96. }
  97. Director::Director()
  98. : _isStatusLabelUpdated(true)
  99. , _invalid(true)
  100. , _deltaTimePassedByCaller(false)
  101. {
  102. }
  103. bool Director::init(void)
  104. {
  105. setDefaultValues();
  106. // scenes
  107. _runningScene = nullptr;
  108. _nextScene = nullptr;
  109. _notificationNode = nullptr;
  110. _scenesStack.reserve(15);
  111. // FPS
  112. _accumDt = 0.0f;
  113. _frameRate = 0.0f;
  114. _FPSLabel = _drawnBatchesLabel = _drawnVerticesLabel = nullptr;
  115. _totalFrames = 0;
  116. _lastUpdate = std::chrono::steady_clock::now();
  117. _secondsPerFrame = 1.0f;
  118. _frames = 0;
  119. // paused ?
  120. _paused = false;
  121. // purge ?
  122. _purgeDirectorInNextLoop = false;
  123. // restart ?
  124. _restartDirectorInNextLoop = false;
  125. // invalid ?
  126. _invalid = false;
  127. _winSizeInPoints = Size::ZERO;
  128. _openGLView = nullptr;
  129. _defaultFBO = nullptr;
  130. _contentScaleFactor = 1.0f;
  131. _console = new (std::nothrow) Console;
  132. // scheduler
  133. _scheduler = new (std::nothrow) Scheduler();
  134. // action manager
  135. _actionManager = new (std::nothrow) ActionManager();
  136. _scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
  137. _eventDispatcher = new (std::nothrow) EventDispatcher();
  138. _beforeSetNextScene = new (std::nothrow) EventCustom(EVENT_BEFORE_SET_NEXT_SCENE);
  139. _beforeSetNextScene->setUserData(this);
  140. _afterSetNextScene = new (std::nothrow) EventCustom(EVENT_AFTER_SET_NEXT_SCENE);
  141. _afterSetNextScene->setUserData(this);
  142. _eventAfterDraw = new (std::nothrow) EventCustom(EVENT_AFTER_DRAW);
  143. _eventAfterDraw->setUserData(this);
  144. _eventBeforeDraw = new (std::nothrow) EventCustom(EVENT_BEFORE_DRAW);
  145. _eventBeforeDraw->setUserData(this);
  146. _eventAfterVisit = new (std::nothrow) EventCustom(EVENT_AFTER_VISIT);
  147. _eventAfterVisit->setUserData(this);
  148. _eventBeforeUpdate = new (std::nothrow) EventCustom(EVENT_BEFORE_UPDATE);
  149. _eventBeforeUpdate->setUserData(this);
  150. _eventAfterUpdate = new (std::nothrow) EventCustom(EVENT_AFTER_UPDATE);
  151. _eventAfterUpdate->setUserData(this);
  152. _eventProjectionChanged = new (std::nothrow) EventCustom(EVENT_PROJECTION_CHANGED);
  153. _eventProjectionChanged->setUserData(this);
  154. _eventResetDirector = new (std::nothrow) EventCustom(EVENT_RESET);
  155. //init TextureCache
  156. initTextureCache();
  157. initMatrixStack();
  158. _renderer = new (std::nothrow) Renderer;
  159. RenderState::initialize();
  160. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  161. EngineDataManager::init();
  162. #endif
  163. return true;
  164. }
  165. Director::~Director(void)
  166. {
  167. CCLOGINFO("deallocing Director: %p", this);
  168. CC_SAFE_RELEASE(_FPSLabel);
  169. CC_SAFE_RELEASE(_drawnVerticesLabel);
  170. CC_SAFE_RELEASE(_drawnBatchesLabel);
  171. CC_SAFE_RELEASE(_runningScene);
  172. CC_SAFE_RELEASE(_notificationNode);
  173. CC_SAFE_RELEASE(_scheduler);
  174. CC_SAFE_RELEASE(_actionManager);
  175. CC_SAFE_DELETE(_defaultFBO);
  176. CC_SAFE_RELEASE(_beforeSetNextScene);
  177. CC_SAFE_RELEASE(_afterSetNextScene);
  178. CC_SAFE_RELEASE(_eventBeforeUpdate);
  179. CC_SAFE_RELEASE(_eventAfterUpdate);
  180. CC_SAFE_RELEASE(_eventAfterDraw);
  181. CC_SAFE_RELEASE(_eventBeforeDraw);
  182. CC_SAFE_RELEASE(_eventAfterVisit);
  183. CC_SAFE_RELEASE(_eventProjectionChanged);
  184. CC_SAFE_RELEASE(_eventResetDirector);
  185. delete _renderer;
  186. delete _console;
  187. CC_SAFE_RELEASE(_eventDispatcher);
  188. Configuration::destroyInstance();
  189. ObjectFactory::destroyInstance();
  190. s_SharedDirector = nullptr;
  191. }
  192. void Director::setDefaultValues(void)
  193. {
  194. Configuration *conf = Configuration::getInstance();
  195. // default FPS
  196. double fps = conf->getValue("cocos2d.x.fps", Value(kDefaultFPS)).asDouble();
  197. _oldAnimationInterval = _animationInterval = 1.0 / fps;
  198. // Display FPS
  199. _displayStats = conf->getValue("cocos2d.x.display_fps", Value(false)).asBool();
  200. // GL projection
  201. std::string projection = conf->getValue("cocos2d.x.gl.projection", Value("3d")).asString();
  202. if (projection == "3d")
  203. _projection = Projection::_3D;
  204. else if (projection == "2d")
  205. _projection = Projection::_2D;
  206. else if (projection == "custom")
  207. _projection = Projection::CUSTOM;
  208. else
  209. CCASSERT(false, "Invalid projection value");
  210. // Default pixel format for PNG images with alpha
  211. std::string pixel_format = conf->getValue("cocos2d.x.texture.pixel_format_for_png", Value("rgba8888")).asString();
  212. if (pixel_format == "rgba8888")
  213. Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA8888);
  214. else if(pixel_format == "rgba4444")
  215. Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA4444);
  216. else if(pixel_format == "rgba5551")
  217. Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGB5A1);
  218. // PVR v2 has alpha premultiplied ?
  219. bool pvr_alpha_premultiplied = conf->getValue("cocos2d.x.texture.pvrv2_has_alpha_premultiplied", Value(false)).asBool();
  220. Image::setPVRImagesHavePremultipliedAlpha(pvr_alpha_premultiplied);
  221. }
  222. void Director::setGLDefaultValues()
  223. {
  224. // This method SHOULD be called only after openGLView_ was initialized
  225. CCASSERT(_openGLView, "opengl view should not be null");
  226. setAlphaBlending(true);
  227. setDepthTest(false);
  228. setProjection(_projection);
  229. }
  230. // Draw the Scene
  231. void Director::drawScene()
  232. {
  233. // calculate "global" dt
  234. calculateDeltaTime();
  235. if (_openGLView)
  236. {
  237. _openGLView->pollEvents();
  238. }
  239. //tick before glClear: issue #533
  240. if (! _paused)
  241. {
  242. _eventDispatcher->dispatchEvent(_eventBeforeUpdate);
  243. _scheduler->update(_deltaTime);
  244. _eventDispatcher->dispatchEvent(_eventAfterUpdate);
  245. }
  246. _renderer->clear();
  247. experimental::FrameBuffer::clearAllFBOs();
  248. _eventDispatcher->dispatchEvent(_eventBeforeDraw);
  249. /* to avoid flickr, nextScene MUST be here: after tick and before draw.
  250. * FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
  251. */
  252. if (_nextScene)
  253. {
  254. setNextScene();
  255. }
  256. pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  257. if (_runningScene)
  258. {
  259. #if (CC_USE_PHYSICS || (CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION) || CC_USE_NAVMESH)
  260. _runningScene->stepPhysicsAndNavigation(_deltaTime);
  261. #endif
  262. //clear draw stats
  263. _renderer->clearDrawStats();
  264. //render the scene
  265. if(_openGLView)
  266. _openGLView->renderScene(_runningScene, _renderer);
  267. _eventDispatcher->dispatchEvent(_eventAfterVisit);
  268. }
  269. // draw the notifications node
  270. if (_notificationNode)
  271. {
  272. _notificationNode->visit(_renderer, Mat4::IDENTITY, 0);
  273. }
  274. updateFrameRate();
  275. if (_displayStats)
  276. {
  277. #if !CC_STRIP_FPS
  278. showStats();
  279. #endif
  280. }
  281. _renderer->render();
  282. _eventDispatcher->dispatchEvent(_eventAfterDraw);
  283. popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  284. _totalFrames++;
  285. // swap buffers
  286. if (_openGLView)
  287. {
  288. _openGLView->swapBuffers();
  289. }
  290. if (_displayStats)
  291. {
  292. #if !CC_STRIP_FPS
  293. calculateMPF();
  294. #endif
  295. }
  296. }
  297. void Director::calculateDeltaTime()
  298. {
  299. // new delta time. Re-fixed issue #1277
  300. if (_nextDeltaTimeZero)
  301. {
  302. _deltaTime = 0;
  303. _nextDeltaTimeZero = false;
  304. }
  305. else
  306. {
  307. // delta time may passed by invoke mainLoop(dt)
  308. if (!_deltaTimePassedByCaller)
  309. {
  310. auto now = std::chrono::steady_clock::now();
  311. _deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(now - _lastUpdate).count() / 1000000.0f;
  312. _lastUpdate = now;
  313. }
  314. _deltaTime = MAX(0, _deltaTime);
  315. }
  316. #if COCOS2D_DEBUG
  317. // If we are debugging our code, prevent big delta time
  318. if (_deltaTime > 0.2f)
  319. {
  320. _deltaTime = 1 / 60.0f;
  321. }
  322. #endif
  323. }
  324. float Director::getDeltaTime() const
  325. {
  326. return _deltaTime;
  327. }
  328. void Director::setOpenGLView(GLView *openGLView)
  329. {
  330. CCASSERT(openGLView, "opengl view should not be null");
  331. if (_openGLView != openGLView)
  332. {
  333. // Configuration. Gather GPU info
  334. Configuration *conf = Configuration::getInstance();
  335. conf->gatherGPUInfo();
  336. CCLOG("%s\n",conf->getInfo().c_str());
  337. if(_openGLView)
  338. _openGLView->release();
  339. _openGLView = openGLView;
  340. _openGLView->retain();
  341. // set size
  342. _winSizeInPoints = _openGLView->getDesignResolutionSize();
  343. _isStatusLabelUpdated = true;
  344. if (_openGLView)
  345. {
  346. setGLDefaultValues();
  347. }
  348. _renderer->initGLView();
  349. CHECK_GL_ERROR_DEBUG();
  350. if (_eventDispatcher)
  351. {
  352. _eventDispatcher->setEnabled(true);
  353. }
  354. _defaultFBO = experimental::FrameBuffer::getOrCreateDefaultFBO(_openGLView);
  355. _defaultFBO->retain();
  356. }
  357. }
  358. TextureCache* Director::getTextureCache() const
  359. {
  360. return _textureCache;
  361. }
  362. void Director::initTextureCache()
  363. {
  364. _textureCache = new (std::nothrow) TextureCache();
  365. }
  366. void Director::destroyTextureCache()
  367. {
  368. if (_textureCache)
  369. {
  370. _textureCache->waitForQuit();
  371. CC_SAFE_RELEASE_NULL(_textureCache);
  372. }
  373. }
  374. void Director::setViewport()
  375. {
  376. if (_openGLView)
  377. {
  378. _openGLView->setViewPortInPoints(0, 0, _winSizeInPoints.width, _winSizeInPoints.height);
  379. }
  380. }
  381. void Director::setNextDeltaTimeZero(bool nextDeltaTimeZero)
  382. {
  383. _nextDeltaTimeZero = nextDeltaTimeZero;
  384. }
  385. //
  386. // FIXME TODO
  387. // Matrix code MUST NOT be part of the Director
  388. // MUST BE moved outside.
  389. // Why the Director must have this code ?
  390. //
  391. void Director::initMatrixStack()
  392. {
  393. while (!_modelViewMatrixStack.empty())
  394. {
  395. _modelViewMatrixStack.pop();
  396. }
  397. _projectionMatrixStackList.clear();
  398. while (!_textureMatrixStack.empty())
  399. {
  400. _textureMatrixStack.pop();
  401. }
  402. _modelViewMatrixStack.push(Mat4::IDENTITY);
  403. std::stack<Mat4> projectionMatrixStack;
  404. projectionMatrixStack.push(Mat4::IDENTITY);
  405. _projectionMatrixStackList.push_back(projectionMatrixStack);
  406. _textureMatrixStack.push(Mat4::IDENTITY);
  407. }
  408. void Director::resetMatrixStack()
  409. {
  410. initMatrixStack();
  411. }
  412. void Director::initProjectionMatrixStack(size_t stackCount)
  413. {
  414. _projectionMatrixStackList.clear();
  415. std::stack<Mat4> projectionMatrixStack;
  416. projectionMatrixStack.push(Mat4::IDENTITY);
  417. for (size_t i = 0; i < stackCount; ++i)
  418. _projectionMatrixStackList.push_back(projectionMatrixStack);
  419. }
  420. size_t Director::getProjectionMatrixStackSize()
  421. {
  422. return _projectionMatrixStackList.size();
  423. }
  424. void Director::popMatrix(MATRIX_STACK_TYPE type)
  425. {
  426. if(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW == type)
  427. {
  428. _modelViewMatrixStack.pop();
  429. }
  430. else if(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION == type)
  431. {
  432. _projectionMatrixStackList[0].pop();
  433. }
  434. else if(MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE == type)
  435. {
  436. _textureMatrixStack.pop();
  437. }
  438. else
  439. {
  440. CCASSERT(false, "unknown matrix stack type");
  441. }
  442. }
  443. void Director::popProjectionMatrix(size_t index)
  444. {
  445. _projectionMatrixStackList[index].pop();
  446. }
  447. void Director::loadIdentityMatrix(MATRIX_STACK_TYPE type)
  448. {
  449. if(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW == type)
  450. {
  451. _modelViewMatrixStack.top() = Mat4::IDENTITY;
  452. }
  453. else if(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION == type)
  454. {
  455. _projectionMatrixStackList[0].top() = Mat4::IDENTITY;
  456. }
  457. else if(MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE == type)
  458. {
  459. _textureMatrixStack.top() = Mat4::IDENTITY;
  460. }
  461. else
  462. {
  463. CCASSERT(false, "unknown matrix stack type");
  464. }
  465. }
  466. void Director::loadProjectionIdentityMatrix(size_t index)
  467. {
  468. _projectionMatrixStackList[index].top() = Mat4::IDENTITY;
  469. }
  470. void Director::loadMatrix(MATRIX_STACK_TYPE type, const Mat4& mat)
  471. {
  472. if(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW == type)
  473. {
  474. _modelViewMatrixStack.top() = mat;
  475. }
  476. else if(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION == type)
  477. {
  478. _projectionMatrixStackList[0].top() = mat;
  479. }
  480. else if(MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE == type)
  481. {
  482. _textureMatrixStack.top() = mat;
  483. }
  484. else
  485. {
  486. CCASSERT(false, "unknown matrix stack type");
  487. }
  488. }
  489. void Director::loadProjectionMatrix(const Mat4& mat, size_t index)
  490. {
  491. _projectionMatrixStackList[index].top() = mat;
  492. }
  493. void Director::multiplyMatrix(MATRIX_STACK_TYPE type, const Mat4& mat)
  494. {
  495. if(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW == type)
  496. {
  497. _modelViewMatrixStack.top() *= mat;
  498. }
  499. else if(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION == type)
  500. {
  501. _projectionMatrixStackList[0].top() *= mat;
  502. }
  503. else if(MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE == type)
  504. {
  505. _textureMatrixStack.top() *= mat;
  506. }
  507. else
  508. {
  509. CCASSERT(false, "unknown matrix stack type");
  510. }
  511. }
  512. void Director::multiplyProjectionMatrix(const Mat4& mat, size_t index)
  513. {
  514. _projectionMatrixStackList[index].top() *= mat;
  515. }
  516. void Director::pushMatrix(MATRIX_STACK_TYPE type)
  517. {
  518. if(type == MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW)
  519. {
  520. _modelViewMatrixStack.push(_modelViewMatrixStack.top());
  521. }
  522. else if(type == MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION)
  523. {
  524. _projectionMatrixStackList[0].push(_projectionMatrixStackList[0].top());
  525. }
  526. else if(type == MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE)
  527. {
  528. _textureMatrixStack.push(_textureMatrixStack.top());
  529. }
  530. else
  531. {
  532. CCASSERT(false, "unknown matrix stack type");
  533. }
  534. }
  535. void Director::pushProjectionMatrix(size_t index)
  536. {
  537. _projectionMatrixStackList[index].push(_projectionMatrixStackList[index].top());
  538. }
  539. const Mat4& Director::getMatrix(MATRIX_STACK_TYPE type) const
  540. {
  541. if(type == MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW)
  542. {
  543. return _modelViewMatrixStack.top();
  544. }
  545. else if(type == MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION)
  546. {
  547. return _projectionMatrixStackList[0].top();
  548. }
  549. else if(type == MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE)
  550. {
  551. return _textureMatrixStack.top();
  552. }
  553. CCASSERT(false, "unknown matrix stack type, will return modelview matrix instead");
  554. return _modelViewMatrixStack.top();
  555. }
  556. const Mat4& Director::getProjectionMatrix(size_t index) const
  557. {
  558. return _projectionMatrixStackList[index].top();
  559. }
  560. void Director::setProjection(Projection projection)
  561. {
  562. Size size = _winSizeInPoints;
  563. if (size.width == 0 || size.height == 0)
  564. {
  565. CCLOGERROR("cocos2d: warning, Director::setProjection() failed because size is 0");
  566. return;
  567. }
  568. setViewport();
  569. switch (projection)
  570. {
  571. case Projection::_2D:
  572. {
  573. Mat4 orthoMatrix;
  574. Mat4::createOrthographicOffCenter(0, size.width, 0, size.height, -1024, 1024, &orthoMatrix);
  575. loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
  576. loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  577. break;
  578. }
  579. case Projection::_3D:
  580. {
  581. float zeye = this->getZEye();
  582. Mat4 matrixPerspective, matrixLookup;
  583. // issue #1334
  584. Mat4::createPerspective(60, (GLfloat)size.width/size.height, 10, zeye+size.height/2, &matrixPerspective);
  585. Vec3 eye(size.width/2, size.height/2, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);
  586. Mat4::createLookAt(eye, center, up, &matrixLookup);
  587. Mat4 proj3d = matrixPerspective * matrixLookup;
  588. loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, proj3d);
  589. loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  590. break;
  591. }
  592. case Projection::CUSTOM:
  593. // Projection Delegate is no longer needed
  594. // since the event "PROJECTION CHANGED" is emitted
  595. break;
  596. default:
  597. CCLOG("cocos2d: Director: unrecognized projection");
  598. break;
  599. }
  600. _projection = projection;
  601. GL::setProjectionMatrixDirty();
  602. _eventDispatcher->dispatchEvent(_eventProjectionChanged);
  603. }
  604. void Director::purgeCachedData(void)
  605. {
  606. FontFNT::purgeCachedData();
  607. FontAtlasCache::purgeCachedData();
  608. if (s_SharedDirector->getOpenGLView())
  609. {
  610. SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();
  611. _textureCache->removeUnusedTextures();
  612. // Note: some tests such as ActionsTest are leaking refcounted textures
  613. // There should be no test textures left in the cache
  614. //log("%s\n", _textureCache->getCachedTextureInfo().c_str());
  615. }
  616. FileUtils::getInstance()->purgeCachedEntries();
  617. }
  618. float Director::getZEye(void) const
  619. {
  620. return (_winSizeInPoints.height / 1.154700538379252f);//(2 * tanf(M_PI/6))
  621. }
  622. void Director::setAlphaBlending(bool on)
  623. {
  624. if (on)
  625. {
  626. GL::blendFunc(CC_BLEND_SRC, CC_BLEND_DST);
  627. }
  628. else
  629. {
  630. GL::blendFunc(GL_ONE, GL_ZERO);
  631. }
  632. CHECK_GL_ERROR_DEBUG();
  633. }
  634. void Director::setDepthTest(bool on)
  635. {
  636. _renderer->setDepthTest(on);
  637. }
  638. void Director::setClearColor(const Color4F& clearColor)
  639. {
  640. _renderer->setClearColor(clearColor);
  641. auto defaultFBO = experimental::FrameBuffer::getOrCreateDefaultFBO(_openGLView);
  642. if(defaultFBO) defaultFBO->setClearColor(clearColor);
  643. }
  644. static void GLToClipTransform(Mat4 *transformOut)
  645. {
  646. if(nullptr == transformOut) return;
  647. Director* director = Director::getInstance();
  648. CCASSERT(nullptr != director, "Director is null when setting matrix stack");
  649. auto projection = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  650. auto modelview = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  651. *transformOut = projection * modelview;
  652. }
  653. Vec2 Director::convertToGL(const Vec2& uiPoint)
  654. {
  655. Mat4 transform;
  656. GLToClipTransform(&transform);
  657. Mat4 transformInv = transform.getInversed();
  658. // Calculate z=0 using -> transform*[0, 0, 0, 1]/w
  659. float zClip = transform.m[14]/transform.m[15];
  660. Size glSize = _openGLView->getDesignResolutionSize();
  661. Vec4 clipCoord(2.0f*uiPoint.x/glSize.width - 1.0f, 1.0f - 2.0f*uiPoint.y/glSize.height, zClip, 1);
  662. Vec4 glCoord;
  663. //transformInv.transformPoint(clipCoord, &glCoord);
  664. transformInv.transformVector(clipCoord, &glCoord);
  665. float factor = 1.0f / glCoord.w;
  666. return Vec2(glCoord.x * factor, glCoord.y * factor);
  667. }
  668. Vec2 Director::convertToUI(const Vec2& glPoint)
  669. {
  670. Mat4 transform;
  671. GLToClipTransform(&transform);
  672. Vec4 clipCoord;
  673. // Need to calculate the zero depth from the transform.
  674. Vec4 glCoord(glPoint.x, glPoint.y, 0.0, 1);
  675. transform.transformVector(glCoord, &clipCoord);
  676. /*
  677. BUG-FIX #5506
  678. a = (Vx, Vy, Vz, 1)
  679. b = (a×M)T
  680. Out = 1 ⁄ bw(bx, by, bz)
  681. */
  682. clipCoord.x = clipCoord.x / clipCoord.w;
  683. clipCoord.y = clipCoord.y / clipCoord.w;
  684. clipCoord.z = clipCoord.z / clipCoord.w;
  685. Size glSize = _openGLView->getDesignResolutionSize();
  686. float factor = 1.0f / glCoord.w;
  687. return Vec2(glSize.width * (clipCoord.x * 0.5f + 0.5f) * factor, glSize.height * (-clipCoord.y * 0.5f + 0.5f) * factor);
  688. }
  689. const Size& Director::getWinSize(void) const
  690. {
  691. return _winSizeInPoints;
  692. }
  693. Size Director::getWinSizeInPixels() const
  694. {
  695. return Size(_winSizeInPoints.width * _contentScaleFactor, _winSizeInPoints.height * _contentScaleFactor);
  696. }
  697. Size Director::getVisibleSize() const
  698. {
  699. if (_openGLView)
  700. {
  701. return _openGLView->getVisibleSize();
  702. }
  703. else
  704. {
  705. return Size::ZERO;
  706. }
  707. }
  708. Vec2 Director::getVisibleOrigin() const
  709. {
  710. if (_openGLView)
  711. {
  712. return _openGLView->getVisibleOrigin();
  713. }
  714. else
  715. {
  716. return Vec2::ZERO;
  717. }
  718. }
  719. Rect Director::getSafeAreaRect() const
  720. {
  721. if (_openGLView)
  722. {
  723. return _openGLView->getSafeAreaRect();
  724. }
  725. else
  726. {
  727. return Rect::ZERO;
  728. }
  729. }
  730. // scene management
  731. void Director::runWithScene(Scene *scene)
  732. {
  733. CCASSERT(scene != nullptr, "This command can only be used to start the Director. There is already a scene present.");
  734. CCASSERT(_runningScene == nullptr, "_runningScene should be null");
  735. pushScene(scene);
  736. startAnimation();
  737. }
  738. void Director::replaceScene(Scene *scene)
  739. {
  740. //CCASSERT(_runningScene, "Use runWithScene: instead to start the director");
  741. CCASSERT(scene != nullptr, "the scene should not be null");
  742. if (_runningScene == nullptr) {
  743. runWithScene(scene);
  744. return;
  745. }
  746. if (scene == _nextScene)
  747. return;
  748. if (_nextScene)
  749. {
  750. if (_nextScene->isRunning())
  751. {
  752. _nextScene->onExit();
  753. }
  754. _nextScene->cleanup();
  755. _nextScene = nullptr;
  756. }
  757. ssize_t index = _scenesStack.size() - 1;
  758. _sendCleanupToScene = true;
  759. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  760. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  761. if (sEngine)
  762. {
  763. sEngine->retainScriptObject(this, scene);
  764. sEngine->releaseScriptObject(this, _scenesStack.at(index));
  765. }
  766. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  767. _scenesStack.replace(index, scene);
  768. _nextScene = scene;
  769. }
  770. void Director::pushScene(Scene *scene)
  771. {
  772. CCASSERT(scene, "the scene should not null");
  773. _sendCleanupToScene = false;
  774. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  775. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  776. if (sEngine)
  777. {
  778. sEngine->retainScriptObject(this, scene);
  779. }
  780. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  781. _scenesStack.pushBack(scene);
  782. _nextScene = scene;
  783. }
  784. void Director::popScene(void)
  785. {
  786. CCASSERT(_runningScene != nullptr, "running scene should not null");
  787. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  788. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  789. if (sEngine)
  790. {
  791. sEngine->releaseScriptObject(this, _scenesStack.back());
  792. }
  793. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  794. _scenesStack.popBack();
  795. ssize_t c = _scenesStack.size();
  796. if (c == 0)
  797. {
  798. end();
  799. }
  800. else
  801. {
  802. _sendCleanupToScene = true;
  803. _nextScene = _scenesStack.at(c - 1);
  804. }
  805. }
  806. void Director::popToRootScene(void)
  807. {
  808. popToSceneStackLevel(1);
  809. }
  810. void Director::popToSceneStackLevel(int level)
  811. {
  812. CCASSERT(_runningScene != nullptr, "A running Scene is needed");
  813. ssize_t c = _scenesStack.size();
  814. // level 0? -> end
  815. if (level == 0)
  816. {
  817. end();
  818. return;
  819. }
  820. // current level or lower -> nothing
  821. if (level >= c)
  822. return;
  823. auto firstOnStackScene = _scenesStack.back();
  824. if (firstOnStackScene == _runningScene)
  825. {
  826. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  827. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  828. if (sEngine)
  829. {
  830. sEngine->releaseScriptObject(this, _scenesStack.back());
  831. }
  832. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  833. _scenesStack.popBack();
  834. --c;
  835. }
  836. // pop stack until reaching desired level
  837. while (c > level)
  838. {
  839. auto current = _scenesStack.back();
  840. if (current->isRunning())
  841. {
  842. current->onExit();
  843. }
  844. current->cleanup();
  845. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  846. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  847. if (sEngine)
  848. {
  849. sEngine->releaseScriptObject(this, _scenesStack.back());
  850. }
  851. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  852. _scenesStack.popBack();
  853. --c;
  854. }
  855. _nextScene = _scenesStack.back();
  856. // cleanup running scene
  857. _sendCleanupToScene = true;
  858. }
  859. void Director::end()
  860. {
  861. _purgeDirectorInNextLoop = true;
  862. }
  863. void Director::restart()
  864. {
  865. _restartDirectorInNextLoop = true;
  866. }
  867. void Director::reset()
  868. {
  869. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  870. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  871. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  872. if (_runningScene)
  873. {
  874. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  875. if (sEngine)
  876. {
  877. sEngine->releaseScriptObject(this, _runningScene);
  878. }
  879. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  880. _runningScene->onExit();
  881. _runningScene->cleanup();
  882. _runningScene->release();
  883. }
  884. _runningScene = nullptr;
  885. _nextScene = nullptr;
  886. if (_eventDispatcher)
  887. _eventDispatcher->dispatchEvent(_eventResetDirector);
  888. // cleanup scheduler
  889. getScheduler()->unscheduleAll();
  890. // Remove all events
  891. if (_eventDispatcher)
  892. {
  893. _eventDispatcher->removeAllEventListeners();
  894. }
  895. if(_notificationNode)
  896. {
  897. _notificationNode->onExit();
  898. _notificationNode->cleanup();
  899. _notificationNode->release();
  900. }
  901. _notificationNode = nullptr;
  902. // remove all objects, but don't release it.
  903. // runWithScene might be executed after 'end'.
  904. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  905. if (sEngine)
  906. {
  907. for (const auto &scene : _scenesStack)
  908. {
  909. if (scene)
  910. sEngine->releaseScriptObject(this, scene);
  911. }
  912. }
  913. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  914. _scenesStack.clear();
  915. stopAnimation();
  916. CC_SAFE_RELEASE_NULL(_notificationNode);
  917. CC_SAFE_RELEASE_NULL(_FPSLabel);
  918. CC_SAFE_RELEASE_NULL(_drawnBatchesLabel);
  919. CC_SAFE_RELEASE_NULL(_drawnVerticesLabel);
  920. // purge bitmap cache
  921. FontFNT::purgeCachedData();
  922. FontAtlasCache::purgeCachedData();
  923. FontFreeType::shutdownFreeType();
  924. // purge all managed caches
  925. #if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
  926. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  927. #elif _MSC_VER >= 1400 //vs 2005 or higher
  928. #pragma warning (push)
  929. #pragma warning (disable: 4996)
  930. #endif
  931. //it will crash clang static analyzer so hide it if __clang_analyzer__ defined
  932. #ifndef __clang_analyzer__
  933. DrawPrimitives::free();
  934. #endif
  935. #if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
  936. #pragma GCC diagnostic warning "-Wdeprecated-declarations"
  937. #elif _MSC_VER >= 1400 //vs 2005 or higher
  938. #pragma warning (pop)
  939. #endif
  940. AnimationCache::destroyInstance();
  941. SpriteFrameCache::destroyInstance();
  942. GLProgramCache::destroyInstance();
  943. GLProgramStateCache::destroyInstance();
  944. FileUtils::destroyInstance();
  945. AsyncTaskPool::destroyInstance();
  946. // cocos2d-x specific data structures
  947. UserDefault::destroyInstance();
  948. GL::invalidateStateCache();
  949. RenderState::finalize();
  950. destroyTextureCache();
  951. }
  952. void Director::purgeDirector()
  953. {
  954. reset();
  955. CHECK_GL_ERROR_DEBUG();
  956. // OpenGL view
  957. if (_openGLView)
  958. {
  959. _openGLView->end();
  960. _openGLView = nullptr;
  961. }
  962. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  963. EngineDataManager::destroy();
  964. #endif
  965. // delete Director
  966. release();
  967. }
  968. void Director::restartDirector()
  969. {
  970. reset();
  971. // RenderState need to be reinitialized
  972. RenderState::initialize();
  973. // Texture cache need to be reinitialized
  974. initTextureCache();
  975. // Reschedule for action manager
  976. getScheduler()->scheduleUpdate(getActionManager(), Scheduler::PRIORITY_SYSTEM, false);
  977. // release the objects
  978. PoolManager::getInstance()->getCurrentPool()->clear();
  979. // Restart animation
  980. startAnimation();
  981. // Real restart in script level
  982. #if CC_ENABLE_SCRIPT_BINDING
  983. ScriptEvent scriptEvent(kRestartGame, nullptr);
  984. ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent);
  985. #endif
  986. }
  987. void Director::setNextScene()
  988. {
  989. _eventDispatcher->dispatchEvent(_beforeSetNextScene);
  990. bool runningIsTransition = dynamic_cast<TransitionScene*>(_runningScene) != nullptr;
  991. bool newIsTransition = dynamic_cast<TransitionScene*>(_nextScene) != nullptr;
  992. // If it is not a transition, call onExit/cleanup
  993. if (! newIsTransition)
  994. {
  995. if (_runningScene)
  996. {
  997. _runningScene->onExitTransitionDidStart();
  998. _runningScene->onExit();
  999. }
  1000. // issue #709. the root node (scene) should receive the cleanup message too
  1001. // otherwise it might be leaked.
  1002. if (_sendCleanupToScene && _runningScene)
  1003. {
  1004. _runningScene->cleanup();
  1005. }
  1006. }
  1007. if (_runningScene)
  1008. {
  1009. _runningScene->release();
  1010. }
  1011. _runningScene = _nextScene;
  1012. _nextScene->retain();
  1013. _nextScene = nullptr;
  1014. if ((! runningIsTransition) && _runningScene)
  1015. {
  1016. _runningScene->onEnter();
  1017. _runningScene->onEnterTransitionDidFinish();
  1018. }
  1019. _eventDispatcher->dispatchEvent(_afterSetNextScene);
  1020. }
  1021. void Director::pause()
  1022. {
  1023. if (_paused)
  1024. {
  1025. return;
  1026. }
  1027. _oldAnimationInterval = _animationInterval;
  1028. // when paused, don't consume CPU
  1029. setAnimationInterval(1 / 4.0, SetIntervalReason::BY_DIRECTOR_PAUSE);
  1030. _paused = true;
  1031. }
  1032. void Director::resume()
  1033. {
  1034. if (! _paused)
  1035. {
  1036. return;
  1037. }
  1038. setAnimationInterval(_oldAnimationInterval, SetIntervalReason::BY_ENGINE);
  1039. _paused = false;
  1040. _deltaTime = 0;
  1041. // fix issue #3509, skip one fps to avoid incorrect time calculation.
  1042. setNextDeltaTimeZero(true);
  1043. }
  1044. void Director::updateFrameRate()
  1045. {
  1046. // static const float FPS_FILTER = 0.1f;
  1047. // static float prevDeltaTime = 0.016f; // 60FPS
  1048. //
  1049. // float dt = _deltaTime * FPS_FILTER + (1.0f-FPS_FILTER) * prevDeltaTime;
  1050. // prevDeltaTime = dt;
  1051. // _frameRate = 1.0f/dt;
  1052. // Frame rate should be the real value of current frame.
  1053. _frameRate = 1.0f / _deltaTime;
  1054. }
  1055. #if !CC_STRIP_FPS
  1056. // display the FPS using a LabelAtlas
  1057. // updates the FPS every frame
  1058. void Director::showStats()
  1059. {
  1060. if (_isStatusLabelUpdated)
  1061. {
  1062. createStatsLabel();
  1063. _isStatusLabelUpdated = false;
  1064. }
  1065. static unsigned long prevCalls = 0;
  1066. static unsigned long prevVerts = 0;
  1067. ++_frames;
  1068. _accumDt += _deltaTime;
  1069. if (_displayStats && _FPSLabel && _drawnBatchesLabel && _drawnVerticesLabel)
  1070. {
  1071. char buffer[30] = {0};
  1072. // Probably we don't need this anymore since
  1073. // the framerate is using a low-pass filter
  1074. // to make the FPS stable
  1075. if (_accumDt > CC_DIRECTOR_STATS_INTERVAL)
  1076. {
  1077. sprintf(buffer, "%.1f / %.3f", _frames / _accumDt, _secondsPerFrame);
  1078. _FPSLabel->setString(buffer);
  1079. _accumDt = 0;
  1080. _frames = 0;
  1081. }
  1082. auto currentCalls = (unsigned long)_renderer->getDrawnBatches();
  1083. auto currentVerts = (unsigned long)_renderer->getDrawnVertices();
  1084. if( currentCalls != prevCalls ) {
  1085. sprintf(buffer, "GL calls:%6lu", currentCalls);
  1086. _drawnBatchesLabel->setString(buffer);
  1087. prevCalls = currentCalls;
  1088. }
  1089. if( currentVerts != prevVerts) {
  1090. sprintf(buffer, "GL verts:%6lu", currentVerts);
  1091. _drawnVerticesLabel->setString(buffer);
  1092. prevVerts = currentVerts;
  1093. }
  1094. const Mat4& identity = Mat4::IDENTITY;
  1095. _drawnVerticesLabel->visit(_renderer, identity, 0);
  1096. _drawnBatchesLabel->visit(_renderer, identity, 0);
  1097. _FPSLabel->visit(_renderer, identity, 0);
  1098. }
  1099. }
  1100. void Director::calculateMPF()
  1101. {
  1102. static float prevSecondsPerFrame = 0;
  1103. static const float MPF_FILTER = 0.10f;
  1104. _secondsPerFrame = _deltaTime * MPF_FILTER + (1-MPF_FILTER) * prevSecondsPerFrame;
  1105. prevSecondsPerFrame = _secondsPerFrame;
  1106. }
  1107. // returns the FPS image data pointer and len
  1108. void Director::getFPSImageData(unsigned char** datapointer, ssize_t* length)
  1109. {
  1110. // FIXME: fixed me if it should be used
  1111. *datapointer = cc_fps_images_png;
  1112. *length = cc_fps_images_len();
  1113. }
  1114. void Director::createStatsLabel()
  1115. {
  1116. Texture2D *texture = nullptr;
  1117. std::string fpsString = "00.0";
  1118. std::string drawBatchString = "000";
  1119. std::string drawVerticesString = "00000";
  1120. if (_FPSLabel)
  1121. {
  1122. fpsString = _FPSLabel->getString();
  1123. drawBatchString = _drawnBatchesLabel->getString();
  1124. drawVerticesString = _drawnVerticesLabel->getString();
  1125. CC_SAFE_RELEASE_NULL(_FPSLabel);
  1126. CC_SAFE_RELEASE_NULL(_drawnBatchesLabel);
  1127. CC_SAFE_RELEASE_NULL(_drawnVerticesLabel);
  1128. _textureCache->removeTextureForKey("/cc_fps_images");
  1129. FileUtils::getInstance()->purgeCachedEntries();
  1130. }
  1131. Texture2D::PixelFormat currentFormat = Texture2D::getDefaultAlphaPixelFormat();
  1132. Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA4444);
  1133. unsigned char *data = nullptr;
  1134. ssize_t dataLength = 0;
  1135. getFPSImageData(&data, &dataLength);
  1136. Image* image = new (std::nothrow) Image();
  1137. bool isOK = image ? image->initWithImageData(data, dataLength) : false;
  1138. if (! isOK) {
  1139. if(image)
  1140. delete image;
  1141. CCLOGERROR("%s", "Fails: init fps_images");
  1142. return;
  1143. }
  1144. texture = _textureCache->addImage(image, "/cc_fps_images");
  1145. CC_SAFE_RELEASE(image);
  1146. /*
  1147. We want to use an image which is stored in the file named ccFPSImage.c
  1148. for any design resolutions and all resource resolutions.
  1149. To achieve this, we need to ignore 'contentScaleFactor' in 'AtlasNode' and 'LabelAtlas'.
  1150. So I added a new method called 'setIgnoreContentScaleFactor' for 'AtlasNode',
  1151. this is not exposed to game developers, it's only used for displaying FPS now.
  1152. */
  1153. float scaleFactor = 1 / CC_CONTENT_SCALE_FACTOR();
  1154. _FPSLabel = LabelAtlas::create();
  1155. _FPSLabel->retain();
  1156. _FPSLabel->setIgnoreContentScaleFactor(true);
  1157. _FPSLabel->initWithString(fpsString, texture, 12, 32 , '.');
  1158. _FPSLabel->setScale(scaleFactor);
  1159. _drawnBatchesLabel = LabelAtlas::create();
  1160. _drawnBatchesLabel->retain();
  1161. _drawnBatchesLabel->setIgnoreContentScaleFactor(true);
  1162. _drawnBatchesLabel->initWithString(drawBatchString, texture, 12, 32, '.');
  1163. _drawnBatchesLabel->setScale(scaleFactor);
  1164. _drawnVerticesLabel = LabelAtlas::create();
  1165. _drawnVerticesLabel->retain();
  1166. _drawnVerticesLabel->setIgnoreContentScaleFactor(true);
  1167. _drawnVerticesLabel->initWithString(drawVerticesString, texture, 12, 32, '.');
  1168. _drawnVerticesLabel->setScale(scaleFactor);
  1169. Texture2D::setDefaultAlphaPixelFormat(currentFormat);
  1170. const int height_spacing = 22 / CC_CONTENT_SCALE_FACTOR();
  1171. _drawnVerticesLabel->setPosition(Vec2(0, height_spacing*2) + CC_DIRECTOR_STATS_POSITION);
  1172. _drawnBatchesLabel->setPosition(Vec2(0, height_spacing*1) + CC_DIRECTOR_STATS_POSITION);
  1173. _FPSLabel->setPosition(Vec2(0, height_spacing*0)+CC_DIRECTOR_STATS_POSITION);
  1174. }
  1175. #endif // #if !CC_STRIP_FPS
  1176. void Director::setContentScaleFactor(float scaleFactor)
  1177. {
  1178. if (scaleFactor != _contentScaleFactor)
  1179. {
  1180. _contentScaleFactor = scaleFactor;
  1181. _isStatusLabelUpdated = true;
  1182. }
  1183. }
  1184. void Director::setNotificationNode(Node *node)
  1185. {
  1186. if (_notificationNode != nullptr){
  1187. _notificationNode->onExitTransitionDidStart();
  1188. _notificationNode->onExit();
  1189. _notificationNode->cleanup();
  1190. }
  1191. CC_SAFE_RELEASE(_notificationNode);
  1192. _notificationNode = node;
  1193. if (node == nullptr)
  1194. return;
  1195. _notificationNode->onEnter();
  1196. _notificationNode->onEnterTransitionDidFinish();
  1197. CC_SAFE_RETAIN(_notificationNode);
  1198. }
  1199. void Director::setScheduler(Scheduler* scheduler)
  1200. {
  1201. if (_scheduler != scheduler)
  1202. {
  1203. CC_SAFE_RETAIN(scheduler);
  1204. CC_SAFE_RELEASE(_scheduler);
  1205. _scheduler = scheduler;
  1206. }
  1207. }
  1208. void Director::setActionManager(ActionManager* actionManager)
  1209. {
  1210. if (_actionManager != actionManager)
  1211. {
  1212. CC_SAFE_RETAIN(actionManager);
  1213. CC_SAFE_RELEASE(_actionManager);
  1214. _actionManager = actionManager;
  1215. }
  1216. }
  1217. void Director::setEventDispatcher(EventDispatcher* dispatcher)
  1218. {
  1219. if (_eventDispatcher != dispatcher)
  1220. {
  1221. CC_SAFE_RETAIN(dispatcher);
  1222. CC_SAFE_RELEASE(_eventDispatcher);
  1223. _eventDispatcher = dispatcher;
  1224. }
  1225. }
  1226. void Director::startAnimation()
  1227. {
  1228. startAnimation(SetIntervalReason::BY_ENGINE);
  1229. }
  1230. void Director::startAnimation(SetIntervalReason reason)
  1231. {
  1232. _lastUpdate = std::chrono::steady_clock::now();
  1233. _invalid = false;
  1234. _cocos2d_thread_id = std::this_thread::get_id();
  1235. Application::getInstance()->setAnimationInterval(_animationInterval, reason);
  1236. // fix issue #3509, skip one fps to avoid incorrect time calculation.
  1237. setNextDeltaTimeZero(true);
  1238. }
  1239. void Director::mainLoop()
  1240. {
  1241. if (_purgeDirectorInNextLoop)
  1242. {
  1243. _purgeDirectorInNextLoop = false;
  1244. purgeDirector();
  1245. }
  1246. else if (_restartDirectorInNextLoop)
  1247. {
  1248. _restartDirectorInNextLoop = false;
  1249. restartDirector();
  1250. }
  1251. else if (! _invalid)
  1252. {
  1253. drawScene();
  1254. // release the objects
  1255. PoolManager::getInstance()->getCurrentPool()->clear();
  1256. }
  1257. }
  1258. void Director::mainLoop(float dt)
  1259. {
  1260. _deltaTime = dt;
  1261. _deltaTimePassedByCaller = true;
  1262. mainLoop();
  1263. }
  1264. void Director::stopAnimation()
  1265. {
  1266. _invalid = true;
  1267. }
  1268. void Director::setAnimationInterval(float interval)
  1269. {
  1270. setAnimationInterval(interval, SetIntervalReason::BY_GAME);
  1271. }
  1272. void Director::setAnimationInterval(float interval, SetIntervalReason reason)
  1273. {
  1274. _animationInterval = interval;
  1275. if (! _invalid)
  1276. {
  1277. stopAnimation();
  1278. startAnimation(reason);
  1279. }
  1280. }
  1281. void Director::drawMoveScene(int frameNumbers)
  1282. {
  1283. #if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
  1284. bFlag = true;
  1285. if (frameNumbers < 1)
  1286. return;
  1287. LONGLONG interval = 0LL;
  1288. LONG waitMS = 0L;
  1289. static LARGE_INTEGER nLast;
  1290. static LARGE_INTEGER nNow;
  1291. static bool bFirst = true;
  1292. if (bFirst)
  1293. {
  1294. bFirst = false;
  1295. QueryPerformanceCounter(&nLast);
  1296. }
  1297. LARGE_INTEGER freq;
  1298. QueryPerformanceFrequency(&freq);
  1299. double lastPositionX = -999, lastPositionY = -999;
  1300. _openGLView->getCursorPos(&lastPositionX, &lastPositionY);
  1301. //CCLOG("lastPositionX = %f lastPositionY = %f", lastPositionX, lastPositionY);
  1302. auto frameSize = _openGLView->getFrameSize();
  1303. bool bClose = false;
  1304. int det = 105; //(_openGLView->getChangeScreen() ? 10 : 0) + 105;
  1305. int fullscreenWidth = Director::getInstance()->getVisibleSize().width;
  1306. int fullscreenHeight = Director::getInstance()->getVisibleSize().height;
  1307. //Device::getWidthAndHeight(fullscreenWidth, fullscreenHeight);
  1308. int bottomY = -8;
  1309. if (frameSize.width == fullscreenWidth)
  1310. {
  1311. bottomY += 6;
  1312. det = 114;
  1313. }
  1314. if ((frameSize.width - det < lastPositionX &&lastPositionX <= frameSize.width) && (-31 < lastPositionY&&lastPositionY < bottomY))
  1315. bClose = true;
  1316. while (frameNumbers > 0)
  1317. {
  1318. QueryPerformanceCounter(&nNow);
  1319. interval = nNow.QuadPart - nLast.QuadPart;
  1320. if (interval >= 30000)
  1321. {
  1322. nLast.QuadPart = nNow.QuadPart;
  1323. double curPositionX = -999, curPositionY = -999;
  1324. _openGLView->getCursorPos(&curPositionX, &curPositionY);
  1325. auto frameSize = _openGLView->getFrameSize();
  1326. auto state = GetAsyncKeyState(VK_LBUTTON);
  1327. if (!state)
  1328. {
  1329. bFlag = false;
  1330. return;
  1331. }
  1332. if ((curPositionX != lastPositionX || curPositionY != lastPositionY) && (!bClose))
  1333. {
  1334. bFlag = false;
  1335. return;
  1336. }
  1337. calculateDeltaTime();
  1338. //tick before glClear: issue #533
  1339. if (!_paused)
  1340. {
  1341. _eventDispatcher->dispatchEvent(_eventBeforeUpdate);
  1342. _scheduler->update(_deltaTime);
  1343. _eventDispatcher->dispatchEvent(_eventAfterUpdate);
  1344. }
  1345. _renderer->clear();
  1346. experimental::FrameBuffer::clearAllFBOs();
  1347. /* to avoid flickr, nextScene MUST be here: after tick and before draw.
  1348. * FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
  1349. */
  1350. if (_nextScene)
  1351. {
  1352. setNextScene();
  1353. }
  1354. pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  1355. if (_runningScene)
  1356. {
  1357. #if (CC_USE_PHYSICS || (CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION) || CC_USE_NAVMESH)
  1358. _runningScene->stepPhysicsAndNavigation(_deltaTime);
  1359. #endif
  1360. //clear draw stats
  1361. _renderer->clearDrawStats();
  1362. //render the scene
  1363. _openGLView->renderScene(_runningScene, _renderer);
  1364. _eventDispatcher->dispatchEvent(_eventAfterVisit);
  1365. }
  1366. // draw the notifications node
  1367. if (_notificationNode)
  1368. {
  1369. _notificationNode->visit(_renderer, Mat4::IDENTITY, 0);
  1370. }
  1371. if (_displayStats)
  1372. {
  1373. showStats();
  1374. }
  1375. else
  1376. {
  1377. static float prevDeltaTime = 0.016f; // 60FPS
  1378. static const float FPS_FILTER = 0.10f;
  1379. float dt = _deltaTime * FPS_FILTER + (1 - FPS_FILTER) * prevDeltaTime;
  1380. prevDeltaTime = dt;
  1381. _frameRate = 1 / dt;
  1382. }
  1383. _renderer->render();
  1384. _eventDispatcher->dispatchEvent(_eventAfterDraw);
  1385. popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  1386. _totalFrames++;
  1387. // swap buffers
  1388. if (_openGLView)
  1389. {
  1390. _openGLView->swapBuffers();
  1391. }
  1392. if (_displayStats)
  1393. {
  1394. calculateMPF();
  1395. }
  1396. frameNumbers -= 1;
  1397. }
  1398. else {
  1399. waitMS = (30000 - interval) * 1000LL / freq.QuadPart - 1L;
  1400. if (waitMS > 1L)
  1401. Sleep(waitMS);
  1402. }
  1403. bFlag = false;
  1404. // _openGLView->pollEvents();
  1405. }
  1406. #endif
  1407. }
  1408. NS_CC_END