三.CCTextureCache:
打开CCTextureCache.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
#ifndef __CCTEXTURE_CACHE_H__
#define __CCTEXTURE_CACHE_H__ //由CCObject派生 #include "cocoa/CCObject.h" //需要用到字典 #include "cocoa/CCDictionary.h" #include "textures/CCTexture2D.h" #include <string> //这里用到CCImage类和STL容器之一list #if CC_ENABLE_CACHE_TEXTURE_DATA #include "platform/CCImage.h" #include <list> #endif //Cocos2d命名空间 NS_CC_BEGIN //用到线程锁 class CCLock ; //用到CCImage处理图片 class CCImage ; //纹理管理器 class CC_DLL CCTextureCache : public CCObject { protected : //字典对象指针。 CCDictionary * m_pTextures ; //线程临界区。用于锁定字典访问,貌似用不到。这里屏蔽了~ //pthread_mutex_t *m_pDictLock; private : // 设置多线程加载图片时的回调函数。 void addImageAsyncCallBack ( float dt ) ; public : //构造函数 CCTextureCache ( ) ; //析构函数 virtual ~CCTextureCache ( ) ; //取得当前类描述 const char * description ( void ) ; //取得当前字典的快照(拷贝) CCDictionary * snapshotTextures ( ) ; //返回唯一纹理管理器的实例指针 static CCTextureCache * sharedTextureCache ( ) ; //销毁唯一纹理管理器的实例指针 static void purgeSharedTextureCache ( ) ; //加载一个图片生成纹理,文件名做为字典的查询对应关键字。返回生成的纹理指针,支持png,bmp,tiff,jpeg,pvr,gif等格式。 CCTexture2D * addImage ( const char * fileimage ) ; //此函数可以支持多线程载入图片,调用时会创建一个线程进行异步加载,加载成功后由主线程调用设置的回调函数,当然创建的纹理会做为参数传递。支持png和jpg void addImageAsync ( const char *path, CCObject *target, SEL_CallFuncO selector ) ; //加载一个图片生成纹理,指定参数key(其实要求是图片的相对路径字符串)做为字典的查询对应关键字。 CCTexture2D * addUIImage (CCImage *image, const char *key ) ; //通过查询关键字(其实要求是图片的相对路径字符串)从字典里找到对应的纹理。 CCTexture2D * textureForKey ( const char * key ) ; //清空字典,释放所有纹理。 void removeAllTextures ( ) ; //清除未被外部使用的纹理。怎么知道未使用呢?因为在Cocos2d-x中使用“引用计数器”来管理各种资源的使用情况,纹理也不例外。在资源类构造时,纹理的计数器值为0,但由CCTextureCache来创建完成后,会对纹理的资源计数器做加1操作以通知纹理说“你现在被我占用呢”。如果纹理被外部使用,应该再次调用其资源计数器做加1操作,退出使用时做减1操作通知其“我现在不用你了”。所以这里只需要遍历下计数器值为1的纹理即未被外部使用的纹理进行释放即可。 void removeUnusedTextures ( ) ; //移除一个纹理 void removeTexture (CCTexture2D * texture ) ; //由字典查询关键字找到相应纹理并移除。 void removeTextureForKey ( const char *textureKeyName ) ; //打印出当前管理的纹理信息,包括现在纹理占用的内存和总的纹理内存。 void dumpCachedTextureInfo ( ) ; #ifdef CC_SUPPORT_PVRTC //如果开启支持PVR的压缩格式,这里提供加载PVR压缩文件生成纹理的函数。 //参1:PVR压缩文件名 //参2:压缩质量参数,只能设为2或4,4比2质量高,但压缩比低。2则相反。 //参3:是否有Alpha通道。这里会根据是否有ALPHA通道以生成相应的默认纹理格式。 //参4:图片必须是2的幂次方大小的正方形,所以这里只需要填写一下宽度,也就是图片大小。 CCTexture2D * addPVRTCImage ( const char * fileimage, int bpp, bool hasAlpha, int width ) ; #endif // CC_SUPPORT_PVRTC //加载普通的PVR图片文件生成纹理。 CCTexture2D * addPVRImage ( const char * filename ) ; //如果CC_ENABLE_CACHE_TEXTURE_DATA宏定义为可用(即值为1),则调用此函数会将所有的纹理都预加载进内存生成相应纹理。 static void reloadAllTextures ( ) ; } ; //如果定义了CC_ENABLE_CACHE_TEXTURE_DATA,这里定义一个新的类 #if CC_ENABLE_CACHE_TEXTURE_DATA //新定义的类名称为VolatileTexture,意思是多变纹理。这里代表了多种数据源生成的纹理的管理器。 class VolatileTexture { //这里声明了一个枚举,代表了多变纹理对应的几种数据源类型 typedef enum { kInvalid = 0, //无效未加载任何数据的状态 kImageFile, //图片文件 kImageData, //内存中的图片数据 kString, //字符串 kImage, //图片对象(CCImage) }ccCachedImageType ; public : //构造 VolatileTexture (CCTexture2D *t ) ; //析构 ~VolatileTexture ( ) ; //静态函数:通过图片文件生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。 static void addImageTexture (CCTexture2D *tt, const char * imageFileName, CCImage :: EImageFormat format ) ; //静态函数:通过字符串生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。 static void addStringTexture (CCTexture2D *tt, const char * text, const CCSize & dimensions, CCTextAlignment alignment, CCVerticalTextAlignment vAlignment, const char *fontName, float fontSize ) ; //通过图片数据生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。 static void addDataTexture (CCTexture2D *tt, void * data, CCTexture2DPixelFormat pixelFormat, const CCSize & contentSize ) ; //通过图片对象生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。 static void addCCImage (CCTexture2D *tt, CCImage *image ) ; //通过纹理指针参数从容器中删除对应的多变纹理 static void removeTexture (CCTexture2D *t ) ; //重新载入所有的纹理 static void reloadAllTextures ( ) ; public : //静态多变纹理指针容器,用来存储所有的多变纹理对象指针。 static std :: list <VolatileTexture * > textures ; //是否正在进行全部重新载入 static bool isReloading ; private : //通过纹理指针参数从容器找到对应的多变纹理对象指针 static VolatileTexture * findVolotileTexture (CCTexture2D *tt ) ; protected : //与当前多变纹理对应的纹理指针 CCTexture2D *texture ; //对应的图片对象 CCImage *uiImage ; //数据源类型 ccCachedImageType m_eCashedImageType ; //纹理数据指针 void *m_pTextureData ; //纹理的实际大小 CCSize m_TextureSize ; //纹理的像素格式 CCTexture2DPixelFormat m_PixelFormat ; //对应的图片名称 std :: string m_strFileName ; //图片的像素格式 CCImage :: EImageFormat m_FmtImage ; //图片的大小 CCSize m_size ; //横向文字的对齐方式 CCTextAlignment m_alignment ; //纵向文字的对齐方式 CCVerticalTextAlignment m_vAlignment ; //字体名称 std :: string m_strFontName ; //文字 std :: string m_strText ; //字体大小 float m_fFontSize ; } ; #endif NS_CC_END #endif //__CCTEXTURE_CACHE_H__ |
然后是CPP文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 |
#include "CCTextureCache.h"
#include "CCTexture2D.h" #include "ccMacros.h" #include "CCDirector.h" #include "platform/platform.h" #include "platform/CCFileUtils.h" #include "platform/CCThread.h" #include "platform/CCImage.h" #include "support/ccUtils.h" #include "CCScheduler.h" #include "cocoa/CCString.h" #include <errno.h> #include <stack> #include <string> #include <cctype> #include <queue> #include <list> #include <pthread.h> #include <semaphore.h> //使用标准库命名空间 using namespace std ; //使用Cocos2d命名空间 NS_CC_BEGIN //异步加载所用的消息结构 typedef struct _AsyncStruct { std :: string filename ; //文件名 CCObject *target ; //调用者 SEL_CallFuncO selector ; //载回完的回调函数 } AsyncStruct ; //图片信息 typedef struct _ImageInfo { AsyncStruct *asyncStruct ; //异步加载消息结构 CCImage *image ; //图片指针 CCImage :: EImageFormat imageType //图片类型 } ImageInfo ; //加载图片的线程 static pthread_t s_loadingThread ; //用于读取异步消息队列的线程临界区 static pthread_mutex_t s_asyncStructQueueMutex ; //用于存储图片信息结构处理的临界区 static pthread_mutex_t s_ImageInfoMutex ; //信号量指针。信号量是当前进程中的多个线程通信的一种方式。 static sem_t * s_pSem = NULL ; //多线程加载图片的数量。 static unsigned long s_nAsyncRefCount = 0 ; //如果是IOS平台,则定义是否使用信号量命名。 #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS #define CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE 1 #else #define CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE 0 #endif //如果使用信号量命名,则定义命名的字符串宏,否则定义静态全局的信号量结构。 #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE #define CC_ASYNC_TEXTURE_CACHE_SEMAPHORE "ccAsync" #else static sem_t s_sem ; #endif //是否在当前加载线程处理完手上的活儿就退出。 static bool need_quit = false ; //异步加载图片的消息结构指针容器,即消息队列。 static std :: queue <AsyncStruct * > * s_pAsyncStructQueue = NULL ; //异步存储图片信息结构指针的容器。 static std :: queue <ImageInfo * > * s_pImageQueue = NULL ; //通过文件扩展名取得图片格式 static CCImage :: EImageFormat computeImageFormatType (string & filename ) { CCImage :: EImageFormat ret = CCImage :: kFmtUnKnown ; //JPG if ( (std :: string :: npos ! = filename. find ( ".jpg" ) ) || (std :: string :: npos ! = filename. find ( ".jpeg" ) ) ) { ret = CCImage :: kFmtJpg ; } //PNG else if ( (std :: string :: npos ! = filename. find ( ".png" ) ) || (std :: string :: npos ! = filename. find ( ".PNG" ) ) ) { ret = CCImage :: kFmtPng ; } //TIFF else if ( (std :: string :: npos ! = filename. find ( ".tiff" ) ) || (std :: string :: npos ! = filename. find ( ".TIFF" ) ) ) { ret = CCImage :: kFmtTiff ; } return ret ; } //加载图片的线程函数 static void * loadImage ( void * data ) { // 创建一个线程信息对象 CCThread thread ; thread. createAutoreleasePool ( ) ; //多线程加载消息结构 AsyncStruct *pAsyncStruct = NULL ; //线程将处理所有随时要进行多线程加载的图片,所以会有一个While循环。 while ( true ) { //当前线程等待信号量变为非零值,并减1。 int semWaitRet = sem_wait (s_pSem ) ; //如果信号量为负值,打印出错信息并中断。 if ( semWaitRet < 0 ) { CCLOG ( "CCTextureCache async thread semaphore error: %s\n", strerror ( errno ) ) ; break ; } //取得全局的异步加载信息结构指针容器 std :: queue <AsyncStruct * > *pQueue = s_pAsyncStructQueue ; //下面代码作为临界区上锁 pthread_mutex_lock ( &s_asyncStructQueueMutex ) ; //如果没有需要异步加载的图片 if (pQueue - >empty ( ) ) { //解锁临界区 pthread_mutex_unlock ( &s_asyncStructQueueMutex ) ; //如果退出线程标记为true则中断退出,否则继续。 if (need_quit ) break ; else continue ; } else { //如果有需要异步加载的图片,则从队列中取第一个消息指针保存在变量pAsyncStruct中随后将其从队列中移除。 pAsyncStruct = pQueue - >front ( ) ; pQueue - >pop ( ) ; //解锁临界区 pthread_mutex_unlock ( &s_asyncStructQueueMutex ) ; } //取得要进行异步加载的图片名称 const char *filename = pAsyncStruct - >filename. c_str ( ) ; //取得图片类型 CCImage :: EImageFormat imageType = computeImageFormatType (pAsyncStruct - >filename ) ; //如果不是PNG,JPG或TIFF就不支持了。打印错误后进行相应处理。 if (imageType == CCImage :: kFmtUnKnown ) { CCLOG ( "unsupportted format %s",filename ) ; delete pAsyncStruct ; continue ; } // 如果是有效格式,生成一个新的CCImage对象 CCImage *pImage = new CCImage ( ) ; // 由文件名和图片格式将图片加载到CCImage中。 if ( ! pImage - >initWithImageFileThreadSafe (filename, imageType ) ) { //如果失败,释放CCImage对象并打印错误。 delete pImage ; CCLOG ( "can not load %s", filename ) ; continue ; } // 动态创建一个新的图片信息结构并填充相应信息 ImageInfo *pImageInfo = new ImageInfo ( ) ; pImageInfo - >asyncStruct = pAsyncStruct ; pImageInfo - >image = pImage ; pImageInfo - >imageType = imageType ; //下面代码作为临界区上锁 pthread_mutex_lock ( &s_ImageInfoMutex ) ; //将新的图片信息放入图片信息结构容器。 s_pImageQueue - >push (pImageInfo ) ; //解锁临界区 pthread_mutex_unlock ( &s_ImageInfoMutex ) ; } //如果退出循环,释放信号量 if ( s_pSem ! = NULL ) { #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE sem_unlink (CC_ASYNC_TEXTURE_CACHE_SEMAPHORE ) ; sem_close (s_pSem ) ; #else sem_destroy (s_pSem ) ; #endif s_pSem = NULL ; //释放多线程加载所用的消息队列和与之对应的图片信息队列。 delete s_pAsyncStructQueue ; delete s_pImageQueue ; } return 0 ; } // 唯一的全局纹理数据缓冲区对象指针 static CCTextureCache *g_sharedTextureCache = NULL ; //取得唯一的全局纹理数据缓冲区对象指针 CCTextureCache * CCTextureCache :: sharedTextureCache ( ) { if ( !g_sharedTextureCache ) { g_sharedTextureCache = new CCTextureCache ( ) ; } return g_sharedTextureCache ; } //构造函数 CCTextureCache :: CCTextureCache ( ) { CCAssert (g_sharedTextureCache == NULL, "Attempted to allocate a second instance of a singleton." ) ; //生成一个字典 m_pTextures = new CCDictionary ( ) ; } //析构函数 CCTextureCache ::~CCTextureCache ( ) { CCLOGINFO ( "cocos2d: deallocing CCTextureCache." ) ; need_quit = true ; if (s_pSem ! = NULL ) { sem_post (s_pSem ) ; } //释放字典 CC_SAFE_RELEASE (m_pTextures ) ; } //释放唯一的全局纹理数据缓冲区对象 void CCTextureCache :: purgeSharedTextureCache ( ) { CC_SAFE_RELEASE_NULL (g_sharedTextureCache ) ; } //取得当前类描述 const char * CCTextureCache :: description ( ) { return CCString :: createWithFormat ( "<CCTextureCache | Number of textures = %u>", m_pTextures - >count ( ) ) - >getCString ( ) ; } //取得当前字典的快照 CCDictionary * CCTextureCache :: snapshotTextures ( ) { //动态创建一个新的字典 CCDictionary * pRet = new CCDictionary ( ) ; CCDictElement * pElement = NULL ; //遍历原来字典将数据填充到新字典中 CCDICT_FOREACH (m_pTextures, pElement ) { pRet - >setObject (pElement - >getObject ( ), pElement - >getStrKey ( ) ) ; } return pRet ; } //使用多线程载入图片。 //参1:图片相对路径名。 //参2:载入完成后要通知的对象。 //参3:载入完成后要通知对象调用的函数。 void CCTextureCache :: addImageAsync ( const char *path, CCObject *target, SEL_CallFuncO selector ) { //文件名不能为空 CCAssert (path ! = NULL, "TextureCache: fileimage MUST not be NULL" ) ; //定义一个纹理指针并置空 CCTexture2D *texture = NULL ; //创建字符串pathKey做为字典查询关键字。 std :: string pathKey = path ; //取得图片所在位置的全路径名 pathKey = CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (pathKey. c_str ( ) ) ; //先查询一下是否字典里已经有了此纹理。 texture = (CCTexture2D * )m_pTextures - >objectForKey (pathKey. c_str ( ) ) ; std :: string fullpath = pathKey ; //如果已经有了,则直接把纹理做为参数调用要通知的对象的函数。 if (texture ! = NULL ) { if (target && selector ) { (target - > *selector ) (texture ) ; } return ; } //如果是第一次调用多线程载入,创建信号量并进行相应初始化。 if (s_pSem == NULL ) { //判断是否使用信号量命名,如果是,创建一个信号量返回其地址给指针s_pSem。 #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE s_pSem = sem_open (CC_ASYNC_TEXTURE_CACHE_SEMAPHORE, O_CREAT, 0644, 0 ) ; if ( s_pSem == SEM_FAILED ) { CCLOG ( "CCTextureCache async thread semaphore init error: %s\n", strerror ( errno ) ) ; s_pSem = NULL ; return ; } #else //如果不使用信号量命名,直接用sem_init来初始化信号量对象s_sem。 int semInitRet = sem_init ( &s_sem, 0, 0 ) ; if ( semInitRet < 0 ) { //如果失败,打印出错并退出。 CCLOG ( "CCTextureCache async thread semaphore init error: %s\n", strerror ( errno ) ) ; return ; } //如果成功,将信号量对象地址给指针s_pSem。 s_pSem = &s_sem ; #endif //建立加载消息队列 s_pAsyncStructQueue = new queue <AsyncStruct * > ( ) ; //建立加载的图片信息结构队列 s_pImageQueue = new queue <ImageInfo * > ( ) ; //线程锁初始化 pthread_mutex_init ( &s_asyncStructQueueMutex, NULL ) ; pthread_mutex_init ( &s_ImageInfoMutex, NULL ) ; //创建加载线程。 pthread_create ( &s_loadingThread, NULL, loadImage, NULL ) ; //将退出指令设为false。 need_quit = false ; } //多线程加载图片的引用计数器如果为0, if ( 0 == s_nAsyncRefCount ) { //将addImageAsyncCallBack函数加入显示设备上的回调函数处理器中。 CCDirector :: sharedDirector ( ) - >getScheduler ( ) - >scheduleSelector (schedule_selector (CCTextureCache :: addImageAsyncCallBack ), this, 0, false ) ; } //计数器加1 ++s_nAsyncRefCount ; // if (target ) { target - >retain ( ) ; } // 产生一个新的加载消息,放入加载消息队列中。 AsyncStruct *data = new AsyncStruct ( ) ; data - >filename = fullpath. c_str ( ) ; data - >target = target ; data - >selector = selector ; // 当然,放入时得锁一下,放入后再解锁。 pthread_mutex_lock ( &s_asyncStructQueueMutex ) ; s_pAsyncStructQueue - >push (data ) ; pthread_mutex_unlock ( &s_asyncStructQueueMutex ) ; //给信号量加1,sem_post是原子操作,即多个线程同时调用并不会产生冲突。 sem_post (s_pSem ) ; } //多线程加载图片时的回调函数。 void CCTextureCache :: addImageAsyncCallBack ( float dt ) { // 取得多线程加载的图片信息队列 std :: queue <ImageInfo * > *imagesQueue = s_pImageQueue ; //下面代码作为临界区上锁 pthread_mutex_lock ( &s_ImageInfoMutex ) ; //如果图片信息队列为空直接解锁,否则进行处理 if (imagesQueue - >empty ( ) ) { pthread_mutex_unlock ( &s_ImageInfoMutex ) ; } else { //取出图片信息队列的头一个信息从队列中弹出。 ImageInfo *pImageInfo = imagesQueue - >front ( ) ; imagesQueue - >pop ( ) ; //解锁临界区 pthread_mutex_unlock ( &s_ImageInfoMutex ) ; //取得信息中的加载消息。 AsyncStruct *pAsyncStruct = pImageInfo - >asyncStruct ; //取得图片信息中的CCImage指针。 CCImage *pImage = pImageInfo - >image ; //取得加载完成后要通知的对象以及要调用的函数。 CCObject *target = pAsyncStruct - >target ; SEL_CallFuncO selector = pAsyncStruct - >selector ; //取得图片文件名 const char * filename = pAsyncStruct - >filename. c_str ( ) ; // 新建一个纹理。 CCTexture2D *texture = new CCTexture2D ( ) ; //使用CCImage指针pImage来初始化纹理生成OpenGL贴图。 #if 0 //TODO: (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) texture - >initWithImage (pImage, kCCResolutioniPhone ) ; #else texture - >initWithImage (pImage ) ; #endif #if CC_ENABLE_CACHE_TEXTURE_DATA //使用纹理和图片信息生成相应的可变纹理 VolatileTexture :: addImageTexture (texture, filename, pImageInfo - >imageType ) ; #endif //使用文件名做为查询关键字将纹理存入字典 m_pTextures - >setObject (texture, filename ) ; texture - >autorelease ( ) ; //调用通知目标的相应函数。 if (target && selector ) { (target - > *selector ) (texture ) ; target - >release ( ) ; } //释放CCImage对象。 pImage - >release ( ) ; //释放new出来的消息结构和图片信息结构。 delete pAsyncStruct ; delete pImageInfo ; //多线程加载引用计数器减1, --s_nAsyncRefCount ; if ( 0 == s_nAsyncRefCount ) { //从显示设备上的回调函数处理器中移除加载回调函数。 CCDirector :: sharedDirector ( ) - >getScheduler ( ) - >unscheduleSelector (schedule_selector (CCTextureCache :: addImageAsyncCallBack ), this ) ; } } } //加载一个图片生成纹理。 CCTexture2D * CCTextureCache :: addImage ( const char * path ) { //参数有效性判断 CCAssert (path ! = NULL, "TextureCache: fileimage MUST not be NULL" ) ; //定义纹理指针变量并置空 CCTexture2D * texture = NULL ; //非多线程,故屏蔽,如果addImageAsync在其它线程调用此函数,则打开这段代码。 //pthread_mutex_lock(m_pDictLock); //创建字符串pathKey做为字典查询关键字。 std :: string pathKey = path ; //取得图片所在位置的全路径名 pathKey = CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (pathKey. c_str ( ) ) ; //用pathKey查询字典中是否有此纹理。 texture = (CCTexture2D * )m_pTextures - >objectForKey (pathKey. c_str ( ) ) ; //新建字符串fullpath存储全路径。 std :: string fullpath = pathKey ; //如果没有找到, if ( ! texture ) { //将文件路径放入新字符串lowerCase。并将字符串中的所有字母转为小写。 std :: string lowerCase (path ) ; for ( unsigned int i = 0 ; i < lowerCase. length ( ) ; ++i ) { lowerCase [i ] = tolower (lowerCase [i ] ) ; } // do { //如果字符串能够找到".pvr",则代表是pvr文件。调用相应函数将其载入。 if (std :: string :: npos ! = lowerCase. find ( ".pvr" ) ) { texture = this - >addPVRImage (fullpath. c_str ( ) ) ; } else { //否则分别取得文件的格式。 CCImage :: EImageFormat eImageFormat = CCImage :: kFmtUnKnown ; if (std :: string :: npos ! = lowerCase. find ( ".png" ) ) { eImageFormat = CCImage :: kFmtPng ; } else if (std :: string :: npos ! = lowerCase. find ( ".jpg" ) || std :: string :: npos ! = lowerCase. find ( ".jpeg" ) ) { eImageFormat = CCImage :: kFmtJpg ; } else if (std :: string :: npos ! = lowerCase. find ( ".tif" ) || std :: string :: npos ! = lowerCase. find ( ".tiff" ) ) { eImageFormat = CCImage :: kFmtTiff ; } //创建CCImage对象,从文件中读取文件的数据并初始化CCImage对象。 CCImage image ; //取得文件大小 unsigned long nSize = 0 ; //读入数据返回给BYTE类型指针。 unsigned char * pBuffer = CCFileUtils :: sharedFileUtils ( ) - >getFileData (fullpath. c_str ( ), "rb", &nSize ) ; //使用读入的数据初始化相应的图片对象。 CC_BREAK_IF ( ! image. initWithImageData ( ( void * )pBuffer, nSize, eImageFormat ) ) ; //读完后释放数据占用的内存。 CC_SAFE_DELETE_ARRAY (pBuffer ) ; //创建一个纹理。 texture = new CCTexture2D ( ) ; //使用图片对象创建纹理。 if ( texture && texture - >initWithImage ( &image ) ) { #if CC_ENABLE_CACHE_TEXTURE_DATA // 使用图片对象生成可变纹理 VolatileTexture :: addImageTexture (texture, fullpath. c_str ( ), eImageFormat ) ; #endif //利用路径名做为查询关键字将纹理存入字典。 m_pTextures - >setObject (texture, pathKey. c_str ( ) ) ; //计数器减1。则刚存入字典的纹理的引用计数器值标记为尚未使用。 texture - >release ( ) ; } else { //失败则打印错误。 CCLOG ( "cocos2d: Couldn't add image:%s in CCTextureCache", path ) ; } } } while ( 0 ) ; } //与上面屏蔽加锁一样,这里屏蔽解锁。 //pthread_mutex_unlock(m_pDictLock); return texture ; } //如果支持PVR的压缩格式。 #ifdef CC_SUPPORT_PVRTC //加载一个PVR的压缩格式的图片。 CCTexture2D * CCTextureCache :: addPVRTCImage ( const char * path, int bpp, bool hasAlpha, int width ) { //参数有效性判断 CCAssert (path ! = NULL, "TextureCache: fileimage MUST not be nill" ) ; //压缩类型参数有效性判断,只能为2或4 CCAssert ( bpp == 2 || bpp == 4, "TextureCache: bpp must be either 2 or 4" ) ; //定义一个新的纹理指针 CCTexture2D * texture ; //定义临时字符串存储相对路径名。 std :: string temp (path ) ; //查询字典中是否已经有此纹理。有则取得并直接返回纹理。 if ( (texture = (CCTexture2D * )m_pTextures - >objectForKey (temp. c_str ( ) ) ) ) { return texture ; } // 取得文件的全路径字符串。 std :: string fullpath ( CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (path ) ) ; //新建变量nLeng用于存储读取到的数据大小。初始化为0。 unsigned long nLen = 0 ; //新建字符指针pData用于存储读取到的数据并实际读取文件数据。 unsigned char * pData = CCFileUtils :: sharedFileUtils ( ) - >getFileData (fullpath. c_str ( ), "rb", &nLen ) ; //新建创一个纹理。 texture = new CCTexture2D ( ) ; //使用读取到的数据创建纹理。 if ( texture - >initWithPVRTCData (pData, 0, bpp, hasAlpha, width, (bpp == 2 ? kCCTexture2DPixelFormat_PVRTC2 : kCCTexture2DPixelFormat_PVRTC4 ) ) ) { //将纹理以文件名做为关键字存入字典。 m_pTextures - >setObject (texture, temp. c_str ( ) ) ; //将纹理交由内存管理器处理。 texture - >autorelease ( ) ; } else { //如果创建失败或读取PVR文件失败,打印错误日志。\ CCLOG("cocos2d: Couldn't add PVRTCImage:%s in CCTextureCache",path); } //释放读取文件的数据所占用的内存。 CC_SAFE_DELETE_ARRAY (pData ) ; return texture ; } #endif // CC_SUPPORT_PVRTC //加载一个普通的PVR图片文件 CCTexture2D * CCTextureCache :: addPVRImage ( const char * path ) { //文件名参数有效性判断。 CCAssert (path ! = NULL, "TextureCache: fileimage MUST not be nill" ) ; //新建纹理指针变量置空。 CCTexture2D * texture = NULL ; //定义临时字符串存储相对路径名。 std :: string key (path ) ; //先使用文件名查询是否字典中已经有此纹理了。如果有直接取得并返回纹理。 if ( (texture = (CCTexture2D * )m_pTextures - >objectForKey (key. c_str ( ) ) ) ) { return texture ; } // 由文件名字符串取得图片的全路径字符串。 std :: string fullpath = CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (key. c_str ( ) ) ; //动态创建一个纹理。 texture = new CCTexture2D ( ) ; //如果创建成功,则读取相应的PVR文件来初始化纹理。 if (texture ! = NULL && texture - >initWithPVRFile (fullpath. c_str ( ) ) ) { //初始化成功。 #if CC_ENABLE_CACHE_TEXTURE_DATA // 使用纹理和图片信息生成可变纹理。 VolatileTexture :: addImageTexture (texture, fullpath. c_str ( ), CCImage :: kFmtRawData ) ; #endif //将纹理以文件名做为查询关键字存入字典。 m_pTextures - >setObject (texture, key. c_str ( ) ) ; texture - >autorelease ( ) ; } else { //如果创建失败或读取PVR文件失败,打印错误日志。 CCLOG ( "cocos2d: Couldn't add PVRImage:%s in CCTextureCache",key. c_str ( ) ) ; CC_SAFE_DELETE (texture ) ; } return texture ; } //加载一个图片生成纹理,指定参数key做为字典的查询对应关键字。 CCTexture2D * CCTextureCache :: addUIImage (CCImage *image, const char *key ) { //参数有效性判断 CCAssert (image ! = NULL, "TextureCache: image MUST not be nill" ) ; //定义纹理指针变量texure做为返回值。这里初始化为空。 CCTexture2D * texture = NULL ; //定义字符串变量forKey用来存储完整的图片路径名称。 std :: string forKey ; if (key ) { //取得文件名所对应的全路径名,呵呵,这个key也还是个相对路径名啊。 forKey = CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (key ) ; } do { // 查询字典是否已经有此纹理了。如果有,取出纹理返回给texture,中断退出。 if (key && (texture = (CCTexture2D * )m_pTextures - >objectForKey (forKey. c_str ( ) ) ) ) { break ; } //动态创建一个纹理对象.返回给texture。 texture = new CCTexture2D ( ) ; //使用image来初始化纹理.注意:这一句应该移到下面的if中。 texture - >initWithImage (image ) ; //初始化完成后以路径名做为查询关键字将纹理存入字典。 if (key && texture ) { m_pTextures - >setObject (texture, forKey. c_str ( ) ) ; texture - >autorelease ( ) ; } else { //如果key为空或texture为空打印错误 CCLOG ( "cocos2d: Couldn't add UIImage in CCTextureCache" ) ; } } while ( 0 ) ; #if CC_ENABLE_CACHE_TEXTURE_DATA //使用纹理和CCImage对象生成可变纹理。 VolatileTexture :: addCCImage (texture, image ) ; #endif return texture ; } //清空字典,释放所有纹理。 void CCTextureCache :: removeAllTextures ( ) { m_pTextures - >removeAllObjects ( ) ; } //清除未被外部使用的纹理 void CCTextureCache :: removeUnusedTextures ( ) { /*原来的做法,因为有问题给屏蔽了,仍然解释下: //定义字典词汇指针变量pElement。 CCDictElement* pElement = NULL; //遍历字典 CCDICT_FOREACH(m_pTextures, pElement) { //打印词汇信息 CCLOG("cocos2d: CCTextureCache: texture: %s", pElement->getStrKey()); //取得词汇对应的纹理 CCTexture2D *value = (CCTexture2D*)pElement->getObject(); //如果引用计数器值为1,从字典中删除。 if (value->retainCount() == 1) { CCLOG("cocos2d: CCTextureCache: removing unused texture: %s", pElement->getStrKey()); m_pTextures->removeObjectForElememt(pElement); } } */ //现在的做法 // 判断字典不为空 if (m_pTextures - >count ( ) ) { //定义字典词汇指针变量pElement。 CCDictElement * pElement = NULL ; //定义一个list容器用来存储未被外部使用的纹理指针。 list <CCDictElement * > elementToRemove ; //遍历字典 CCDICT_FOREACH (m_pTextures, pElement ) { //打印词汇信息 CCLOG ( "cocos2d: CCTextureCache: texture: %s", pElement - >getStrKey ( ) ) ; //取得词汇对应的纹理 CCTexture2D *value = (CCTexture2D * )pElement - >getObject ( ) ; if (value - >retainCount ( ) == 1 ) { //如果引用计数器值为1,先存入容器中。 elementToRemove. push_back (pElement ) ; } } // 遍历list中的元素从字典中删除 for (list <CCDictElement * > :: iterator iter = elementToRemove. begin ( ) ; iter ! = elementToRemove. end ( ) ; ++iter ) { //打印删除元素日志。 CCLOG ( "cocos2d: CCTextureCache: removing unused texture: %s", ( *iter ) - >getStrKey ( ) ) ; //从字典中删除 m_pTextures - >removeObjectForElememt ( *iter ) ; } } //好吧,答案是因为CCDICT_FOREACH和removeObjectForElememt会互相影响,CCDICT_FOREACH中会调用HASH_ITER循环遍历。而循环的计数器是位置,通过地址对比来找下一个结点位置。而removeObjectForElememt会调用HASH_DELETE删除元素导致链表的重构。重构后会影响到HASK_ITER的查询。 } //移除一个纹理 void CCTextureCache :: removeTexture (CCTexture2D * texture ) { //参数有效性判断 if ( ! texture ) { return ; } //查询所有对应此纹理的词汇 CCArray * keys = m_pTextures - >allKeysForObject (texture ) ; //从字典中把这些词汇及相应纹理删除。 m_pTextures - >removeObjectsForKeys (keys ) ; } //由字典查询关键字找到相应纹理并移除。 void CCTextureCache :: removeTextureForKey ( const char *textureKeyName ) { //参数有效性判断 if (textureKeyName == NULL ) { return ; } //查询关键字实际是文件的相对路径,这里取得全路径。 string fullPath = CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (textureKeyName ) ; //将全路径做为查询关键字从字典中删除相应词汇及纹理 m_pTextures - >removeObjectForKey (fullPath. c_str ( ) ) ; } //由字典查询关键字找到相应纹理 CCTexture2D * CCTextureCache :: textureForKey ( const char * key ) { return (CCTexture2D * )m_pTextures - >objectForKey (CCFileUtils :: sharedFileUtils ( ) - >fullPathFromRelativePath (key ) ) ; } //重新载入所有的纹理 void CCTextureCache :: reloadAllTextures ( ) { #if CC_ENABLE_CACHE_TEXTURE_DATA //调用可变纹理的静态函数重新载入所有的纹理 VolatileTexture :: reloadAllTextures ( ) ; #endif } //打印字典中的纹理统计信息。 void CCTextureCache :: dumpCachedTextureInfo ( ) { unsigned int count = 0 ; unsigned int totalBytes = 0 ; CCDictElement * pElement = NULL ; //遍历字典中的所有词汇信息 CCDICT_FOREACH (m_pTextures, pElement ) { //取得词汇对应的纹理 CCTexture2D * tex = (CCTexture2D * )pElement - >getObject ( ) ; //取得纹理对应贴图的色深 unsigned int bpp = tex - >bitsPerPixelForFormat ( ) ; // 生成贴图占用的内存大小(字节数量) unsigned int bytes = tex - >getPixelsWide ( ) * tex - >getPixelsHigh ( ) * bpp / 8 ; // 统计内存总大小 totalBytes + = bytes ; count ++ ; //打印纹理信息 CCLOG ( "cocos2d: \"%s\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB", pElement - >getStrKey ( ), //查询关键字 ( long )tex - >retainCount ( ), //使用次数 ( long )tex - >getName ( ), //图片名称 ( long )tex - >getPixelsWide ( ), //对应贴图的宽度 ( long )tex - >getPixelsHigh ( ), //对应贴图的高度 ( long )bpp, //对应贴图色深 ( long )bytes / 1024 ) ; //占用内存大小(千字节数量) } //打印总的数量数量,占用内存数量。 CCLOG ( "cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", ( long )count, ( long )totalBytes / 1024, totalBytes / ( 1024.0f * 1024.0f ) ) ; } //如果开启了使用多变纹理 #if CC_ENABLE_CACHE_TEXTURE_DATA //定义全局的list容器,用来存储产生的多变纹理对象指针 std :: list <VolatileTexture * > VolatileTexture :: textures ; //定义布尔变量标记是否在全部重新载入 bool VolatileTexture :: isReloading = false ; //构造函数 VolatileTexture :: VolatileTexture (CCTexture2D *t ) : texture (t ) , m_eCashedImageType (kInvalid ) , m_pTextureData ( NULL ) , m_PixelFormat (kTexture2DPixelFormat_RGBA8888 ) , m_strFileName ( "" ) , m_FmtImage (CCImage :: kFmtPng ) , m_alignment (kCCTextAlignmentCenter ) , m_vAlignment (kCCVerticalTextAlignmentCenter ) , m_strFontName ( "" ) , m_strText ( "" ) , uiImage ( NULL ) , m_fFontSize ( 0.0f ) { m_size = CCSizeMake ( 0, 0 ) ; textures. push_back ( this ) ; } //析构函数 VolatileTexture ::~VolatileTexture ( ) { textures. remove ( this ) ; CC_SAFE_RELEASE (uiImage ) ; } //通过纹理图片属性信息生成可变纹理。 void VolatileTexture :: addImageTexture (CCTexture2D *tt, const char * imageFileName, CCImage :: EImageFormat format ) { //如果正在重新载入过程中,直接返回。 if (isReloading ) { return ; } //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。 VolatileTexture *vt = findVolotileTexture (tt ) ; //设置相关属性,注意:这里最好对vt做下有效性检查,如果为NULL的话会崩溃的。 vt - >m_eCashedImageType = kImageFile ; vt - >m_strFileName = imageFileName ; vt - >m_FmtImage = format ; vt - >m_PixelFormat = tt - >getPixelFormat ( ) ; } //通过CCImage对象生成可变纹理。 void VolatileTexture :: addCCImage (CCTexture2D *tt, CCImage *image ) { //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。 VolatileTexture *vt = findVolotileTexture (tt ) ; image - >retain ( ) ; //设置相关属性 vt - >uiImage = image ; vt - >m_eCashedImageType = kImage ; } //通过纹理指针找到相应的可变纹理,如果没有则new出一个返回。 VolatileTexture * VolatileTexture :: findVolotileTexture (CCTexture2D *tt ) { VolatileTexture *vt = 0 ; //遍历list容器,对比查询。 std :: list <VolatileTexture * > :: iterator i = textures. begin ( ) ; while (i ! = textures. end ( ) ) { VolatileTexture *v = *i ++ ; if (v - >texture == tt ) { vt = v ; break ; } } //如果没有找到,则由纹理参数new出一个可变纹理,new会调用其带参数的拷贝构造函数设置其对应纹理。 if ( ! vt ) { vt = new VolatileTexture (tt ) ; } return vt ; } //通过指定图像数据,像素格式和图片大小来生成可变纹理。 void VolatileTexture :: addDataTexture (CCTexture2D *tt, void * data, CCTexture2DPixelFormat pixelFormat, const CCSize & contentSize ) { //如果正在重新载入过程中,直接返回。 if (isReloading ) { return ; } //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。 VolatileTexture *vt = findVolotileTexture (tt ) ; //设置相关属性 vt - >m_eCashedImageType = kImageData ; vt - >m_pTextureData = data ; vt - >m_PixelFormat = pixelFormat ; vt - >m_TextureSize = contentSize ; } //由字符串和相应信息生成可变纹理 void VolatileTexture :: addStringTexture (CCTexture2D *tt, const char * text, const CCSize & dimensions, CCTextAlignment alignment, CCVerticalTextAlignment vAlignment, const char *fontName, float fontSize ) { //如果正在重新载入过程中,直接返回。 if (isReloading ) { return ; } //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。 VolatileTexture *vt = findVolotileTexture (tt ) ; //设置相关属性 vt - >m_eCashedImageType = kString ; vt - >m_size = dimensions ; vt - >m_strFontName = fontName ; vt - >m_alignment = alignment ; vt - >m_vAlignment = vAlignment ; vt - >m_fFontSize = fontSize ; vt - >m_strText = text ; } //通过纹理指针找到相应的可变纹理并删除。 void VolatileTexture :: removeTexture (CCTexture2D *t ) { std :: list <VolatileTexture * > :: iterator i = textures. begin ( ) ; while (i ! = textures. end ( ) ) { VolatileTexture *vt = *i ++ ; if (vt - >texture == t ) { delete vt ; break ; } } } //重新载入所有的纹理。 void VolatileTexture :: reloadAllTextures ( ) { //设置开始进行重新载入所有纹理。 isReloading = true ; CCLOG ( "reload all texture" ) ; //通过迭代器遍历list容器 std :: list <VolatileTexture * > :: iterator iter = textures. begin ( ) ; while (iter ! = textures. end ( ) ) { VolatileTexture *vt = *iter ++ ; //根据不同的格式进行纹理的重建 switch (vt - >m_eCashedImageType ) { case kImageFile : { //这里定义一个CCImage对象image CCImage image ; //先将路径名都变成小写字符串。 std :: string lowerCase (vt - >m_strFileName. c_str ( ) ) ; for ( unsigned int i = 0 ; i < lowerCase. length ( ) ; ++i ) { lowerCase [i ] = tolower (lowerCase [i ] ) ; } //扩展名对比,如果是PVR文件 if (std :: string :: npos ! = lowerCase. find ( ".pvr" ) ) { //取得原来的默认带ALPHA通道的像素格式。 CCTexture2DPixelFormat oldPixelFormat = CCTexture2D :: defaultAlphaPixelFormat ( ) ; //重设默认带ALPHA通道的像素格式。 CCTexture2D :: setDefaultAlphaPixelFormat (vt - >m_PixelFormat ) ; //纹理重新由PVR文件进行初始化。会用到新的默认带ALPHA通道的像素格式。 vt - >texture - >initWithPVRFile (vt - >m_strFileName. c_str ( ) ) ; //重设原来的默认带ALPHA通道的像素格式。 CCTexture2D :: setDefaultAlphaPixelFormat (oldPixelFormat ) ; } else { //如果是非PVR文件。 unsigned long nSize = 0 ; //通过文件工具集中的接口读入图片文件并返回数据地址。 unsigned char * pBuffer = CCFileUtils :: sharedFileUtils ( ) - >getFileData (vt - >m_strFileName. c_str ( ), "rb", &nSize ) ; //使用数据地址对前面定义的CCImage对象image进行初始化。 if (image. initWithImageData ( ( void * )pBuffer, nSize, vt - >m_FmtImage ) ) { //取得原来的默认带ALPHA通道的像素格式。 CCTexture2DPixelFormat oldPixelFormat = CCTexture2D :: defaultAlphaPixelFormat ( ) ; //重设默认带ALPHA通道的像素格式。CCTexture2D::setDefaultAlphaPixelFormat(vt->m_PixelFormat); //纹理重新由图片对象初始化。会用到新的默认带ALPHA通道的像素格式。 vt - >texture - >initWithImage ( &image ) ; //重设原来的默认带ALPHA通道的像素格式。 CCTexture2D :: setDefaultAlphaPixelFormat (oldPixelFormat ) ; } CC_SAFE_DELETE_ARRAY (pBuffer ) ; } } break ; case kImageData : { //纹理重新由图片数据初始化。 vt - >texture - >initWithData (vt - >m_pTextureData, vt - >m_PixelFormat, vt - >m_TextureSize. width, vt - >m_TextureSize. height, vt - >m_TextureSize ) ; } break ; case kString : { //纹理重新由字符串初始化。 vt - >texture - >initWithString (vt - >m_strText. c_str ( ), vt - >m_size, vt - >m_alignment, vt - >m_vAlignment, vt - >m_strFontName. c_str ( ), vt - >m_fFontSize ) ; } break ; case kImage : { //纹理重新由图片对象初始化。 vt - >texture - >initWithImage (vt - >uiImage ) ; } break ; default : break ; } } //设置重新载入完成 isReloading = false ; } #endif // CC_ENABLE_CACHE_TEXTURE_DATA NS_CC_END |