【游戏引擎】深入分析Cocos2d-x 2.0中的“纹理”(四)

三.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,  06440 ) ;
         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,  00 ) ;
         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 )this0false ) ;
     }
//计数器加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 ( 00 ) ;
    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  (! = textures. end ( ) )
     {
        VolatileTexture  *=  *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  (! = 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

你可能感兴趣的:(【游戏引擎】深入分析Cocos2d-x 2.0中的“纹理”(四))