2019-11-23 20:27:39 +08:00
/****************************************************************************
Copyright ( c ) 2008 - 2010 Ricardo Quesada
Copyright ( c ) 2010 - 2013 cocos2d - x . org
Copyright ( c ) 2011 Zynga Inc .
Copyright ( c ) 2013 - 2016 Chukong Technologies Inc .
Copyright ( c ) 2017 - 2018 Xiamen Yaji Software Co . , Ltd .
2022-04-23 17:45:07 +08:00
Copyright ( c ) 2021 - 2022 Bytedance Inc .
2019-11-23 20:27:39 +08:00
2022-01-04 12:36:20 +08:00
https : //adxeproject.github.io/
2019-11-23 20:27:39 +08:00
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// cocos2d includes
# include "base/CCDirector.h"
// standard includes
# include <string>
# include "2d/CCSpriteFrameCache.h"
# include "platform/CCFileUtils.h"
# include "2d/CCActionManager.h"
# include "2d/CCFontFNT.h"
# include "2d/CCFontAtlasCache.h"
# include "2d/CCAnimationCache.h"
# include "2d/CCTransition.h"
# include "2d/CCFontFreeType.h"
# include "2d/CCLabelAtlas.h"
# include "renderer/CCTextureCache.h"
# include "renderer/CCRenderer.h"
# include "renderer/CCRenderState.h"
# include "2d/CCCamera.h"
# include "base/CCUserDefault.h"
# include "base/ccUtils.h"
# include "base/ccFPSImages.h"
# include "base/CCScheduler.h"
# include "base/ccMacros.h"
# include "base/CCEventDispatcher.h"
# include "base/CCEventCustom.h"
# include "base/CCConsole.h"
# include "base/CCAutoreleasePool.h"
# include "base/CCConfiguration.h"
# include "base/CCAsyncTaskPool.h"
# include "base/ObjectFactory.h"
# include "platform/CCApplication.h"
# include "renderer/backend/ProgramCache.h"
2022-01-03 11:34:58 +08:00
# include "audio/AudioEngine.h"
2019-11-23 20:27:39 +08:00
# if CC_ENABLE_SCRIPT_BINDING
2021-12-25 10:04:45 +08:00
# include "base / CCScriptSupport.h"
2019-11-23 20:27:39 +08:00
# endif
using namespace std ;
NS_CC_BEGIN
// FIXME: it should be a Director ivar. Move it there once support for multiple directors is added
// singleton stuff
2021-12-25 10:04:45 +08:00
static Director * s_SharedDirector = nullptr ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
# define kDefaultFPS 60 // 60 frames per second
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
const char * Director : : EVENT_BEFORE_SET_NEXT_SCENE = " director_before_set_next_scene " ;
const char * Director : : EVENT_AFTER_SET_NEXT_SCENE = " director_after_set_next_scene " ;
const char * Director : : EVENT_PROJECTION_CHANGED = " director_projection_changed " ;
const char * Director : : EVENT_AFTER_DRAW = " director_after_draw " ;
const char * Director : : EVENT_AFTER_VISIT = " director_after_visit " ;
const char * Director : : EVENT_BEFORE_UPDATE = " director_before_update " ;
const char * Director : : EVENT_AFTER_UPDATE = " director_after_update " ;
const char * Director : : EVENT_RESET = " director_reset " ;
const char * Director : : EVENT_BEFORE_DRAW = " director_before_draw " ;
2019-11-23 20:27:39 +08:00
Director * Director : : getInstance ( )
{
if ( ! s_SharedDirector )
{
2021-12-08 00:11:53 +08:00
s_SharedDirector = new Director ;
2019-11-23 20:27:39 +08:00
CCASSERT ( s_SharedDirector , " FATAL: Not enough memory " ) ;
s_SharedDirector - > init ( ) ;
}
return s_SharedDirector ;
}
2021-12-25 10:04:45 +08:00
Director : : Director ( ) { }
2019-11-23 20:27:39 +08:00
bool Director : : init ( )
{
setDefaultValues ( ) ;
_scenesStack . reserve ( 15 ) ;
// FPS
_lastUpdate = std : : chrono : : steady_clock : : now ( ) ;
2021-12-25 10:04:45 +08:00
2021-12-08 00:11:53 +08:00
_console = new Console ;
2019-11-23 20:27:39 +08:00
// scheduler
2021-12-08 00:11:53 +08:00
_scheduler = new Scheduler ( ) ;
2019-11-23 20:27:39 +08:00
// action manager
2021-12-08 00:11:53 +08:00
_actionManager = new ActionManager ( ) ;
2019-11-23 20:27:39 +08:00
_scheduler - > scheduleUpdate ( _actionManager , Scheduler : : PRIORITY_SYSTEM , false ) ;
2021-12-08 00:11:53 +08:00
_eventDispatcher = new EventDispatcher ( ) ;
2021-12-25 10:04:45 +08:00
2021-12-08 00:11:53 +08:00
_beforeSetNextScene = new EventCustom ( EVENT_BEFORE_SET_NEXT_SCENE ) ;
2019-11-23 20:27:39 +08:00
_beforeSetNextScene - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_afterSetNextScene = new EventCustom ( EVENT_AFTER_SET_NEXT_SCENE ) ;
2019-11-23 20:27:39 +08:00
_afterSetNextScene - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventAfterDraw = new EventCustom ( EVENT_AFTER_DRAW ) ;
2019-11-23 20:27:39 +08:00
_eventAfterDraw - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventBeforeDraw = new EventCustom ( EVENT_BEFORE_DRAW ) ;
2019-11-23 20:27:39 +08:00
_eventBeforeDraw - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventAfterVisit = new EventCustom ( EVENT_AFTER_VISIT ) ;
2019-11-23 20:27:39 +08:00
_eventAfterVisit - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventBeforeUpdate = new EventCustom ( EVENT_BEFORE_UPDATE ) ;
2019-11-23 20:27:39 +08:00
_eventBeforeUpdate - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventAfterUpdate = new EventCustom ( EVENT_AFTER_UPDATE ) ;
2019-11-23 20:27:39 +08:00
_eventAfterUpdate - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventProjectionChanged = new EventCustom ( EVENT_PROJECTION_CHANGED ) ;
2019-11-23 20:27:39 +08:00
_eventProjectionChanged - > setUserData ( this ) ;
2021-12-08 00:11:53 +08:00
_eventResetDirector = new EventCustom ( EVENT_RESET ) ;
2021-12-25 10:04:45 +08:00
// init TextureCache
2019-11-23 20:27:39 +08:00
initTextureCache ( ) ;
initMatrixStack ( ) ;
2021-12-08 00:11:53 +08:00
_renderer = new Renderer ;
2019-11-23 20:27:39 +08:00
return true ;
}
Director : : ~ Director ( )
{
CCLOGINFO ( " deallocing Director: %p " , this ) ;
CC_SAFE_RELEASE ( _FPSLabel ) ;
CC_SAFE_RELEASE ( _drawnVerticesLabel ) ;
CC_SAFE_RELEASE ( _drawnBatchesLabel ) ;
CC_SAFE_RELEASE ( _runningScene ) ;
CC_SAFE_RELEASE ( _notificationNode ) ;
CC_SAFE_RELEASE ( _scheduler ) ;
CC_SAFE_RELEASE ( _actionManager ) ;
CC_SAFE_RELEASE ( _beforeSetNextScene ) ;
CC_SAFE_RELEASE ( _afterSetNextScene ) ;
CC_SAFE_RELEASE ( _eventBeforeUpdate ) ;
CC_SAFE_RELEASE ( _eventAfterUpdate ) ;
CC_SAFE_RELEASE ( _eventAfterDraw ) ;
CC_SAFE_RELEASE ( _eventBeforeDraw ) ;
CC_SAFE_RELEASE ( _eventAfterVisit ) ;
CC_SAFE_RELEASE ( _eventProjectionChanged ) ;
CC_SAFE_RELEASE ( _eventResetDirector ) ;
delete _renderer ;
delete _console ;
CC_SAFE_RELEASE ( _eventDispatcher ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
Configuration : : destroyInstance ( ) ;
ObjectFactory : : destroyInstance ( ) ;
s_SharedDirector = nullptr ;
# if CC_ENABLE_SCRIPT_BINDING
ScriptEngineManager : : destroyInstance ( ) ;
# endif
# if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit ( 0 ) ;
# endif
}
void Director : : setDefaultValues ( )
{
2021-12-25 10:04:45 +08:00
Configuration * conf = Configuration : : getInstance ( ) ;
2019-11-23 20:27:39 +08:00
// default FPS
2021-12-25 10:04:45 +08:00
float fps = conf - > getValue ( " adxe.fps " , Value ( kDefaultFPS ) ) . asFloat ( ) ;
2019-11-23 20:27:39 +08:00
_oldAnimationInterval = _animationInterval = 1.0f / fps ;
// Display FPS
2021-05-18 16:40:30 +08:00
_displayStats = conf - > getValue ( " adxe.display_fps " , Value ( false ) ) . asBool ( ) ;
2019-11-23 20:27:39 +08:00
// GL projection
2021-05-18 16:40:30 +08:00
std : : string projection = conf - > getValue ( " adxe.gl.projection " , Value ( " 3d " ) ) . asString ( ) ;
2019-11-23 20:27:39 +08:00
if ( projection = = " 3d " )
_projection = Projection : : _3D ;
else if ( projection = = " 2d " )
_projection = Projection : : _2D ;
else if ( projection = = " custom " )
_projection = Projection : : CUSTOM ;
else
CCASSERT ( false , " Invalid projection value " ) ;
// Default pixel format for PNG images with alpha
2021-05-18 16:40:30 +08:00
std : : string pixel_format = conf - > getValue ( " adxe.texture.pixel_format_for_png " , Value ( " rgba8888 " ) ) . asString ( ) ;
2019-11-23 20:27:39 +08:00
if ( pixel_format = = " rgba8888 " )
2020-09-25 11:07:56 +08:00
Texture2D : : setDefaultAlphaPixelFormat ( backend : : PixelFormat : : RGBA8 ) ;
2021-12-25 10:04:45 +08:00
else if ( pixel_format = = " rgba4444 " )
2020-09-25 11:07:56 +08:00
Texture2D : : setDefaultAlphaPixelFormat ( backend : : PixelFormat : : RGBA4 ) ;
2021-12-25 10:04:45 +08:00
else if ( pixel_format = = " rgba5551 " )
2019-11-23 20:27:39 +08:00
Texture2D : : setDefaultAlphaPixelFormat ( backend : : PixelFormat : : RGB5A1 ) ;
2022-04-23 17:45:07 +08:00
// !!!NEW since adxe 1.0b6, all compressed image should do PMA at texture convert tools(such as astcenc-2.3+ with -pp-premultiply) or GPU fragment shader
bool compressed_image_has_pma = conf - > getValue ( " adxe.texture.compressed_image_has_pma " , Value { true } ) . asBool ( ) ;
Image : : setCompressedImagesHavePMA ( Image : : CompressedImagePMAFlag : : ALL , compressed_image_has_pma ) ;
2019-11-23 20:27:39 +08:00
}
void Director : : setGLDefaultValues ( )
{
// This method SHOULD be called only after openGLView_ was initialized
CCASSERT ( _openGLView , " opengl view should not be null " ) ;
_renderer - > setDepthTest ( false ) ;
_renderer - > setDepthCompareFunction ( backend : : CompareFunction : : LESS_EQUAL ) ;
setProjection ( _projection ) ;
}
// Draw the Scene
void Director : : drawScene ( )
{
2021-01-31 22:22:52 +08:00
_renderer - > beginFrame ( ) ;
2019-11-23 20:27:39 +08:00
// calculate "global" dt
calculateDeltaTime ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _openGLView )
{
_openGLView - > pollEvents ( ) ;
}
2021-12-25 10:04:45 +08:00
// tick before glClear: issue #533
2020-09-05 17:12:30 +08:00
if ( ! _paused )
2019-11-23 20:27:39 +08:00
{
_eventDispatcher - > dispatchEvent ( _eventBeforeUpdate ) ;
_scheduler - > update ( _deltaTime ) ;
_eventDispatcher - > dispatchEvent ( _eventAfterUpdate ) ;
}
_renderer - > clear ( ClearFlag : : ALL , _clearColor , 1 , 0 , - 10000.0 ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_eventDispatcher - > dispatchEvent ( _eventBeforeDraw ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
* FIXME : Which bug is this one . It seems that it can ' t be reproduced with v0 .9
*/
if ( _nextScene )
{
setNextScene ( ) ;
}
pushMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _runningScene )
{
# if (CC_USE_PHYSICS || (CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION) || CC_USE_NAVMESH)
_runningScene - > stepPhysicsAndNavigation ( _deltaTime ) ;
# endif
2021-12-25 10:04:45 +08:00
// clear draw stats
2019-11-23 20:27:39 +08:00
_renderer - > clearDrawStats ( ) ;
2021-12-25 10:04:45 +08:00
// render the scene
if ( _openGLView )
2019-11-23 20:27:39 +08:00
_openGLView - > renderScene ( _runningScene , _renderer ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_eventDispatcher - > dispatchEvent ( _eventAfterVisit ) ;
}
// draw the notifications node
if ( _notificationNode )
{
_notificationNode - > visit ( _renderer , Mat4 : : IDENTITY , 0 ) ;
}
updateFrameRate ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _displayStats )
{
# if !CC_STRIP_FPS
showStats ( ) ;
# endif
}
2021-12-25 10:04:45 +08:00
_renderer - > render ( ) ;
2019-11-23 20:27:39 +08:00
_eventDispatcher - > dispatchEvent ( _eventAfterDraw ) ;
popMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
_totalFrames + + ;
// swap buffers
if ( _openGLView )
{
_openGLView - > swapBuffers ( ) ;
}
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_renderer - > endFrame ( ) ;
if ( _displayStats )
{
# if !CC_STRIP_FPS
calculateMPF ( ) ;
# endif
}
}
void Director : : calculateDeltaTime ( )
{
// new delta time. Re-fixed issue #1277
if ( _nextDeltaTimeZero )
{
2021-12-25 10:04:45 +08:00
_deltaTime = 0 ;
2019-11-23 20:27:39 +08:00
_nextDeltaTimeZero = false ;
2021-12-25 10:04:45 +08:00
_lastUpdate = std : : chrono : : steady_clock : : now ( ) ;
2019-11-23 20:27:39 +08:00
}
else
{
// delta time may passed by invoke mainLoop(dt)
if ( ! _deltaTimePassedByCaller )
{
2021-12-25 10:04:45 +08:00
auto now = std : : chrono : : steady_clock : : now ( ) ;
_deltaTime = std : : chrono : : duration_cast < std : : chrono : : microseconds > ( now - _lastUpdate ) . count ( ) / 1000000.0f ;
2019-11-23 20:27:39 +08:00
_lastUpdate = now ;
}
_deltaTime = MAX ( 0 , _deltaTime ) ;
}
# if COCOS2D_DEBUG
// If we are debugging our code, prevent big delta time
if ( _deltaTime > 0.2f )
{
_deltaTime = 1 / 60.0f ;
}
# endif
}
float Director : : getDeltaTime ( ) const
{
return _deltaTime ;
}
2021-12-25 10:04:45 +08:00
void Director : : setOpenGLView ( GLView * openGLView )
2019-11-23 20:27:39 +08:00
{
CCASSERT ( openGLView , " opengl view should not be null " ) ;
if ( _openGLView ! = openGLView )
{
// Configuration. Gather GPU info
2021-12-25 10:04:45 +08:00
Configuration * conf = Configuration : : getInstance ( ) ;
2019-11-23 20:27:39 +08:00
conf - > gatherGPUInfo ( ) ;
2021-12-25 10:04:45 +08:00
CCLOG ( " %s \n " , conf - > getInfo ( ) . c_str ( ) ) ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
if ( _openGLView )
2019-11-23 20:27:39 +08:00
_openGLView - > release ( ) ;
_openGLView = openGLView ;
_openGLView - > retain ( ) ;
// set size
_winSizeInPoints = _openGLView - > getDesignResolutionSize ( ) ;
_isStatusLabelUpdated = true ;
2020-09-21 22:10:50 +08:00
_renderer - > init ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _openGLView )
{
setGLDefaultValues ( ) ;
}
if ( _eventDispatcher )
{
_eventDispatcher - > setEnabled ( true ) ;
}
}
}
TextureCache * Director : : getTextureCache ( ) const
{
return _textureCache ;
}
void Director : : initTextureCache ( )
{
2021-12-08 00:11:53 +08:00
_textureCache = new TextureCache ( ) ;
2019-11-23 20:27:39 +08:00
}
void Director : : destroyTextureCache ( )
{
if ( _textureCache )
{
_textureCache - > waitForQuit ( ) ;
CC_SAFE_RELEASE_NULL ( _textureCache ) ;
}
}
void Director : : setViewport ( )
{
if ( _openGLView )
{
_openGLView - > setViewPortInPoints ( 0 , 0 , _winSizeInPoints . width , _winSizeInPoints . height ) ;
}
}
void Director : : setNextDeltaTimeZero ( bool nextDeltaTimeZero )
{
_nextDeltaTimeZero = nextDeltaTimeZero ;
}
//
// FIXME TODO
// Matrix code MUST NOT be part of the Director
// MUST BE moved outside.
// Why the Director must have this code ?
//
void Director : : initMatrixStack ( )
{
while ( ! _modelViewMatrixStack . empty ( ) )
{
_modelViewMatrixStack . pop ( ) ;
}
while ( ! _projectionMatrixStack . empty ( ) )
{
2021-12-25 10:04:45 +08:00
_projectionMatrixStack . pop ( ) ;
2019-11-23 20:27:39 +08:00
}
while ( ! _textureMatrixStack . empty ( ) )
{
_textureMatrixStack . pop ( ) ;
}
_modelViewMatrixStack . push ( Mat4 : : IDENTITY ) ;
_projectionMatrixStack . push ( Mat4 : : IDENTITY ) ;
_textureMatrixStack . push ( Mat4 : : IDENTITY ) ;
}
void Director : : resetMatrixStack ( )
{
initMatrixStack ( ) ;
}
void Director : : popMatrix ( MATRIX_STACK_TYPE type )
{
2021-12-25 10:04:45 +08:00
if ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW = = type )
2019-11-23 20:27:39 +08:00
{
_modelViewMatrixStack . pop ( ) ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION = = type )
2019-11-23 20:27:39 +08:00
{
_projectionMatrixStack . pop ( ) ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE = = type )
2019-11-23 20:27:39 +08:00
{
_textureMatrixStack . pop ( ) ;
}
else
{
CCASSERT ( false , " unknown matrix stack type " ) ;
}
}
void Director : : loadIdentityMatrix ( MATRIX_STACK_TYPE type )
{
2021-12-25 10:04:45 +08:00
if ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW = = type )
2019-11-23 20:27:39 +08:00
{
_modelViewMatrixStack . top ( ) = Mat4 : : IDENTITY ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION = = type )
2019-11-23 20:27:39 +08:00
{
_projectionMatrixStack . top ( ) = Mat4 : : IDENTITY ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE = = type )
2019-11-23 20:27:39 +08:00
{
_textureMatrixStack . top ( ) = Mat4 : : IDENTITY ;
}
else
{
CCASSERT ( false , " unknown matrix stack type " ) ;
}
}
void Director : : loadMatrix ( MATRIX_STACK_TYPE type , const Mat4 & mat )
{
2021-12-25 10:04:45 +08:00
if ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW = = type )
2019-11-23 20:27:39 +08:00
{
_modelViewMatrixStack . top ( ) = mat ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION = = type )
2019-11-23 20:27:39 +08:00
{
_projectionMatrixStack . top ( ) = mat ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE = = type )
2019-11-23 20:27:39 +08:00
{
_textureMatrixStack . top ( ) = mat ;
}
else
{
CCASSERT ( false , " unknown matrix stack type " ) ;
}
}
void Director : : multiplyMatrix ( MATRIX_STACK_TYPE type , const Mat4 & mat )
{
2021-12-25 10:04:45 +08:00
if ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW = = type )
2019-11-23 20:27:39 +08:00
{
_modelViewMatrixStack . top ( ) * = mat ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION = = type )
2019-11-23 20:27:39 +08:00
{
_projectionMatrixStack . top ( ) * = mat ;
}
2021-12-25 10:04:45 +08:00
else if ( MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE = = type )
2019-11-23 20:27:39 +08:00
{
_textureMatrixStack . top ( ) * = mat ;
}
else
{
CCASSERT ( false , " unknown matrix stack type " ) ;
}
}
void Director : : pushMatrix ( MATRIX_STACK_TYPE type )
{
2021-12-25 10:04:45 +08:00
if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW )
2019-11-23 20:27:39 +08:00
{
_modelViewMatrixStack . push ( _modelViewMatrixStack . top ( ) ) ;
}
2021-12-25 10:04:45 +08:00
else if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION )
2019-11-23 20:27:39 +08:00
{
_projectionMatrixStack . push ( _projectionMatrixStack . top ( ) ) ;
}
2021-12-25 10:04:45 +08:00
else if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE )
2019-11-23 20:27:39 +08:00
{
_textureMatrixStack . push ( _textureMatrixStack . top ( ) ) ;
}
else
{
CCASSERT ( false , " unknown matrix stack type " ) ;
}
}
const Mat4 & Director : : getMatrix ( MATRIX_STACK_TYPE type ) const
{
2021-12-25 10:04:45 +08:00
if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW )
2019-11-23 20:27:39 +08:00
{
return _modelViewMatrixStack . top ( ) ;
}
2021-12-25 10:04:45 +08:00
else if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION )
2019-11-23 20:27:39 +08:00
{
return _projectionMatrixStack . top ( ) ;
}
2021-12-25 10:04:45 +08:00
else if ( type = = MATRIX_STACK_TYPE : : MATRIX_STACK_TEXTURE )
2019-11-23 20:27:39 +08:00
{
return _textureMatrixStack . top ( ) ;
}
CCASSERT ( false , " unknown matrix stack type, will return modelview matrix instead " ) ;
2021-12-25 10:04:45 +08:00
return _modelViewMatrixStack . top ( ) ;
2019-11-23 20:27:39 +08:00
}
void Director : : setProjection ( Projection projection )
{
2021-10-23 23:27:14 +08:00
Vec2 size = _winSizeInPoints ;
2019-11-23 20:27:39 +08:00
if ( size . width = = 0 | | size . height = = 0 )
{
CCLOGERROR ( " cocos2d: warning, Director::setProjection() failed because size is 0 " ) ;
return ;
}
setViewport ( ) ;
switch ( projection )
{
2021-12-25 10:04:45 +08:00
case Projection : : _2D :
{
Mat4 orthoMatrix ;
Mat4 : : createOrthographicOffCenter ( 0 , size . width , 0 , size . height , - 1024 , 1024 , & orthoMatrix ) ;
loadMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION , orthoMatrix ) ;
loadIdentityMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
break ;
}
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
case Projection : : _3D :
{
float zeye = this - > getZEye ( ) ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
Mat4 matrixPerspective , matrixLookup ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
// issue #1334
Mat4 : : createPerspective ( 60 , ( float ) size . width / size . height , 10 , zeye + size . height / 2 , & matrixPerspective ) ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
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 ) ;
Mat4 : : createLookAt ( eye , center , up , & matrixLookup ) ;
Mat4 proj3d = matrixPerspective * matrixLookup ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
loadMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION , proj3d ) ;
loadIdentityMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
break ;
}
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
case Projection : : CUSTOM :
// Projection Delegate is no longer needed
// since the event "PROJECTION CHANGED" is emitted
break ;
default :
CCLOG ( " cocos2d: Director: unrecognized projection " ) ;
break ;
2019-11-23 20:27:39 +08:00
}
_projection = projection ;
_eventDispatcher - > dispatchEvent ( _eventProjectionChanged ) ;
}
void Director : : purgeCachedData ( )
{
FontFNT : : purgeCachedData ( ) ;
FontAtlasCache : : purgeCachedData ( ) ;
if ( s_SharedDirector - > getOpenGLView ( ) )
{
SpriteFrameCache : : getInstance ( ) - > removeUnusedSpriteFrames ( ) ;
_textureCache - > removeUnusedTextures ( ) ;
// Note: some tests such as ActionsTest are leaking refcounted textures
// There should be no test textures left in the cache
log ( " %s \n " , _textureCache - > getCachedTextureInfo ( ) . c_str ( ) ) ;
}
FileUtils : : getInstance ( ) - > purgeCachedEntries ( ) ;
}
float Director : : getZEye ( ) const
{
2021-12-25 10:04:45 +08:00
return ( _winSizeInPoints . height / 1.154700538379252f ) ; //(2 * tanf(M_PI/6))
2019-11-23 20:27:39 +08:00
}
void Director : : setClearColor ( const Color4F & clearColor )
{
_clearColor = clearColor ;
}
2021-12-25 10:04:45 +08:00
static void GLToClipTransform ( Mat4 * transformOut )
2019-11-23 20:27:39 +08:00
{
2021-12-25 10:04:45 +08:00
if ( nullptr = = transformOut )
return ;
2019-11-23 20:27:39 +08:00
Director * director = Director : : getInstance ( ) ;
CCASSERT ( nullptr ! = director , " Director is null when setting matrix stack " ) ;
2020-08-28 15:01:25 +08:00
auto & projection = director - > getMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION ) ;
2021-12-25 10:04:45 +08:00
auto & modelview = director - > getMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
* transformOut = projection * modelview ;
2019-11-23 20:27:39 +08:00
}
Vec2 Director : : convertToGL ( const Vec2 & uiPoint )
{
Mat4 transform ;
GLToClipTransform ( & transform ) ;
Mat4 transformInv = transform . getInversed ( ) ;
// Calculate z=0 using -> transform*[0, 0, 0, 1]/w
2021-12-25 10:04:45 +08:00
float zClip = transform . m [ 14 ] / transform . m [ 15 ] ;
2019-11-23 20:27:39 +08:00
2021-10-23 23:27:14 +08:00
Vec2 glSize = _openGLView - > getDesignResolutionSize ( ) ;
2021-12-25 10:04:45 +08:00
Vec4 clipCoord ( 2.0f * uiPoint . x / glSize . width - 1.0f , 1.0f - 2.0f * uiPoint . y / glSize . height , zClip , 1 ) ;
2019-11-23 20:27:39 +08:00
Vec4 glCoord ;
2021-12-25 10:04:45 +08:00
// transformInv.transformPoint(clipCoord, &glCoord);
2019-11-23 20:27:39 +08:00
transformInv . transformVector ( clipCoord , & glCoord ) ;
float factor = 1.0f / glCoord . w ;
return Vec2 ( glCoord . x * factor , glCoord . y * factor ) ;
}
Vec2 Director : : convertToUI ( const Vec2 & glPoint )
{
Mat4 transform ;
GLToClipTransform ( & transform ) ;
Vec4 clipCoord ;
// Need to calculate the zero depth from the transform.
Vec4 glCoord ( glPoint . x , glPoint . y , 0.0 , 1 ) ;
transform . transformVector ( glCoord , & clipCoord ) ;
2021-12-25 10:04:45 +08:00
/*
BUG - FIX # 5506
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
a = ( Vx , Vy , Vz , 1 )
b = ( a × M ) T
Out = 1 ⁄ bw ( bx , by , bz )
*/
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
clipCoord . x = clipCoord . x / clipCoord . w ;
clipCoord . y = clipCoord . y / clipCoord . w ;
clipCoord . z = clipCoord . z / clipCoord . w ;
Vec2 glSize = _openGLView - > getDesignResolutionSize ( ) ;
2019-11-23 20:27:39 +08:00
float factor = 1.0f / glCoord . w ;
2021-12-25 10:04:45 +08:00
return Vec2 ( glSize . width * ( clipCoord . x * 0.5f + 0.5f ) * factor ,
glSize . height * ( - clipCoord . y * 0.5f + 0.5f ) * factor ) ;
2019-11-23 20:27:39 +08:00
}
2021-10-23 23:27:14 +08:00
const Vec2 & Director : : getWinSize ( ) const
2019-11-23 20:27:39 +08:00
{
return _winSizeInPoints ;
}
2021-10-23 23:27:14 +08:00
Vec2 Director : : getWinSizeInPixels ( ) const
2019-11-23 20:27:39 +08:00
{
2021-10-23 23:27:14 +08:00
return Vec2 ( _winSizeInPoints . width * _contentScaleFactor , _winSizeInPoints . height * _contentScaleFactor ) ;
2019-11-23 20:27:39 +08:00
}
2021-10-23 23:27:14 +08:00
Vec2 Director : : getVisibleSize ( ) const
2019-11-23 20:27:39 +08:00
{
if ( _openGLView )
{
return _openGLView - > getVisibleSize ( ) ;
}
else
{
2021-10-23 23:27:14 +08:00
return Vec2 : : ZERO ;
2019-11-23 20:27:39 +08:00
}
}
Vec2 Director : : getVisibleOrigin ( ) const
{
if ( _openGLView )
{
return _openGLView - > getVisibleOrigin ( ) ;
}
else
{
return Vec2 : : ZERO ;
}
}
Rect Director : : getSafeAreaRect ( ) const
{
if ( _openGLView )
{
return _openGLView - > getSafeAreaRect ( ) ;
}
else
{
return Rect : : ZERO ;
}
}
// scene management
2021-12-25 10:04:45 +08:00
void Director : : runWithScene ( Scene * scene )
2019-11-23 20:27:39 +08:00
{
2021-12-25 10:04:45 +08:00
CCASSERT ( scene ! = nullptr ,
" This command can only be used to start the Director. There is already a scene present. " ) ;
2019-11-23 20:27:39 +08:00
CCASSERT ( _runningScene = = nullptr , " _runningScene should be null " ) ;
pushScene ( scene ) ;
startAnimation ( ) ;
}
2021-12-25 10:04:45 +08:00
void Director : : replaceScene ( Scene * scene )
2019-11-23 20:27:39 +08:00
{
2021-12-25 10:04:45 +08:00
// CCASSERT(_runningScene, "Use runWithScene: instead to start the director");
2019-11-23 20:27:39 +08:00
CCASSERT ( scene ! = nullptr , " the scene should not be null " ) ;
2021-12-25 10:04:45 +08:00
if ( _runningScene = = nullptr )
{
2019-11-23 20:27:39 +08:00
runWithScene ( scene ) ;
return ;
}
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( scene = = _nextScene )
return ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _nextScene )
{
if ( _nextScene - > isRunning ( ) )
{
_nextScene - > onExit ( ) ;
}
_nextScene - > cleanup ( ) ;
_nextScene = nullptr ;
}
ssize_t index = _scenesStack . size ( ) - 1 ;
_sendCleanupToScene = true ;
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
if ( sEngine )
{
sEngine - > retainScriptObject ( this , scene ) ;
sEngine - > releaseScriptObject ( this , _scenesStack . at ( index ) ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_scenesStack . replace ( index , scene ) ;
_nextScene = scene ;
}
2021-12-25 10:04:45 +08:00
void Director : : pushScene ( Scene * scene )
2019-11-23 20:27:39 +08:00
{
CCASSERT ( scene , " the scene should not null " ) ;
_sendCleanupToScene = false ;
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
if ( sEngine )
{
sEngine - > retainScriptObject ( this , scene ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_scenesStack . pushBack ( scene ) ;
_nextScene = scene ;
}
void Director : : popScene ( )
{
CCASSERT ( _runningScene ! = nullptr , " running scene should not null " ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
if ( sEngine )
{
sEngine - > releaseScriptObject ( this , _scenesStack . back ( ) ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_scenesStack . popBack ( ) ;
ssize_t c = _scenesStack . size ( ) ;
if ( c = = 0 )
{
end ( ) ;
}
else
{
_sendCleanupToScene = true ;
2021-12-25 10:04:45 +08:00
_nextScene = _scenesStack . at ( c - 1 ) ;
2019-11-23 20:27:39 +08:00
}
}
void Director : : popToRootScene ( )
{
popToSceneStackLevel ( 1 ) ;
}
void Director : : popToSceneStackLevel ( int level )
{
CCASSERT ( _runningScene ! = nullptr , " A running Scene is needed " ) ;
ssize_t c = _scenesStack . size ( ) ;
// level 0? -> end
if ( level = = 0 )
{
end ( ) ;
return ;
}
// current level or lower -> nothing
if ( level > = c )
return ;
auto firstOnStackScene = _scenesStack . back ( ) ;
if ( firstOnStackScene = = _runningScene )
{
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
if ( sEngine )
{
sEngine - > releaseScriptObject ( this , _scenesStack . back ( ) ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_scenesStack . popBack ( ) ;
- - c ;
}
// pop stack until reaching desired level
while ( c > level )
{
auto current = _scenesStack . back ( ) ;
if ( current - > isRunning ( ) )
{
current - > onExit ( ) ;
}
current - > cleanup ( ) ;
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
if ( sEngine )
{
sEngine - > releaseScriptObject ( this , _scenesStack . back ( ) ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_scenesStack . popBack ( ) ;
- - c ;
}
_nextScene = _scenesStack . back ( ) ;
// cleanup running scene
_sendCleanupToScene = true ;
}
void Director : : end ( )
{
_purgeDirectorInNextLoop = true ;
}
void Director : : restart ( )
{
_restartDirectorInNextLoop = true ;
}
void Director : : reset ( )
{
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) ;
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
if ( _runningScene )
{
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
if ( sEngine )
{
sEngine - > releaseScriptObject ( this , _runningScene ) ;
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
_runningScene - > onExit ( ) ;
_runningScene - > cleanup ( ) ;
_runningScene - > release ( ) ;
}
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_runningScene = nullptr ;
2021-12-25 10:04:45 +08:00
_nextScene = nullptr ;
2019-11-23 20:27:39 +08:00
if ( _eventDispatcher )
_eventDispatcher - > dispatchEvent ( _eventResetDirector ) ;
2021-12-15 16:56:08 +08:00
// Fix github issue: https://github.com/adxeproject/adxe/issues/550
// !!!The AudioEngine hold scheduler must end before Director destroyed, otherwise, just lead app crash
AudioEngine : : end ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// cleanup scheduler
getScheduler ( ) - > unscheduleAll ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// Remove all events
if ( _eventDispatcher )
{
_eventDispatcher - > removeAllEventListeners ( ) ;
}
2021-12-25 10:04:45 +08:00
if ( _notificationNode )
2019-11-23 20:27:39 +08:00
{
_notificationNode - > onExit ( ) ;
_notificationNode - > cleanup ( ) ;
_notificationNode - > release ( ) ;
}
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_notificationNode = nullptr ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// remove all objects, but don't release it.
// runWithScene might be executed after 'end'.
# if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
if ( sEngine )
{
2021-12-25 10:04:45 +08:00
for ( const auto & scene : _scenesStack )
2019-11-23 20:27:39 +08:00
{
if ( scene )
sEngine - > releaseScriptObject ( this , scene ) ;
}
}
2021-12-25 10:04:45 +08:00
# endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
2019-11-23 20:27:39 +08:00
while ( ! _scenesStack . empty ( ) )
{
_scenesStack . popBack ( ) ;
}
stopAnimation ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
CC_SAFE_RELEASE_NULL ( _notificationNode ) ;
CC_SAFE_RELEASE_NULL ( _FPSLabel ) ;
CC_SAFE_RELEASE_NULL ( _drawnBatchesLabel ) ;
CC_SAFE_RELEASE_NULL ( _drawnVerticesLabel ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// purge bitmap cache
FontFNT : : purgeCachedData ( ) ;
FontAtlasCache : : purgeCachedData ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
FontFreeType : : shutdownFreeType ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// purge all managed caches
AnimationCache : : destroyInstance ( ) ;
SpriteFrameCache : : destroyInstance ( ) ;
FileUtils : : destroyInstance ( ) ;
AsyncTaskPool : : destroyInstance ( ) ;
backend : : ProgramCache : : destroyInstance ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// cocos2d-x specific data structures
UserDefault : : destroyInstance ( ) ;
resetMatrixStack ( ) ;
destroyTextureCache ( ) ;
}
void Director : : purgeDirector ( )
{
reset ( ) ;
2021-12-25 10:04:45 +08:00
// CHECK_GL_ERROR_DEBUG();
2019-11-23 20:27:39 +08:00
// OpenGL view
if ( _openGLView )
{
_openGLView - > end ( ) ;
_openGLView = nullptr ;
}
// delete Director
release ( ) ;
}
void Director : : restartDirector ( )
{
reset ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// Texture cache need to be reinitialized
initTextureCache ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// Reschedule for action manager
getScheduler ( ) - > scheduleUpdate ( getActionManager ( ) , Scheduler : : PRIORITY_SYSTEM , false ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// release the objects
PoolManager : : getInstance ( ) - > getCurrentPool ( ) - > clear ( ) ;
// Restart animation
startAnimation ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// Real restart in script level
# if CC_ENABLE_SCRIPT_BINDING
ScriptEvent scriptEvent ( kRestartGame , nullptr ) ;
2020-02-24 23:08:47 +08:00
ScriptEngineManager : : sendEventToLua ( scriptEvent ) ;
2019-11-23 20:27:39 +08:00
# endif
2021-12-25 10:04:45 +08:00
2021-11-15 17:49:46 +08:00
setGLDefaultValues ( ) ;
2019-11-23 20:27:39 +08:00
}
void Director : : setNextScene ( )
{
_eventDispatcher - > dispatchEvent ( _beforeSetNextScene ) ;
bool runningIsTransition = dynamic_cast < TransitionScene * > ( _runningScene ) ! = nullptr ;
2021-12-25 10:04:45 +08:00
bool newIsTransition = dynamic_cast < TransitionScene * > ( _nextScene ) ! = nullptr ;
2019-11-23 20:27:39 +08:00
// If it is not a transition, call onExit/cleanup
2021-12-25 10:04:45 +08:00
if ( ! newIsTransition )
{
if ( _runningScene )
{
_runningScene - > onExitTransitionDidStart ( ) ;
_runningScene - > onExit ( ) ;
}
// issue #709. the root node (scene) should receive the cleanup message too
// otherwise it might be leaked.
if ( _sendCleanupToScene & & _runningScene )
{
_runningScene - > cleanup ( ) ;
}
}
2019-11-23 20:27:39 +08:00
if ( _runningScene )
{
_runningScene - > release ( ) ;
}
_runningScene = _nextScene ;
_nextScene - > retain ( ) ;
_nextScene = nullptr ;
2021-12-25 10:04:45 +08:00
if ( ( ! runningIsTransition ) & & _runningScene )
2019-11-23 20:27:39 +08:00
{
_runningScene - > onEnter ( ) ;
_runningScene - > onEnterTransitionDidFinish ( ) ;
}
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
_eventDispatcher - > dispatchEvent ( _afterSetNextScene ) ;
}
void Director : : pause ( )
{
if ( _paused )
{
return ;
}
_oldAnimationInterval = _animationInterval ;
2020-09-05 17:12:30 +08:00
# if CC_REDUCE_PAUSED_CPU_USAGE
2019-11-23 20:27:39 +08:00
// when paused, don't consume CPU
setAnimationInterval ( 1 / 4.0 , SetIntervalReason : : BY_DIRECTOR_PAUSE ) ;
2020-09-05 17:12:30 +08:00
# endif
2019-11-23 20:27:39 +08:00
_paused = true ;
}
void Director : : resume ( )
{
2021-12-25 10:04:45 +08:00
if ( ! _paused )
2019-11-23 20:27:39 +08:00
{
return ;
}
2020-09-05 17:12:30 +08:00
# if CC_REDUCE_PAUSED_CPU_USAGE
2019-11-23 20:27:39 +08:00
setAnimationInterval ( _oldAnimationInterval , SetIntervalReason : : BY_ENGINE ) ;
2020-09-05 17:12:30 +08:00
# endif
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
_paused = false ;
2019-11-23 20:27:39 +08:00
_deltaTime = 0 ;
// fix issue #3509, skip one fps to avoid incorrect time calculation.
setNextDeltaTimeZero ( true ) ;
}
void Director : : updateFrameRate ( )
{
2021-12-25 10:04:45 +08:00
// static const float FPS_FILTER = 0.1f;
// static float prevDeltaTime = 0.016f; // 60FPS
//
// float dt = _deltaTime * FPS_FILTER + (1.0f-FPS_FILTER) * prevDeltaTime;
// prevDeltaTime = dt;
// _frameRate = 1.0f/dt;
2019-11-23 20:27:39 +08:00
// Frame rate should be the real value of current frame.
_frameRate = 1.0f / _deltaTime ;
}
# if !CC_STRIP_FPS
// display the FPS using a LabelAtlas
// updates the FPS every frame
void Director : : showStats ( )
{
if ( _isStatusLabelUpdated )
{
createStatsLabel ( ) ;
_isStatusLabelUpdated = false ;
}
2021-09-05 20:45:32 +08:00
static uint32_t prevCalls = 0 ;
static uint32_t prevVerts = 0 ;
2019-11-23 20:27:39 +08:00
+ + _frames ;
_accumDt + = _deltaTime ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
if ( _displayStats & & _FPSLabel & & _drawnBatchesLabel & & _drawnVerticesLabel )
{
char buffer [ 30 ] = { 0 } ;
// Probably we don't need this anymore since
// the framerate is using a low-pass filter
// to make the FPS stable
if ( _accumDt > CC_DIRECTOR_STATS_INTERVAL )
{
sprintf ( buffer , " %.1f / %.3f " , _frames / _accumDt , _secondsPerFrame ) ;
_FPSLabel - > setString ( buffer ) ;
_accumDt = 0 ;
2021-12-25 10:04:45 +08:00
_frames = 0 ;
2019-11-23 20:27:39 +08:00
}
2021-09-05 20:45:32 +08:00
auto currentCalls = ( uint32_t ) _renderer - > getDrawnBatches ( ) ;
auto currentVerts = ( uint32_t ) _renderer - > getDrawnVertices ( ) ;
2021-12-25 10:04:45 +08:00
if ( currentCalls ! = prevCalls )
{
2021-10-09 13:48:56 +08:00
sprintf ( buffer , " GL calls:%6u " , currentCalls ) ;
2019-11-23 20:27:39 +08:00
_drawnBatchesLabel - > setString ( buffer ) ;
prevCalls = currentCalls ;
}
2021-12-25 10:04:45 +08:00
if ( currentVerts ! = prevVerts )
{
2021-10-09 13:48:56 +08:00
sprintf ( buffer , " GL verts:%6u " , currentVerts ) ;
2019-11-23 20:27:39 +08:00
_drawnVerticesLabel - > setString ( buffer ) ;
prevVerts = currentVerts ;
}
const Mat4 & identity = Mat4 : : IDENTITY ;
_drawnVerticesLabel - > visit ( _renderer , identity , 0 ) ;
_drawnBatchesLabel - > visit ( _renderer , identity , 0 ) ;
_FPSLabel - > visit ( _renderer , identity , 0 ) ;
}
}
void Director : : calculateMPF ( )
{
static float prevSecondsPerFrame = 0 ;
2021-12-25 10:04:45 +08:00
static const float MPF_FILTER = 0.10f ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
_secondsPerFrame = _deltaTime * MPF_FILTER + ( 1 - MPF_FILTER ) * prevSecondsPerFrame ;
2019-11-23 20:27:39 +08:00
prevSecondsPerFrame = _secondsPerFrame ;
}
// returns the FPS image data pointer and len
void Director : : getFPSImageData ( unsigned char * * datapointer , ssize_t * length )
{
2021-12-25 10:04:45 +08:00
// FIXME: fixed me if it should be used
2019-11-23 20:27:39 +08:00
* datapointer = cc_fps_images_png ;
2021-12-25 10:04:45 +08:00
* length = cc_fps_images_len ( ) ;
2019-11-23 20:27:39 +08:00
}
void Director : : createStatsLabel ( )
{
2021-12-25 10:04:45 +08:00
Texture2D * texture = nullptr ;
std : : string fpsString = " 00.0 " ;
std : : string drawBatchString = " 000 " ;
2019-11-23 20:27:39 +08:00
std : : string drawVerticesString = " 00000 " ;
if ( _FPSLabel )
{
2021-12-25 10:04:45 +08:00
fpsString = _FPSLabel - > getString ( ) ;
drawBatchString = _drawnBatchesLabel - > getString ( ) ;
2019-11-23 20:27:39 +08:00
drawVerticesString = _drawnVerticesLabel - > getString ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
CC_SAFE_RELEASE_NULL ( _FPSLabel ) ;
CC_SAFE_RELEASE_NULL ( _drawnBatchesLabel ) ;
CC_SAFE_RELEASE_NULL ( _drawnVerticesLabel ) ;
_textureCache - > removeTextureForKey ( " /cc_fps_images " ) ;
FileUtils : : getInstance ( ) - > purgeCachedEntries ( ) ;
}
backend : : PixelFormat currentFormat = Texture2D : : getDefaultAlphaPixelFormat ( ) ;
2020-09-25 11:07:56 +08:00
Texture2D : : setDefaultAlphaPixelFormat ( backend : : PixelFormat : : RGBA4 ) ;
2021-12-25 10:04:45 +08:00
unsigned char * data = nullptr ;
ssize_t dataLength = 0 ;
2019-11-23 20:27:39 +08:00
getFPSImageData ( & data , & dataLength ) ;
2021-12-08 00:11:53 +08:00
Image * image = new Image ( ) ;
2021-12-25 10:04:45 +08:00
bool isOK = image - > initWithImageData ( data , dataLength , false ) ;
if ( ! isOK )
{
if ( image )
2019-11-23 20:27:39 +08:00
delete image ;
CCLOGERROR ( " %s " , " Fails: init fps_images " ) ;
return ;
}
texture = _textureCache - > addImage ( image , " /cc_fps_images " ) ;
CC_SAFE_RELEASE ( image ) ;
/*
2021-12-25 10:04:45 +08:00
We want to use an image which is stored in the file named ccFPSImage . c
for any design resolutions and all resource resolutions .
2019-11-23 20:27:39 +08:00
To achieve this , we need to ignore ' contentScaleFactor ' in ' AtlasNode ' and ' LabelAtlas ' .
So I added a new method called ' setIgnoreContentScaleFactor ' for ' AtlasNode ' ,
this is not exposed to game developers , it ' s only used for displaying FPS now .
*/
float scaleFactor = 1 / CC_CONTENT_SCALE_FACTOR ( ) ;
2020-09-09 15:29:56 +08:00
_FPSLabel = LabelAtlas : : create ( fpsString , texture , 12 , 32 , ' . ' ) ;
2019-11-23 20:27:39 +08:00
_FPSLabel - > retain ( ) ;
_FPSLabel - > setIgnoreContentScaleFactor ( true ) ;
_FPSLabel - > setScale ( scaleFactor ) ;
2020-09-09 15:29:56 +08:00
_drawnBatchesLabel = LabelAtlas : : create ( drawBatchString , texture , 12 , 32 , ' . ' ) ;
2019-11-23 20:27:39 +08:00
_drawnBatchesLabel - > retain ( ) ;
_drawnBatchesLabel - > setIgnoreContentScaleFactor ( true ) ;
_drawnBatchesLabel - > setScale ( scaleFactor ) ;
2020-09-09 15:29:56 +08:00
_drawnVerticesLabel = LabelAtlas : : create ( drawVerticesString , texture , 12 , 32 , ' . ' ) ;
2019-11-23 20:27:39 +08:00
_drawnVerticesLabel - > retain ( ) ;
_drawnVerticesLabel - > setIgnoreContentScaleFactor ( true ) ;
_drawnVerticesLabel - > setScale ( scaleFactor ) ;
Texture2D : : setDefaultAlphaPixelFormat ( currentFormat ) ;
2021-12-25 10:04:45 +08:00
auto safeOrigin = getSafeAreaRect ( ) . origin ;
2019-11-23 20:27:39 +08:00
const int height_spacing = ( int ) ( 22 / CC_CONTENT_SCALE_FACTOR ( ) ) ;
2021-12-25 10:04:45 +08:00
_drawnVerticesLabel - > setPosition ( Vec2 ( 0 , height_spacing * 2.0f ) + safeOrigin ) ;
_drawnBatchesLabel - > setPosition ( Vec2 ( 0 , height_spacing * 1.0f ) + safeOrigin ) ;
2021-10-09 14:45:49 +08:00
_FPSLabel - > setPosition ( Vec2 ( 0 , height_spacing * 0.0f ) + safeOrigin ) ;
2019-11-23 20:27:39 +08:00
}
2021-12-25 10:04:45 +08:00
# endif // #if !CC_STRIP_FPS
2019-11-23 20:27:39 +08:00
void Director : : setContentScaleFactor ( float scaleFactor )
{
if ( scaleFactor ! = _contentScaleFactor )
{
2021-12-25 10:04:45 +08:00
_contentScaleFactor = scaleFactor ;
2019-11-23 20:27:39 +08:00
_isStatusLabelUpdated = true ;
}
}
2021-12-25 10:04:45 +08:00
void Director : : setNotificationNode ( Node * node )
2019-11-23 20:27:39 +08:00
{
2021-12-25 10:04:45 +08:00
if ( _notificationNode ! = nullptr )
{
_notificationNode - > onExitTransitionDidStart ( ) ;
_notificationNode - > onExit ( ) ;
_notificationNode - > cleanup ( ) ;
}
CC_SAFE_RELEASE ( _notificationNode ) ;
2019-11-23 20:27:39 +08:00
2021-12-25 10:04:45 +08:00
_notificationNode = node ;
if ( node = = nullptr )
return ;
_notificationNode - > onEnter ( ) ;
_notificationNode - > onEnterTransitionDidFinish ( ) ;
2019-11-23 20:27:39 +08:00
CC_SAFE_RETAIN ( _notificationNode ) ;
}
void Director : : setScheduler ( Scheduler * scheduler )
{
if ( _scheduler ! = scheduler )
{
CC_SAFE_RETAIN ( scheduler ) ;
CC_SAFE_RELEASE ( _scheduler ) ;
_scheduler = scheduler ;
}
}
void Director : : setActionManager ( ActionManager * actionManager )
{
if ( _actionManager ! = actionManager )
{
CC_SAFE_RETAIN ( actionManager ) ;
CC_SAFE_RELEASE ( _actionManager ) ;
_actionManager = actionManager ;
2021-12-25 10:04:45 +08:00
}
2019-11-23 20:27:39 +08:00
}
void Director : : setEventDispatcher ( EventDispatcher * dispatcher )
{
if ( _eventDispatcher ! = dispatcher )
{
CC_SAFE_RETAIN ( dispatcher ) ;
CC_SAFE_RELEASE ( _eventDispatcher ) ;
_eventDispatcher = dispatcher ;
}
}
void Director : : startAnimation ( )
{
startAnimation ( SetIntervalReason : : BY_ENGINE ) ;
}
void Director : : startAnimation ( SetIntervalReason reason )
{
_lastUpdate = std : : chrono : : steady_clock : : now ( ) ;
_invalid = false ;
_cocos2d_thread_id = std : : this_thread : : get_id ( ) ;
Application : : getInstance ( ) - > setAnimationInterval ( _animationInterval ) ;
// fix issue #3509, skip one fps to avoid incorrect time calculation.
setNextDeltaTimeZero ( true ) ;
}
void Director : : mainLoop ( )
{
if ( _purgeDirectorInNextLoop )
{
_purgeDirectorInNextLoop = false ;
purgeDirector ( ) ;
}
else if ( _restartDirectorInNextLoop )
{
_restartDirectorInNextLoop = false ;
restartDirector ( ) ;
}
2021-12-25 10:04:45 +08:00
else if ( ! _invalid )
2019-11-23 20:27:39 +08:00
{
drawScene ( ) ;
2021-12-25 10:04:45 +08:00
2019-11-23 20:27:39 +08:00
// release the objects
PoolManager : : getInstance ( ) - > getCurrentPool ( ) - > clear ( ) ;
}
}
void Director : : mainLoop ( float dt )
{
2021-12-25 10:04:45 +08:00
_deltaTime = dt ;
2019-11-23 20:27:39 +08:00
_deltaTimePassedByCaller = true ;
mainLoop ( ) ;
}
void Director : : stopAnimation ( )
{
_invalid = true ;
}
void Director : : setAnimationInterval ( float interval )
{
setAnimationInterval ( interval , SetIntervalReason : : BY_GAME ) ;
}
void Director : : setAnimationInterval ( float interval , SetIntervalReason reason )
{
_animationInterval = interval ;
2021-12-25 10:04:45 +08:00
if ( ! _invalid )
2019-11-23 20:27:39 +08:00
{
stopAnimation ( ) ;
startAnimation ( reason ) ;
}
}
NS_CC_END