summary refs log tree commit diff stats
path: root/libs
diff options
context:
space:
mode:
authorStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
committerStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
commit9cd57b731ab1c666d4a1cb725538fdc137763d12 (patch)
tree5bac45ae5157a1cb10c6e45500cbf72789917980 /libs
downloadcartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.gz
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.bz2
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.zip
Initial commit (version 0.2.1)
Diffstat (limited to 'libs')
-rwxr-xr-xlibs/CocosDenshion/CDAudioManager.h243
-rwxr-xr-xlibs/CocosDenshion/CDAudioManager.m887
-rwxr-xr-xlibs/CocosDenshion/CDConfig.h60
-rwxr-xr-xlibs/CocosDenshion/CDOpenALSupport.h77
-rwxr-xr-xlibs/CocosDenshion/CDOpenALSupport.m246
-rwxr-xr-xlibs/CocosDenshion/CocosDenshion.h440
-rwxr-xr-xlibs/CocosDenshion/CocosDenshion.m1602
-rwxr-xr-xlibs/CocosDenshion/SimpleAudioEngine.h90
-rwxr-xr-xlibs/CocosDenshion/SimpleAudioEngine.m220
-rwxr-xr-xlibs/FontLabel/FontLabel.h44
-rwxr-xr-xlibs/FontLabel/FontLabel.m195
-rwxr-xr-xlibs/FontLabel/FontLabelStringDrawing.h69
-rwxr-xr-xlibs/FontLabel/FontLabelStringDrawing.m892
-rwxr-xr-xlibs/FontLabel/FontManager.h85
-rwxr-xr-xlibs/FontLabel/FontManager.m123
-rwxr-xr-xlibs/FontLabel/ZAttributedString.h77
-rwxr-xr-xlibs/FontLabel/ZAttributedString.m597
-rwxr-xr-xlibs/FontLabel/ZAttributedStringPrivate.h24
-rwxr-xr-xlibs/FontLabel/ZFont.h47
-rwxr-xr-xlibs/FontLabel/ZFont.m170
-rwxr-xr-xlibs/README1
-rwxr-xr-xlibs/TouchJSON/CDataScanner.h71
-rwxr-xr-xlibs/TouchJSON/CDataScanner.m340
-rwxr-xr-xlibs/TouchJSON/Extensions/CDataScanner_Extensions.h40
-rwxr-xr-xlibs/TouchJSON/Extensions/CDataScanner_Extensions.m135
-rwxr-xr-xlibs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h37
-rwxr-xr-xlibs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m47
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONDeserializer.h63
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONDeserializer.m161
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONScanner.h95
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONScanner.m676
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONSerializer.h53
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONSerializer.m342
-rwxr-xr-xlibs/TouchJSON/JSON/JSONRepresentation.h18
-rwxr-xr-xlibs/cocos2d/CCAction.h195
-rwxr-xr-xlibs/cocos2d/CCAction.m360
-rwxr-xr-xlibs/cocos2d/CCActionCamera.h73
-rwxr-xr-xlibs/cocos2d/CCActionCamera.m147
-rwxr-xr-xlibs/cocos2d/CCActionEase.h159
-rwxr-xr-xlibs/cocos2d/CCActionEase.m534
-rwxr-xr-xlibs/cocos2d/CCActionGrid.h165
-rwxr-xr-xlibs/cocos2d/CCActionGrid.m386
-rwxr-xr-xlibs/cocos2d/CCActionGrid3D.h208
-rwxr-xr-xlibs/cocos2d/CCActionGrid3D.m659
-rwxr-xr-xlibs/cocos2d/CCActionInstant.h205
-rwxr-xr-xlibs/cocos2d/CCActionInstant.m477
-rwxr-xr-xlibs/cocos2d/CCActionInterval.h421
-rwxr-xr-xlibs/cocos2d/CCActionInterval.m1355
-rwxr-xr-xlibs/cocos2d/CCActionManager.h111
-rwxr-xr-xlibs/cocos2d/CCActionManager.m345
-rwxr-xr-xlibs/cocos2d/CCActionPageTurn3D.h42
-rwxr-xr-xlibs/cocos2d/CCActionPageTurn3D.m86
-rwxr-xr-xlibs/cocos2d/CCActionProgressTimer.h59
-rwxr-xr-xlibs/cocos2d/CCActionProgressTimer.m103
-rwxr-xr-xlibs/cocos2d/CCActionTiledGrid.h211
-rwxr-xr-xlibs/cocos2d/CCActionTiledGrid.m768
-rwxr-xr-xlibs/cocos2d/CCActionTween.h62
-rwxr-xr-xlibs/cocos2d/CCActionTween.m72
-rwxr-xr-xlibs/cocos2d/CCAnimation.h136
-rwxr-xr-xlibs/cocos2d/CCAnimation.m153
-rwxr-xr-xlibs/cocos2d/CCAnimationCache.h64
-rwxr-xr-xlibs/cocos2d/CCAnimationCache.m101
-rwxr-xr-xlibs/cocos2d/CCAtlasNode.h93
-rwxr-xr-xlibs/cocos2d/CCAtlasNode.m211
-rwxr-xr-xlibs/cocos2d/CCBlockSupport.h51
-rwxr-xr-xlibs/cocos2d/CCBlockSupport.m46
-rwxr-xr-xlibs/cocos2d/CCCamera.h95
-rwxr-xr-xlibs/cocos2d/CCCamera.m131
-rwxr-xr-xlibs/cocos2d/CCConfiguration.h116
-rwxr-xr-xlibs/cocos2d/CCConfiguration.m193
-rwxr-xr-xlibs/cocos2d/CCDirector.h307
-rwxr-xr-xlibs/cocos2d/CCDirector.m565
-rwxr-xr-xlibs/cocos2d/CCDrawingPrimitives.h92
-rwxr-xr-xlibs/cocos2d/CCDrawingPrimitives.m272
-rwxr-xr-xlibs/cocos2d/CCGrabber.h43
-rwxr-xr-xlibs/cocos2d/CCGrabber.m95
-rwxr-xr-xlibs/cocos2d/CCGrid.h121
-rwxr-xr-xlibs/cocos2d/CCGrid.m571
-rwxr-xr-xlibs/cocos2d/CCLabelAtlas.h62
-rwxr-xr-xlibs/cocos2d/CCLabelAtlas.m170
-rwxr-xr-xlibs/cocos2d/CCLabelBMFont.h190
-rwxr-xr-xlibs/cocos2d/CCLabelBMFont.m675
-rwxr-xr-xlibs/cocos2d/CCLabelTTF.h78
-rwxr-xr-xlibs/cocos2d/CCLabelTTF.m138
-rwxr-xr-xlibs/cocos2d/CCLayer.h293
-rwxr-xr-xlibs/cocos2d/CCLayer.m621
-rwxr-xr-xlibs/cocos2d/CCMenu.h93
-rwxr-xr-xlibs/cocos2d/CCMenu.m523
-rwxr-xr-xlibs/cocos2d/CCMenuItem.h377
-rwxr-xr-xlibs/cocos2d/CCMenuItem.m795
-rwxr-xr-xlibs/cocos2d/CCMotionStreak.h67
-rwxr-xr-xlibs/cocos2d/CCMotionStreak.m104
-rwxr-xr-xlibs/cocos2d/CCNode.h529
-rwxr-xr-xlibs/cocos2d/CCNode.m921
-rwxr-xr-xlibs/cocos2d/CCParallaxNode.h50
-rwxr-xr-xlibs/cocos2d/CCParallaxNode.m161
-rwxr-xr-xlibs/cocos2d/CCParticleExamples.h111
-rwxr-xr-xlibs/cocos2d/CCParticleExamples.m926
-rwxr-xr-xlibs/cocos2d/CCParticleSystem.h445
-rwxr-xr-xlibs/cocos2d/CCParticleSystem.m808
-rwxr-xr-xlibs/cocos2d/CCParticleSystemPoint.h65
-rwxr-xr-xlibs/cocos2d/CCParticleSystemPoint.m211
-rwxr-xr-xlibs/cocos2d/CCParticleSystemQuad.h76
-rwxr-xr-xlibs/cocos2d/CCParticleSystemQuad.m318
-rwxr-xr-xlibs/cocos2d/CCProgressTimer.h83
-rwxr-xr-xlibs/cocos2d/CCProgressTimer.m493
-rwxr-xr-xlibs/cocos2d/CCProtocols.h125
-rwxr-xr-xlibs/cocos2d/CCRenderTexture.h108
-rwxr-xr-xlibs/cocos2d/CCRenderTexture.m340
-rwxr-xr-xlibs/cocos2d/CCRibbon.h117
-rwxr-xr-xlibs/cocos2d/CCRibbon.m383
-rwxr-xr-xlibs/cocos2d/CCScene.h43
-rwxr-xr-xlibs/cocos2d/CCScene.m45
-rwxr-xr-xlibs/cocos2d/CCScheduler.h199
-rwxr-xr-xlibs/cocos2d/CCScheduler.m657
-rwxr-xr-xlibs/cocos2d/CCSprite.h351
-rwxr-xr-xlibs/cocos2d/CCSprite.m1029
-rwxr-xr-xlibs/cocos2d/CCSpriteBatchNode.h145
-rwxr-xr-xlibs/cocos2d/CCSpriteBatchNode.m503
-rwxr-xr-xlibs/cocos2d/CCSpriteFrame.h90
-rwxr-xr-xlibs/cocos2d/CCSpriteFrame.m111
-rwxr-xr-xlibs/cocos2d/CCSpriteFrameCache.h137
-rwxr-xr-xlibs/cocos2d/CCSpriteFrameCache.m347
-rwxr-xr-xlibs/cocos2d/CCTMXLayer.h152
-rwxr-xr-xlibs/cocos2d/CCTMXLayer.m670
-rwxr-xr-xlibs/cocos2d/CCTMXObjectGroup.h67
-rwxr-xr-xlibs/cocos2d/CCTMXObjectGroup.m86
-rwxr-xr-xlibs/cocos2d/CCTMXTiledMap.h145
-rwxr-xr-xlibs/cocos2d/CCTMXTiledMap.m201
-rwxr-xr-xlibs/cocos2d/CCTMXXMLParser.h202
-rwxr-xr-xlibs/cocos2d/CCTMXXMLParser.m456
-rwxr-xr-xlibs/cocos2d/CCTexture2D.h328
-rwxr-xr-xlibs/cocos2d/CCTexture2D.m814
-rwxr-xr-xlibs/cocos2d/CCTextureAtlas.h147
-rwxr-xr-xlibs/cocos2d/CCTextureAtlas.m369
-rwxr-xr-xlibs/cocos2d/CCTextureCache.h149
-rwxr-xr-xlibs/cocos2d/CCTextureCache.m498
-rwxr-xr-xlibs/cocos2d/CCTexturePVR.h127
-rwxr-xr-xlibs/cocos2d/CCTexturePVR.m428
-rwxr-xr-xlibs/cocos2d/CCTileMapAtlas.h83
-rwxr-xr-xlibs/cocos2d/CCTileMapAtlas.m234
-rwxr-xr-xlibs/cocos2d/CCTransition.h296
-rwxr-xr-xlibs/cocos2d/CCTransition.m1059
-rwxr-xr-xlibs/cocos2d/CCTransitionPageTurn.h60
-rwxr-xr-xlibs/cocos2d/CCTransitionPageTurn.m117
-rwxr-xr-xlibs/cocos2d/CCTransitionRadial.h40
-rwxr-xr-xlibs/cocos2d/CCTransitionRadial.m115
-rwxr-xr-xlibs/cocos2d/Platforms/CCGL.h83
-rwxr-xr-xlibs/cocos2d/Platforms/CCNS.h78
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/CCDirectorMac.h103
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/CCDirectorMac.m479
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/CCEventDispatcher.h277
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/CCEventDispatcher.m645
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/MacGLView.h89
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/MacGLView.m242
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/MacWindow.h42
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/MacWindow.m70
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCDirectorIOS.h255
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCDirectorIOS.m735
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCTouchDelegateProtocol.h75
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCTouchDispatcher.h123
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCTouchDispatcher.m347
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCTouchHandler.h93
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/CCTouchHandler.m135
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/EAGLView.h155
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/EAGLView.m343
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/ES1Renderer.h72
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/ES1Renderer.m259
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/ESRenderer.h54
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/glu.c113
-rwxr-xr-xlibs/cocos2d/Platforms/iOS/glu.h29
-rwxr-xr-xlibs/cocos2d/Support/CCArray.h106
-rwxr-xr-xlibs/cocos2d/Support/CCArray.m290
-rwxr-xr-xlibs/cocos2d/Support/CCFileUtils.h62
-rwxr-xr-xlibs/cocos2d/Support/CCFileUtils.m169
-rwxr-xr-xlibs/cocos2d/Support/CCProfiling.h53
-rwxr-xr-xlibs/cocos2d/Support/CCProfiling.m117
-rwxr-xr-xlibs/cocos2d/Support/CGPointExtension.h334
-rwxr-xr-xlibs/cocos2d/Support/CGPointExtension.m196
-rwxr-xr-xlibs/cocos2d/Support/OpenGL_Internal.h80
-rwxr-xr-xlibs/cocos2d/Support/TGAlib.h55
-rwxr-xr-xlibs/cocos2d/Support/TGAlib.m274
-rwxr-xr-xlibs/cocos2d/Support/TransformUtils.h37
-rwxr-xr-xlibs/cocos2d/Support/TransformUtils.m46
-rwxr-xr-xlibs/cocos2d/Support/ZipUtils.h91
-rwxr-xr-xlibs/cocos2d/Support/ZipUtils.m251
-rwxr-xr-xlibs/cocos2d/Support/base64.c93
-rwxr-xr-xlibs/cocos2d/Support/base64.h33
-rwxr-xr-xlibs/cocos2d/Support/ccCArray.h447
-rwxr-xr-xlibs/cocos2d/Support/ccUtils.c20
-rwxr-xr-xlibs/cocos2d/Support/ccUtils.h29
-rwxr-xr-xlibs/cocos2d/Support/uthash.h972
-rwxr-xr-xlibs/cocos2d/Support/utlist.h490
-rwxr-xr-xlibs/cocos2d/ccConfig.h334
-rwxr-xr-xlibs/cocos2d/ccMacros.h253
-rwxr-xr-xlibs/cocos2d/ccTypes.h287
-rwxr-xr-xlibs/cocos2d/cocos2d.h161
-rwxr-xr-xlibs/cocos2d/cocos2d.m34
-rwxr-xr-xlibs/cocoslive/CLScoreServerPost.h142
-rwxr-xr-xlibs/cocoslive/CLScoreServerPost.m335
-rwxr-xr-xlibs/cocoslive/CLScoreServerRequest.h122
-rwxr-xr-xlibs/cocoslive/CLScoreServerRequest.m257
-rwxr-xr-xlibs/cocoslive/cocoslive.h43
-rwxr-xr-xlibs/cocoslive/cocoslive.m37
204 files changed, 51028 insertions, 0 deletions
diff --git a/libs/CocosDenshion/CDAudioManager.h b/libs/CocosDenshion/CDAudioManager.h new file mode 100755 index 0000000..2475929 --- /dev/null +++ b/libs/CocosDenshion/CDAudioManager.h
@@ -0,0 +1,243 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25#import "CocosDenshion.h"
26#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30000
27 #import <AVFoundation/AVFoundation.h>
28#else
29 #import "CDXMacOSXSupport.h"
30#endif
31
32/** Different modes of the engine */
33typedef enum {
34 kAMM_FxOnly, //!Other apps will be able to play audio
35 kAMM_FxPlusMusic, //!Only this app will play audio
36 kAMM_FxPlusMusicIfNoOtherAudio, //!If another app is playing audio at start up then allow it to continue and don't play music
37 kAMM_MediaPlayback, //!This app takes over audio e.g music player app
38 kAMM_PlayAndRecord //!App takes over audio and has input and output
39} tAudioManagerMode;
40
41/** Possible states of the engine */
42typedef enum {
43 kAMStateUninitialised, //!Audio manager has not been initialised - do not use
44 kAMStateInitialising, //!Audio manager is in the process of initialising - do not use
45 kAMStateInitialised //!Audio manager is initialised - safe to use
46} tAudioManagerState;
47
48typedef enum {
49 kAMRBDoNothing, //Audio manager will not do anything on resign or becoming active
50 kAMRBStopPlay, //Background music is stopped on resign and resumed on become active
51 kAMRBStop //Background music is stopped on resign but not resumed - maybe because you want to do this from within your game
52} tAudioManagerResignBehavior;
53
54/** Notifications */
55extern NSString * const kCDN_AudioManagerInitialised;
56
57@interface CDAsynchInitialiser : NSOperation {}
58@end
59
60/** CDAudioManager supports two long audio source channels called left and right*/
61typedef enum {
62 kASC_Left = 0,
63 kASC_Right = 1
64} tAudioSourceChannel;
65
66typedef enum {
67 kLAS_Init,
68 kLAS_Loaded,
69 kLAS_Playing,
70 kLAS_Paused,
71 kLAS_Stopped,
72} tLongAudioSourceState;
73
74@class CDLongAudioSource;
75@protocol CDLongAudioSourceDelegate <NSObject>
76@optional
77/** The audio source completed playing */
78- (void) cdAudioSourceDidFinishPlaying:(CDLongAudioSource *) audioSource;
79/** The file used to load the audio source has changed */
80- (void) cdAudioSourceFileDidChange:(CDLongAudioSource *) audioSource;
81@end
82
83/**
84 CDLongAudioSource represents an audio source that has a long duration which makes
85 it costly to load into memory for playback as an effect using CDSoundEngine. Examples
86 include background music and narration tracks. The audio file may or may not be compressed.
87 Bear in mind that current iDevices can only use hardware to decode a single compressed
88 audio file at a time and playing multiple compressed files will result in a performance drop
89 as software decompression will take place.
90 @since v0.99
91 */
92@interface CDLongAudioSource : NSObject <AVAudioPlayerDelegate, CDAudioInterruptProtocol>{
93 AVAudioPlayer *audioSourcePlayer;
94 NSString *audioSourceFilePath;
95 NSInteger numberOfLoops;
96 float volume;
97 id<CDLongAudioSourceDelegate> delegate;
98 BOOL mute;
99 BOOL enabled_;
100 BOOL backgroundMusic;
101@public
102 BOOL systemPaused;//Used for auto resign handling
103 NSTimeInterval systemPauseLocation;//Used for auto resign handling
104@protected
105 tLongAudioSourceState state;
106}
107@property (readonly) AVAudioPlayer *audioSourcePlayer;
108@property (readonly) NSString *audioSourceFilePath;
109@property (readwrite, nonatomic) NSInteger numberOfLoops;
110@property (readwrite, nonatomic) float volume;
111@property (assign) id<CDLongAudioSourceDelegate> delegate;
112/* This long audio source functions as background music */
113@property (readwrite, nonatomic) BOOL backgroundMusic;
114
115/** Loads the file into the audio source */
116-(void) load:(NSString*) filePath;
117/** Plays the audio source */
118-(void) play;
119/** Stops playing the audio soruce */
120-(void) stop;
121/** Pauses the audio source */
122-(void) pause;
123/** Rewinds the audio source */
124-(void) rewind;
125/** Resumes playing the audio source if it was paused */
126-(void) resume;
127/** Returns whether or not the audio source is playing */
128-(BOOL) isPlaying;
129
130@end
131
132/**
133 CDAudioManager manages audio requirements for a game. It provides access to a CDSoundEngine object
134 for playing sound effects. It provides access to two CDLongAudioSource object (left and right channel)
135 for playing long duration audio such as background music and narration tracks. Additionally it manages
136 the audio session to take care of things like audio session interruption and interacting with the audio
137 of other apps that are running on the device.
138
139 Requirements:
140 - Firmware: OS 2.2 or greater
141 - Files: CDAudioManager.*, CocosDenshion.*
142 - Frameworks: OpenAL, AudioToolbox, AVFoundation
143 @since v0.8
144 */
145@interface CDAudioManager : NSObject <CDLongAudioSourceDelegate, CDAudioInterruptProtocol, AVAudioSessionDelegate> {
146 CDSoundEngine *soundEngine;
147 CDLongAudioSource *backgroundMusic;
148 NSMutableArray *audioSourceChannels;
149 NSString* _audioSessionCategory;
150 BOOL _audioWasPlayingAtStartup;
151 tAudioManagerMode _mode;
152 SEL backgroundMusicCompletionSelector;
153 id backgroundMusicCompletionListener;
154 BOOL willPlayBackgroundMusic;
155 BOOL _mute;
156 BOOL _resigned;
157 BOOL _interrupted;
158 BOOL _audioSessionActive;
159 BOOL enabled_;
160
161 //For handling resign/become active
162 BOOL _isObservingAppEvents;
163 tAudioManagerResignBehavior _resignBehavior;
164}
165
166@property (readonly) CDSoundEngine *soundEngine;
167@property (readonly) CDLongAudioSource *backgroundMusic;
168@property (readonly) BOOL willPlayBackgroundMusic;
169
170/** Returns the shared singleton */
171+ (CDAudioManager *) sharedManager;
172+ (tAudioManagerState) sharedManagerState;
173/** Configures the shared singleton with a mode*/
174+ (void) configure: (tAudioManagerMode) mode;
175/** Initializes the engine asynchronously with a mode */
176+ (void) initAsynchronously: (tAudioManagerMode) mode;
177/** Initializes the engine synchronously with a mode, channel definition and a total number of channels */
178- (id) init: (tAudioManagerMode) mode;
179-(void) audioSessionInterrupted;
180-(void) audioSessionResumed;
181-(void) setResignBehavior:(tAudioManagerResignBehavior) resignBehavior autoHandle:(BOOL) autoHandle;
182/** Returns true is audio is muted at a hardware level e.g user has ringer switch set to off */
183-(BOOL) isDeviceMuted;
184/** Returns true if another app is playing audio such as the iPod music player */
185-(BOOL) isOtherAudioPlaying;
186/** Sets the way the audio manager interacts with the operating system such as whether it shares output with other apps or obeys the mute switch */
187-(void) setMode:(tAudioManagerMode) mode;
188/** Shuts down the shared audio manager instance so that it can be reinitialised */
189+(void) end;
190
191/** Call if you want to use built in resign behavior but need to do some additional audio processing on resign active. */
192- (void) applicationWillResignActive;
193/** Call if you want to use built in resign behavior but need to do some additional audio processing on become active. */
194- (void) applicationDidBecomeActive;
195
196//New AVAudioPlayer API
197/** Loads the data from the specified file path to the channel's audio source */
198-(CDLongAudioSource*) audioSourceLoad:(NSString*) filePath channel:(tAudioSourceChannel) channel;
199/** Retrieves the audio source for the specified channel */
200-(CDLongAudioSource*) audioSourceForChannel:(tAudioSourceChannel) channel;
201
202//Legacy AVAudioPlayer API
203/** Plays music in background. The music can be looped or not
204 It is recommended to use .aac files as background music since they are decoded by the device (hardware).
205 */
206-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop;
207/** Preloads a background music */
208-(void) preloadBackgroundMusic:(NSString*) filePath;
209/** Stops playing the background music */
210-(void) stopBackgroundMusic;
211/** Pauses the background music */
212-(void) pauseBackgroundMusic;
213/** Rewinds the background music */
214-(void) rewindBackgroundMusic;
215/** Resumes playing the background music */
216-(void) resumeBackgroundMusic;
217/** Returns whether or not the background music is playing */
218-(BOOL) isBackgroundMusicPlaying;
219
220-(void) setBackgroundMusicCompletionListener:(id) listener selector:(SEL) selector;
221
222@end
223
224/** Fader for long audio source objects */
225@interface CDLongAudioSourceFader : CDPropertyModifier{}
226@end
227
228static const int kCDNoBuffer = -1;
229
230/** Allows buffers to be associated with file names */
231@interface CDBufferManager:NSObject{
232 NSMutableDictionary* loadedBuffers;
233 NSMutableArray *freedBuffers;
234 CDSoundEngine *soundEngine;
235 int nextBufferId;
236}
237
238-(id) initWithEngine:(CDSoundEngine *) theSoundEngine;
239-(int) bufferForFile:(NSString*) filePath create:(BOOL) create;
240-(void) releaseBufferForFile:(NSString *) filePath;
241
242@end
243
diff --git a/libs/CocosDenshion/CDAudioManager.m b/libs/CocosDenshion/CDAudioManager.m new file mode 100755 index 0000000..0929f3c --- /dev/null +++ b/libs/CocosDenshion/CDAudioManager.m
@@ -0,0 +1,887 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25
26#import "CDAudioManager.h"
27
28NSString * const kCDN_AudioManagerInitialised = @"kCDN_AudioManagerInitialised";
29
30//NSOperation object used to asynchronously initialise
31@implementation CDAsynchInitialiser
32
33-(void) main {
34 [super main];
35 [CDAudioManager sharedManager];
36}
37
38@end
39
40@implementation CDLongAudioSource
41
42@synthesize audioSourcePlayer, audioSourceFilePath, delegate, backgroundMusic;
43
44-(id) init {
45 if ((self = [super init])) {
46 state = kLAS_Init;
47 volume = 1.0f;
48 mute = NO;
49 enabled_ = YES;
50 }
51 return self;
52}
53
54-(void) dealloc {
55 CDLOGINFO(@"Denshion::CDLongAudioSource - deallocating %@", self);
56 [audioSourcePlayer release];
57 [audioSourceFilePath release];
58 [super dealloc];
59}
60
61-(void) load:(NSString*) filePath {
62 //We have alread loaded a file previously, check if we are being asked to load the same file
63 if (state == kLAS_Init || ![filePath isEqualToString:audioSourceFilePath]) {
64 CDLOGINFO(@"Denshion::CDLongAudioSource - Loading new audio source %@",filePath);
65 //New file
66 if (state != kLAS_Init) {
67 [audioSourceFilePath release];//Release old file path
68 [audioSourcePlayer release];//Release old AVAudioPlayer, they can't be reused
69 }
70 audioSourceFilePath = [filePath copy];
71 NSError *error = nil;
72 NSString *path = [CDUtilities fullPathFromRelativePath:audioSourceFilePath];
73 audioSourcePlayer = [(AVAudioPlayer*)[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
74 if (error == nil) {
75 [audioSourcePlayer prepareToPlay];
76 audioSourcePlayer.delegate = self;
77 if (delegate && [delegate respondsToSelector:@selector(cdAudioSourceFileDidChange:)]) {
78 //Tell our delegate the file has changed
79 [delegate cdAudioSourceFileDidChange:self];
80 }
81 } else {
82 CDLOG(@"Denshion::CDLongAudioSource - Error initialising audio player: %@",error);
83 }
84 } else {
85 //Same file - just return it to a consistent state
86 [self pause];
87 [self rewind];
88 }
89 audioSourcePlayer.volume = volume;
90 audioSourcePlayer.numberOfLoops = numberOfLoops;
91 state = kLAS_Loaded;
92}
93
94-(void) play {
95 if (enabled_) {
96 self->systemPaused = NO;
97 [audioSourcePlayer play];
98 } else {
99 CDLOGINFO(@"Denshion::CDLongAudioSource long audio source didn't play because it is disabled");
100 }
101}
102
103-(void) stop {
104 [audioSourcePlayer stop];
105}
106
107-(void) pause {
108 [audioSourcePlayer pause];
109}
110
111-(void) rewind {
112 [audioSourcePlayer setCurrentTime:0];
113}
114
115-(void) resume {
116 [audioSourcePlayer play];
117}
118
119-(BOOL) isPlaying {
120 if (state != kLAS_Init) {
121 return [audioSourcePlayer isPlaying];
122 } else {
123 return NO;
124 }
125}
126
127-(void) setVolume:(float) newVolume
128{
129 volume = newVolume;
130 if (state != kLAS_Init && !mute) {
131 audioSourcePlayer.volume = newVolume;
132 }
133}
134
135-(float) volume
136{
137 return volume;
138}
139
140#pragma mark Audio Interrupt Protocol
141-(BOOL) mute
142{
143 return mute;
144}
145
146-(void) setMute:(BOOL) muteValue
147{
148 if (mute != muteValue) {
149 if (mute) {
150 //Turn sound back on
151 audioSourcePlayer.volume = volume;
152 } else {
153 audioSourcePlayer.volume = 0.0f;
154 }
155 mute = muteValue;
156 }
157}
158
159-(BOOL) enabled
160{
161 return enabled_;
162}
163
164-(void) setEnabled:(BOOL)enabledValue
165{
166 if (enabledValue != enabled_) {
167 enabled_ = enabledValue;
168 if (!enabled_) {
169 //"Stop" the sounds
170 [self pause];
171 [self rewind];
172 }
173 }
174}
175
176-(NSInteger) numberOfLoops {
177 return numberOfLoops;
178}
179
180-(void) setNumberOfLoops:(NSInteger) loopCount
181{
182 audioSourcePlayer.numberOfLoops = loopCount;
183 numberOfLoops = loopCount;
184}
185
186- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
187 CDLOGINFO(@"Denshion::CDLongAudioSource - audio player finished");
188#if TARGET_IPHONE_SIMULATOR
189 CDLOGINFO(@"Denshion::CDLongAudioSource - workaround for OpenAL clobbered audio issue");
190 //This is a workaround for an issue in all simulators (tested to 3.1.2). Problem is
191 //that OpenAL audio playback is clobbered when an AVAudioPlayer stops. Workaround
192 //is to keep the player playing on an endless loop with 0 volume and then when
193 //it is played again reset the volume and set loop count appropriately.
194 //NB: this workaround is not foolproof but it is good enough for most situations.
195 player.numberOfLoops = -1;
196 player.volume = 0;
197 [player play];
198#endif
199 if (delegate && [delegate respondsToSelector:@selector(cdAudioSourceDidFinishPlaying:)]) {
200 [delegate cdAudioSourceDidFinishPlaying:self];
201 }
202}
203
204-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
205 CDLOGINFO(@"Denshion::CDLongAudioSource - audio player interrupted");
206}
207
208-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player {
209 CDLOGINFO(@"Denshion::CDLongAudioSource - audio player resumed");
210 if (self.backgroundMusic) {
211 //Check if background music can play as rules may have changed during
212 //the interruption. This is to address a specific issue in 4.x when
213 //fast task switching
214 if([CDAudioManager sharedManager].willPlayBackgroundMusic) {
215 [player play];
216 }
217 } else {
218 [player play];
219 }
220}
221
222@end
223
224
225@interface CDAudioManager (PrivateMethods)
226-(BOOL) audioSessionSetActive:(BOOL) active;
227-(BOOL) audioSessionSetCategory:(NSString*) category;
228-(void) badAlContextHandler;
229@end
230
231
232@implementation CDAudioManager
233#define BACKGROUND_MUSIC_CHANNEL kASC_Left
234
235@synthesize soundEngine, willPlayBackgroundMusic;
236static CDAudioManager *sharedManager;
237static tAudioManagerState _sharedManagerState = kAMStateUninitialised;
238static tAudioManagerMode configuredMode;
239static BOOL configured = FALSE;
240
241-(BOOL) audioSessionSetActive:(BOOL) active {
242 NSError *activationError = nil;
243 if ([[AVAudioSession sharedInstance] setActive:active error:&activationError]) {
244 _audioSessionActive = active;
245 CDLOGINFO(@"Denshion::CDAudioManager - Audio session set active %i succeeded", active);
246 return YES;
247 } else {
248 //Failed
249 CDLOG(@"Denshion::CDAudioManager - Audio session set active %i failed with error %@", active, activationError);
250 return NO;
251 }
252}
253
254-(BOOL) audioSessionSetCategory:(NSString*) category {
255 NSError *categoryError = nil;
256 if ([[AVAudioSession sharedInstance] setCategory:category error:&categoryError]) {
257 CDLOGINFO(@"Denshion::CDAudioManager - Audio session set category %@ succeeded", category);
258 return YES;
259 } else {
260 //Failed
261 CDLOG(@"Denshion::CDAudioManager - Audio session set category %@ failed with error %@", category, categoryError);
262 return NO;
263 }
264}
265
266// Init
267+ (CDAudioManager *) sharedManager
268{
269 @synchronized(self) {
270 if (!sharedManager) {
271 if (!configured) {
272 //Set defaults here
273 configuredMode = kAMM_FxPlusMusicIfNoOtherAudio;
274 }
275 sharedManager = [[CDAudioManager alloc] init:configuredMode];
276 _sharedManagerState = kAMStateInitialised;//This is only really relevant when using asynchronous initialisation
277 [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AudioManagerInitialised object:nil];
278 }
279 }
280 return sharedManager;
281}
282
283+ (tAudioManagerState) sharedManagerState {
284 return _sharedManagerState;
285}
286
287/**
288 * Call this to set up audio manager asynchronously. Initialisation is finished when sharedManagerState == kAMStateInitialised
289 */
290+ (void) initAsynchronously: (tAudioManagerMode) mode {
291 @synchronized(self) {
292 if (_sharedManagerState == kAMStateUninitialised) {
293 _sharedManagerState = kAMStateInitialising;
294 [CDAudioManager configure:mode];
295 CDAsynchInitialiser *initOp = [[[CDAsynchInitialiser alloc] init] autorelease];
296 NSOperationQueue *opQ = [[[NSOperationQueue alloc] init] autorelease];
297 [opQ addOperation:initOp];
298 }
299 }
300}
301
302+ (id) alloc
303{
304 @synchronized(self) {
305 NSAssert(sharedManager == nil, @"Attempted to allocate a second instance of a singleton.");
306 return [super alloc];
307 }
308 return nil;
309}
310
311/*
312 * Call this method before accessing the shared manager in order to configure the shared audio manager
313 */
314+ (void) configure: (tAudioManagerMode) mode {
315 configuredMode = mode;
316 configured = TRUE;
317}
318
319-(BOOL) isOtherAudioPlaying {
320 UInt32 isPlaying = 0;
321 UInt32 varSize = sizeof(isPlaying);
322 AudioSessionGetProperty (kAudioSessionProperty_OtherAudioIsPlaying, &varSize, &isPlaying);
323 return (isPlaying != 0);
324}
325
326-(void) setMode:(tAudioManagerMode) mode {
327
328 _mode = mode;
329 switch (_mode) {
330
331 case kAMM_FxOnly:
332 //Share audio with other app
333 CDLOGINFO(@"Denshion::CDAudioManager - Audio will be shared");
334 //_audioSessionCategory = kAudioSessionCategory_AmbientSound;
335 _audioSessionCategory = AVAudioSessionCategoryAmbient;
336 willPlayBackgroundMusic = NO;
337 break;
338
339 case kAMM_FxPlusMusic:
340 //Use audio exclusively - if other audio is playing it will be stopped
341 CDLOGINFO(@"Denshion::CDAudioManager - Audio will be exclusive");
342 //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound;
343 _audioSessionCategory = AVAudioSessionCategorySoloAmbient;
344 willPlayBackgroundMusic = YES;
345 break;
346
347 case kAMM_MediaPlayback:
348 //Use audio exclusively, ignore mute switch and sleep
349 CDLOGINFO(@"Denshion::CDAudioManager - Media playback mode, audio will be exclusive");
350 //_audioSessionCategory = kAudioSessionCategory_MediaPlayback;
351 _audioSessionCategory = AVAudioSessionCategoryPlayback;
352 willPlayBackgroundMusic = YES;
353 break;
354
355 case kAMM_PlayAndRecord:
356 //Use audio exclusively, ignore mute switch and sleep, has inputs and outputs
357 CDLOGINFO(@"Denshion::CDAudioManager - Play and record mode, audio will be exclusive");
358 //_audioSessionCategory = kAudioSessionCategory_PlayAndRecord;
359 _audioSessionCategory = AVAudioSessionCategoryPlayAndRecord;
360 willPlayBackgroundMusic = YES;
361 break;
362
363 default:
364 //kAudioManagerFxPlusMusicIfNoOtherAudio
365 if ([self isOtherAudioPlaying]) {
366 CDLOGINFO(@"Denshion::CDAudioManager - Other audio is playing audio will be shared");
367 //_audioSessionCategory = kAudioSessionCategory_AmbientSound;
368 _audioSessionCategory = AVAudioSessionCategoryAmbient;
369 willPlayBackgroundMusic = NO;
370 } else {
371 CDLOGINFO(@"Denshion::CDAudioManager - Other audio is not playing audio will be exclusive");
372 //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound;
373 _audioSessionCategory = AVAudioSessionCategorySoloAmbient;
374 willPlayBackgroundMusic = YES;
375 }
376
377 break;
378 }
379
380 [self audioSessionSetCategory:_audioSessionCategory];
381
382}
383
384/**
385 * This method is used to work around various bugs introduced in 4.x OS versions. In some circumstances the
386 * audio session is interrupted but never resumed, this results in the loss of OpenAL audio when following
387 * standard practices. If we detect this situation then we will attempt to resume the audio session ourselves.
388 * Known triggers: lock the device then unlock it (iOS 4.2 gm), playback a song using MPMediaPlayer (iOS 4.0)
389 */
390- (void) badAlContextHandler {
391 if (_interrupted && alcGetCurrentContext() == NULL) {
392 CDLOG(@"Denshion::CDAudioManager - bad OpenAL context detected, attempting to resume audio session");
393 [self audioSessionResumed];
394 }
395}
396
397- (id) init: (tAudioManagerMode) mode {
398 if ((self = [super init])) {
399
400 //Initialise the audio session
401 AVAudioSession* session = [AVAudioSession sharedInstance];
402 session.delegate = self;
403
404 _mode = mode;
405 backgroundMusicCompletionSelector = nil;
406 _isObservingAppEvents = FALSE;
407 _mute = NO;
408 _resigned = NO;
409 _interrupted = NO;
410 enabled_ = YES;
411 _audioSessionActive = NO;
412 [self setMode:mode];
413 soundEngine = [[CDSoundEngine alloc] init];
414
415 //Set up audioSource channels
416 audioSourceChannels = [[NSMutableArray alloc] init];
417 CDLongAudioSource *leftChannel = [[CDLongAudioSource alloc] init];
418 leftChannel.backgroundMusic = YES;
419 CDLongAudioSource *rightChannel = [[CDLongAudioSource alloc] init];
420 rightChannel.backgroundMusic = NO;
421 [audioSourceChannels insertObject:leftChannel atIndex:kASC_Left];
422 [audioSourceChannels insertObject:rightChannel atIndex:kASC_Right];
423 [leftChannel release];
424 [rightChannel release];
425 //Used to support legacy APIs
426 backgroundMusic = [self audioSourceForChannel:BACKGROUND_MUSIC_CHANNEL];
427 backgroundMusic.delegate = self;
428
429 //Add handler for bad al context messages, these are posted by the sound engine.
430 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(badAlContextHandler) name:kCDN_BadAlContext object:nil];
431
432 }
433 return self;
434}
435
436-(void) dealloc {
437 CDLOGINFO(@"Denshion::CDAudioManager - deallocating");
438 [self stopBackgroundMusic];
439 [soundEngine release];
440 [[NSNotificationCenter defaultCenter] removeObserver:self];
441 [self audioSessionSetActive:NO];
442 [audioSourceChannels release];
443 [super dealloc];
444}
445
446/** Retrieves the audio source for the specified channel */
447-(CDLongAudioSource*) audioSourceForChannel:(tAudioSourceChannel) channel
448{
449 return (CDLongAudioSource*)[audioSourceChannels objectAtIndex:channel];
450}
451
452/** Loads the data from the specified file path to the channel's audio source */
453-(CDLongAudioSource*) audioSourceLoad:(NSString*) filePath channel:(tAudioSourceChannel) channel
454{
455 CDLongAudioSource *audioSource = [self audioSourceForChannel:channel];
456 if (audioSource) {
457 [audioSource load:filePath];
458 }
459 return audioSource;
460}
461
462-(BOOL) isBackgroundMusicPlaying {
463 return [self.backgroundMusic isPlaying];
464}
465
466//NB: originally I tried using a route change listener and intended to store the current route,
467//however, on a 3gs running 3.1.2 no route change is generated when the user switches the
468//ringer mute switch to off (i.e. enables sound) therefore polling is the only reliable way to
469//determine ringer switch state
470-(BOOL) isDeviceMuted {
471
472#if TARGET_IPHONE_SIMULATOR
473 //Calling audio route stuff on the simulator causes problems
474 return NO;
475#else
476 CFStringRef newAudioRoute;
477 UInt32 propertySize = sizeof (CFStringRef);
478
479 AudioSessionGetProperty (
480 kAudioSessionProperty_AudioRoute,
481 &propertySize,
482 &newAudioRoute
483 );
484
485 if (newAudioRoute == NULL) {
486 //Don't expect this to happen but playing safe otherwise a null in the CFStringCompare will cause a crash
487 return YES;
488 } else {
489 CFComparisonResult newDeviceIsMuted = CFStringCompare (
490 newAudioRoute,
491 (CFStringRef) @"",
492 0
493 );
494
495 return (newDeviceIsMuted == kCFCompareEqualTo);
496 }
497#endif
498}
499
500#pragma mark Audio Interrupt Protocol
501
502-(BOOL) mute {
503 return _mute;
504}
505
506-(void) setMute:(BOOL) muteValue {
507 if (muteValue != _mute) {
508 _mute = muteValue;
509 [soundEngine setMute:muteValue];
510 for( CDLongAudioSource *audioSource in audioSourceChannels) {
511 audioSource.mute = muteValue;
512 }
513 }
514}
515
516-(BOOL) enabled {
517 return enabled_;
518}
519
520-(void) setEnabled:(BOOL) enabledValue {
521 if (enabledValue != enabled_) {
522 enabled_ = enabledValue;
523 [soundEngine setEnabled:enabled_];
524 for( CDLongAudioSource *audioSource in audioSourceChannels) {
525 audioSource.enabled = enabled_;
526 }
527 }
528}
529
530-(CDLongAudioSource*) backgroundMusic
531{
532 return backgroundMusic;
533}
534
535//Load background music ready for playing
536-(void) preloadBackgroundMusic:(NSString*) filePath
537{
538 [self.backgroundMusic load:filePath];
539}
540
541-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop
542{
543 [self.backgroundMusic load:filePath];
544
545 if (!willPlayBackgroundMusic || _mute) {
546 CDLOGINFO(@"Denshion::CDAudioManager - play bgm aborted because audio is not exclusive or sound is muted");
547 return;
548 }
549
550 if (loop) {
551 [self.backgroundMusic setNumberOfLoops:-1];
552 } else {
553 [self.backgroundMusic setNumberOfLoops:0];
554 }
555 [self.backgroundMusic play];
556}
557
558-(void) stopBackgroundMusic
559{
560 [self.backgroundMusic stop];
561}
562
563-(void) pauseBackgroundMusic
564{
565 [self.backgroundMusic pause];
566}
567
568-(void) resumeBackgroundMusic
569{
570 if (!willPlayBackgroundMusic || _mute) {
571 CDLOGINFO(@"Denshion::CDAudioManager - resume bgm aborted because audio is not exclusive or sound is muted");
572 return;
573 }
574
575 [self.backgroundMusic resume];
576}
577
578-(void) rewindBackgroundMusic
579{
580 [self.backgroundMusic rewind];
581}
582
583-(void) setBackgroundMusicCompletionListener:(id) listener selector:(SEL) selector {
584 backgroundMusicCompletionListener = listener;
585 backgroundMusicCompletionSelector = selector;
586}
587
588/*
589 * Call this method to have the audio manager automatically handle application resign and
590 * become active. Pass a tAudioManagerResignBehavior to indicate the desired behavior
591 * for resigning and becoming active again.
592 *
593 * If autohandle is YES then the applicationWillResignActive and applicationDidBecomActive
594 * methods are automatically called, otherwise you must call them yourself at the appropriate time.
595 *
596 * Based on idea of Dominique Bongard
597 */
598-(void) setResignBehavior:(tAudioManagerResignBehavior) resignBehavior autoHandle:(BOOL) autoHandle {
599
600 if (!_isObservingAppEvents && autoHandle) {
601 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:@"UIApplicationWillResignActiveNotification" object:nil];
602 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:@"UIApplicationDidBecomeActiveNotification" object:nil];
603 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil];
604 _isObservingAppEvents = TRUE;
605 }
606 _resignBehavior = resignBehavior;
607}
608
609- (void) applicationWillResignActive {
610 self->_resigned = YES;
611
612 //Set the audio sesssion to one that allows sharing so that other audio won't be clobbered on resume
613 [self audioSessionSetCategory:AVAudioSessionCategoryAmbient];
614
615 switch (_resignBehavior) {
616
617 case kAMRBStopPlay:
618
619 for( CDLongAudioSource *audioSource in audioSourceChannels) {
620 if (audioSource.isPlaying) {
621 audioSource->systemPaused = YES;
622 audioSource->systemPauseLocation = audioSource.audioSourcePlayer.currentTime;
623 [audioSource stop];
624 } else {
625 //Music is either paused or stopped, if it is paused it will be restarted
626 //by OS so we will stop it.
627 audioSource->systemPaused = NO;
628 [audioSource stop];
629 }
630 }
631 break;
632
633 case kAMRBStop:
634 //Stop music regardless of whether it is playing or not because if it was paused
635 //then the OS would resume it
636 for( CDLongAudioSource *audioSource in audioSourceChannels) {
637 [audioSource stop];
638 }
639
640 default:
641 break;
642
643 }
644 CDLOGINFO(@"Denshion::CDAudioManager - handled resign active");
645}
646
647//Called when application resigns active only if setResignBehavior has been called
648- (void) applicationWillResignActive:(NSNotification *) notification
649{
650 [self applicationWillResignActive];
651}
652
653- (void) applicationDidBecomeActive {
654
655 if (self->_resigned) {
656 _resigned = NO;
657 //Reset the mode incase something changed with audio while we were inactive
658 [self setMode:_mode];
659 switch (_resignBehavior) {
660
661 case kAMRBStopPlay:
662
663 //Music had been stopped but stop maintains current time
664 //so playing again will continue from where music was before resign active.
665 //We check if music can be played because while we were inactive the user might have
666 //done something that should force music to not play such as starting a track in the iPod
667 if (self.willPlayBackgroundMusic) {
668 for( CDLongAudioSource *audioSource in audioSourceChannels) {
669 if (audioSource->systemPaused) {
670 [audioSource resume];
671 audioSource->systemPaused = NO;
672 }
673 }
674 }
675 break;
676
677 default:
678 break;
679
680 }
681 CDLOGINFO(@"Denshion::CDAudioManager - audio manager handled become active");
682 }
683}
684
685//Called when application becomes active only if setResignBehavior has been called
686- (void) applicationDidBecomeActive:(NSNotification *) notification
687{
688 [self applicationDidBecomeActive];
689}
690
691//Called when application terminates only if setResignBehavior has been called
692- (void) applicationWillTerminate:(NSNotification *) notification
693{
694 CDLOGINFO(@"Denshion::CDAudioManager - audio manager handling terminate");
695 [self stopBackgroundMusic];
696}
697
698/** The audio source completed playing */
699- (void) cdAudioSourceDidFinishPlaying:(CDLongAudioSource *) audioSource {
700 CDLOGINFO(@"Denshion::CDAudioManager - audio manager got told background music finished");
701 if (backgroundMusicCompletionSelector != nil) {
702 [backgroundMusicCompletionListener performSelector:backgroundMusicCompletionSelector];
703 }
704}
705
706-(void) beginInterruption {
707 CDLOGINFO(@"Denshion::CDAudioManager - begin interruption");
708 [self audioSessionInterrupted];
709}
710
711-(void) endInterruption {
712 CDLOGINFO(@"Denshion::CDAudioManager - end interruption");
713 [self audioSessionResumed];
714}
715
716#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
717-(void) endInterruptionWithFlags:(NSUInteger)flags {
718 CDLOGINFO(@"Denshion::CDAudioManager - interruption ended with flags %i",flags);
719 if (flags == AVAudioSessionInterruptionFlags_ShouldResume) {
720 [self audioSessionResumed];
721 }
722}
723#endif
724
725-(void)audioSessionInterrupted
726{
727 if (!_interrupted) {
728 CDLOGINFO(@"Denshion::CDAudioManager - Audio session interrupted");
729 _interrupted = YES;
730
731 // Deactivate the current audio session
732 [self audioSessionSetActive:NO];
733
734 if (alcGetCurrentContext() != NULL) {
735 CDLOGINFO(@"Denshion::CDAudioManager - Setting OpenAL context to NULL");
736
737 ALenum error = AL_NO_ERROR;
738
739 // set the current context to NULL will 'shutdown' openAL
740 alcMakeContextCurrent(NULL);
741
742 if((error = alGetError()) != AL_NO_ERROR) {
743 CDLOG(@"Denshion::CDAudioManager - Error making context current %x\n", error);
744 }
745 #pragma unused(error)
746 }
747 }
748}
749
750-(void)audioSessionResumed
751{
752 if (_interrupted) {
753 CDLOGINFO(@"Denshion::CDAudioManager - Audio session resumed");
754 _interrupted = NO;
755
756 BOOL activationResult = NO;
757 // Reactivate the current audio session
758 activationResult = [self audioSessionSetActive:YES];
759
760 //This code is to handle a problem with iOS 4.0 and 4.01 where reactivating the session can fail if
761 //task switching is performed too rapidly. A test case that reliably reproduces the issue is to call the
762 //iPhone and then hang up after two rings (timing may vary ;))
763 //Basically we keep waiting and trying to let the OS catch up with itself but the number of tries is
764 //limited.
765 if (!activationResult) {
766 CDLOG(@"Denshion::CDAudioManager - Failure reactivating audio session, will try wait-try cycle");
767 int activateCount = 0;
768 while (!activationResult && activateCount < 10) {
769 [NSThread sleepForTimeInterval:0.5];
770 activationResult = [self audioSessionSetActive:YES];
771 activateCount++;
772 CDLOGINFO(@"Denshion::CDAudioManager - Reactivation attempt %i status = %i",activateCount,activationResult);
773 }
774 }
775
776 if (alcGetCurrentContext() == NULL) {
777 CDLOGINFO(@"Denshion::CDAudioManager - Restoring OpenAL context");
778 ALenum error = AL_NO_ERROR;
779 // Restore open al context
780 alcMakeContextCurrent([soundEngine openALContext]);
781 if((error = alGetError()) != AL_NO_ERROR) {
782 CDLOG(@"Denshion::CDAudioManager - Error making context current%x\n", error);
783 }
784 #pragma unused(error)
785 }
786 }
787}
788
789+(void) end {
790 [sharedManager release];
791 sharedManager = nil;
792}
793
794@end
795
796///////////////////////////////////////////////////////////////////////////////////////
797@implementation CDLongAudioSourceFader
798
799-(void) _setTargetProperty:(float) newVal {
800 ((CDLongAudioSource*)target).volume = newVal;
801}
802
803-(float) _getTargetProperty {
804 return ((CDLongAudioSource*)target).volume;
805}
806
807-(void) _stopTarget {
808 //Pause instead of stop as stop releases resources and causes problems in the simulator
809 [((CDLongAudioSource*)target) pause];
810}
811
812-(Class) _allowableType {
813 return [CDLongAudioSource class];
814}
815
816@end
817///////////////////////////////////////////////////////////////////////////////////////
818@implementation CDBufferManager
819
820-(id) initWithEngine:(CDSoundEngine *) theSoundEngine {
821 if ((self = [super init])) {
822 soundEngine = theSoundEngine;
823 loadedBuffers = [[NSMutableDictionary alloc] initWithCapacity:CD_BUFFERS_START];
824 freedBuffers = [[NSMutableArray alloc] init];
825 nextBufferId = 0;
826 }
827 return self;
828}
829
830-(void) dealloc {
831 [loadedBuffers release];
832 [freedBuffers release];
833 [super dealloc];
834}
835
836-(int) bufferForFile:(NSString*) filePath create:(BOOL) create {
837
838 NSNumber* soundId = (NSNumber*)[loadedBuffers objectForKey:filePath];
839 if(soundId == nil)
840 {
841 if (create) {
842 NSNumber* bufferId = nil;
843 //First try to get a buffer from the free buffers
844 if ([freedBuffers count] > 0) {
845 bufferId = [[[freedBuffers lastObject] retain] autorelease];
846 [freedBuffers removeLastObject];
847 CDLOGINFO(@"Denshion::CDBufferManager reusing buffer id %i",[bufferId intValue]);
848 } else {
849 bufferId = [[NSNumber alloc] initWithInt:nextBufferId];
850 [bufferId autorelease];
851 CDLOGINFO(@"Denshion::CDBufferManager generating new buffer id %i",[bufferId intValue]);
852 nextBufferId++;
853 }
854
855 if ([soundEngine loadBuffer:[bufferId intValue] filePath:filePath]) {
856 //File successfully loaded
857 CDLOGINFO(@"Denshion::CDBufferManager buffer loaded %@ %@",bufferId,filePath);
858 [loadedBuffers setObject:bufferId forKey:filePath];
859 return [bufferId intValue];
860 } else {
861 //File didn't load, put buffer id on free list
862 [freedBuffers addObject:bufferId];
863 return kCDNoBuffer;
864 }
865 } else {
866 //No matching buffer was found
867 return kCDNoBuffer;
868 }
869 } else {
870 return [soundId intValue];
871 }
872}
873
874-(void) releaseBufferForFile:(NSString *) filePath {
875 int bufferId = [self bufferForFile:filePath create:NO];
876 if (bufferId != kCDNoBuffer) {
877 [soundEngine unloadBuffer:bufferId];
878 [loadedBuffers removeObjectForKey:filePath];
879 NSNumber *freedBufferId = [[NSNumber alloc] initWithInt:bufferId];
880 [freedBufferId autorelease];
881 [freedBuffers addObject:freedBufferId];
882 }
883}
884@end
885
886
887
diff --git a/libs/CocosDenshion/CDConfig.h b/libs/CocosDenshion/CDConfig.h new file mode 100755 index 0000000..2bd8f76 --- /dev/null +++ b/libs/CocosDenshion/CDConfig.h
@@ -0,0 +1,60 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24#define COCOSDENSHION_VERSION "Aphex.rc"
25
26
27/**
28 If enabled code useful for debugging such as parameter check assertions will be performed.
29 If you experience any problems you should enable this and test your code with a debug build.
30 */
31//#define CD_DEBUG 1
32
33/**
34 The total number of sounds/buffers that can be loaded assuming memory is sufficient
35 */
36//Number of buffers slots that will be initially created
37#define CD_BUFFERS_START 64
38//Number of buffers that will be added
39#define CD_BUFFERS_INCREMENT 16
40
41/**
42 If enabled, OpenAL code will use static buffers. When static buffers are used the audio
43 data is managed outside of OpenAL, this eliminates a memcpy operation which leads to
44 higher performance when loading sounds.
45
46 However, the downside is that when the audio data is freed you must
47 be certain that it is no longer being accessed otherwise your app will crash. Testing on OS 2.2.1
48 and 3.1.2 has shown that this may occur if a buffer is being used by a source with state = AL_PLAYING
49 when the buffer is deleted. If the data is freed too quickly after the source is stopped then
50 a crash will occur. The implemented workaround is that when static buffers are used the unloadBuffer code will wait for
51 any playing sources to finish playing before the associated buffer and data are deleted, however, this delay may negate any
52 performance gains that are achieved during loading.
53
54 Performance tests on a 1st gen iPod running OS 2.2.1 loading the CocosDenshionDemo sounds were ~0.14 seconds without
55 static buffers and ~0.12 seconds when using static buffers.
56
57 */
58//#define CD_USE_STATIC_BUFFERS 1
59
60
diff --git a/libs/CocosDenshion/CDOpenALSupport.h b/libs/CocosDenshion/CDOpenALSupport.h new file mode 100755 index 0000000..661c69e --- /dev/null +++ b/libs/CocosDenshion/CDOpenALSupport.h
@@ -0,0 +1,77 @@
1/*
2
3 Disclaimer: IMPORTANT: This Apple software is supplied to you by
4 Apple Inc. ("Apple") in consideration of your agreement to the
5 following terms, and your use, installation, modification or
6 redistribution of this Apple software constitutes acceptance of these
7 terms. If you do not agree with these terms, please do not use,
8 install, modify or redistribute this Apple software.
9
10 In consideration of your agreement to abide by the following terms, and
11 subject to these terms, Apple grants you a personal, non-exclusive
12 license, under Apple's copyrights in this original Apple software (the
13 "Apple Software"), to use, reproduce, modify and redistribute the Apple
14 Software, with or without modifications, in source and/or binary forms;
15 provided that if you redistribute the Apple Software in its entirety and
16 without modifications, you must retain this notice and the following
17 text and disclaimers in all such redistributions of the Apple Software.
18 Neither the name, trademarks, service marks or logos of Apple Inc.
19 may be used to endorse or promote products derived from the Apple
20 Software without specific prior written permission from Apple. Except
21 as expressly stated in this notice, no other rights or licenses, express
22 or implied, are granted by Apple herein, including but not limited to
23 any patent rights that may be infringed by your derivative works or by
24 other works in which the Apple Software may be incorporated.
25
26 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31
32 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
40
41 Copyright (C) 2009 Apple Inc. All Rights Reserved.
42
43 $Id$
44 */
45
46/*
47 This file contains code from version 1.1 and 1.4 of MyOpenALSupport.h taken from Apple's oalTouch version.
48 The 1.4 version code is used for loading IMA4 files, however, this code causes very noticeable clicking
49 when used to load wave files that are looped so the 1.1 version code is used specifically for loading
50 wav files.
51 */
52
53#ifndef __CD_OPENAL_H
54#define __CD_OPENAL_H
55
56#ifdef __cplusplus
57extern "C" {
58#endif
59
60
61#import <OpenAL/al.h>
62#import <OpenAL/alc.h>
63#import <CoreFoundation/CFURL.h>
64
65
66//Taken from oalTouch MyOpenALSupport 1.1
67void* CDloadWaveAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate);
68void* CDloadCafAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate);
69void* CDGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate);
70
71#ifdef __cplusplus
72}
73#endif
74
75#endif
76
77
diff --git a/libs/CocosDenshion/CDOpenALSupport.m b/libs/CocosDenshion/CDOpenALSupport.m new file mode 100755 index 0000000..ab0df8e --- /dev/null +++ b/libs/CocosDenshion/CDOpenALSupport.m
@@ -0,0 +1,246 @@
1/*
2
3 Disclaimer: IMPORTANT: This Apple software is supplied to you by
4 Apple Inc. ("Apple") in consideration of your agreement to the
5 following terms, and your use, installation, modification or
6 redistribution of this Apple software constitutes acceptance of these
7 terms. If you do not agree with these terms, please do not use,
8 install, modify or redistribute this Apple software.
9
10 In consideration of your agreement to abide by the following terms, and
11 subject to these terms, Apple grants you a personal, non-exclusive
12 license, under Apple's copyrights in this original Apple software (the
13 "Apple Software"), to use, reproduce, modify and redistribute the Apple
14 Software, with or without modifications, in source and/or binary forms;
15 provided that if you redistribute the Apple Software in its entirety and
16 without modifications, you must retain this notice and the following
17 text and disclaimers in all such redistributions of the Apple Software.
18 Neither the name, trademarks, service marks or logos of Apple Inc.
19 may be used to endorse or promote products derived from the Apple
20 Software without specific prior written permission from Apple. Except
21 as expressly stated in this notice, no other rights or licenses, express
22 or implied, are granted by Apple herein, including but not limited to
23 any patent rights that may be infringed by your derivative works or by
24 other works in which the Apple Software may be incorporated.
25
26 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31
32 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
40
41 Copyright (C) 2009 Apple Inc. All Rights Reserved.
42
43 $Id: CDOpenALSupport.h 16 2010-03-11 06:22:10Z steveoldmeadow $
44 */
45
46#import "CDOpenALSupport.h"
47#import "CocosDenshion.h"
48#import <AudioToolbox/AudioToolbox.h>
49#import <AudioToolbox/ExtendedAudioFile.h>
50
51//Taken from oalTouch MyOpenALSupport 1.1
52void* CDloadWaveAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate)
53{
54 OSStatus err = noErr;
55 UInt64 fileDataSize = 0;
56 AudioStreamBasicDescription theFileFormat;
57 UInt32 thePropertySize = sizeof(theFileFormat);
58 AudioFileID afid = 0;
59 void* theData = NULL;
60
61 // Open a file with ExtAudioFileOpen()
62 err = AudioFileOpenURL(inFileURL, kAudioFileReadPermission, 0, &afid);
63 if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileOpenURL FAILED, Error = %ld\n", err); goto Exit; }
64
65 // Get the audio data format
66 err = AudioFileGetProperty(afid, kAudioFilePropertyDataFormat, &thePropertySize, &theFileFormat);
67 if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileGetProperty(kAudioFileProperty_DataFormat) FAILED, Error = %ld\n", err); goto Exit; }
68
69 if (theFileFormat.mChannelsPerFrame > 2) {
70 CDLOG(@"MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); goto Exit;
71 }
72
73 if ((theFileFormat.mFormatID != kAudioFormatLinearPCM) || (!TestAudioFormatNativeEndian(theFileFormat))) {
74 CDLOG(@"MyGetOpenALAudioData - Unsupported Format, must be little-endian PCM\n"); goto Exit;
75 }
76
77 if ((theFileFormat.mBitsPerChannel != 8) && (theFileFormat.mBitsPerChannel != 16)) {
78 CDLOG(@"MyGetOpenALAudioData - Unsupported Format, must be 8 or 16 bit PCM\n"); goto Exit;
79 }
80
81
82 thePropertySize = sizeof(fileDataSize);
83 err = AudioFileGetProperty(afid, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize);
84 if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileGetProperty(kAudioFilePropertyAudioDataByteCount) FAILED, Error = %ld\n", err); goto Exit; }
85
86 // Read all the data into memory
87 UInt32 dataSize = (UInt32)fileDataSize;
88 theData = malloc(dataSize);
89 if (theData)
90 {
91 AudioFileReadBytes(afid, false, 0, &dataSize, theData);
92 if(err == noErr)
93 {
94 // success
95 *outDataSize = (ALsizei)dataSize;
96 //This fix was added by me, however, 8 bit sounds have a clipping sound at the end so aren't really usable (SO)
97 if (theFileFormat.mBitsPerChannel == 16) {
98 *outDataFormat = (theFileFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
99 } else {
100 *outDataFormat = (theFileFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8;
101 }
102 *outSampleRate = (ALsizei)theFileFormat.mSampleRate;
103 }
104 else
105 {
106 // failure
107 free (theData);
108 theData = NULL; // make sure to return NULL
109 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", err); goto Exit;
110 }
111 }
112
113Exit:
114 // Dispose the ExtAudioFileRef, it is no longer needed
115 if (afid) AudioFileClose(afid);
116 return theData;
117}
118
119//Taken from oalTouch MyOpenALSupport 1.4
120void* CDloadCafAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate)
121{
122 OSStatus status = noErr;
123 BOOL abort = NO;
124 SInt64 theFileLengthInFrames = 0;
125 AudioStreamBasicDescription theFileFormat;
126 UInt32 thePropertySize = sizeof(theFileFormat);
127 ExtAudioFileRef extRef = NULL;
128 void* theData = NULL;
129 AudioStreamBasicDescription theOutputFormat;
130 UInt32 dataSize = 0;
131
132 // Open a file with ExtAudioFileOpen()
133 status = ExtAudioFileOpenURL(inFileURL, &extRef);
134 if (status != noErr)
135 {
136 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %ld\n", status);
137 abort = YES;
138 }
139 if (abort)
140 goto Exit;
141
142 // Get the audio data format
143 status = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat);
144 if (status != noErr)
145 {
146 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %ld\n", status);
147 abort = YES;
148 }
149 if (abort)
150 goto Exit;
151
152 if (theFileFormat.mChannelsPerFrame > 2)
153 {
154 CDLOG(@"MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n");
155 abort = YES;
156 }
157 if (abort)
158 goto Exit;
159
160 // Set the client format to 16 bit signed integer (native-endian) data
161 // Maintain the channel count and sample rate of the original source format
162 theOutputFormat.mSampleRate = theFileFormat.mSampleRate;
163 theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame;
164
165 theOutputFormat.mFormatID = kAudioFormatLinearPCM;
166 theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame;
167 theOutputFormat.mFramesPerPacket = 1;
168 theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame;
169 theOutputFormat.mBitsPerChannel = 16;
170 theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
171
172 // Set the desired client (output) data format
173 status = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat);
174 if (status != noErr)
175 {
176 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %ld\n", status);
177 abort = YES;
178 }
179 if (abort)
180 goto Exit;
181
182 // Get the total frame count
183 thePropertySize = sizeof(theFileLengthInFrames);
184 status = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames);
185 if (status != noErr)
186 {
187 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %ld\n", status);
188 abort = YES;
189 }
190 if (abort)
191 goto Exit;
192
193 // Read all the data into memory
194 dataSize = (UInt32) theFileLengthInFrames * theOutputFormat.mBytesPerFrame;
195 theData = malloc(dataSize);
196 if (theData)
197 {
198 AudioBufferList theDataBuffer;
199 theDataBuffer.mNumberBuffers = 1;
200 theDataBuffer.mBuffers[0].mDataByteSize = dataSize;
201 theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame;
202 theDataBuffer.mBuffers[0].mData = theData;
203
204 // Read the data into an AudioBufferList
205 status = ExtAudioFileRead(extRef, (UInt32*)&theFileLengthInFrames, &theDataBuffer);
206 if(status == noErr)
207 {
208 // success
209 *outDataSize = (ALsizei)dataSize;
210 *outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
211 *outSampleRate = (ALsizei)theOutputFormat.mSampleRate;
212 }
213 else
214 {
215 // failure
216 free (theData);
217 theData = NULL; // make sure to return NULL
218 CDLOG(@"MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", status);
219 abort = YES;
220 }
221 }
222 if (abort)
223 goto Exit;
224
225Exit:
226 // Dispose the ExtAudioFileRef, it is no longer needed
227 if (extRef) ExtAudioFileDispose(extRef);
228 return theData;
229}
230
231void* CDGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate) {
232
233 CFStringRef extension = CFURLCopyPathExtension(inFileURL);
234 CFComparisonResult isWavFile = 0;
235 if (extension != NULL) {
236 isWavFile = CFStringCompare (extension,(CFStringRef)@"wav", kCFCompareCaseInsensitive);
237 CFRelease(extension);
238 }
239
240 if (isWavFile == kCFCompareEqualTo) {
241 return CDloadWaveAudioData(inFileURL, outDataSize, outDataFormat, outSampleRate);
242 } else {
243 return CDloadCafAudioData(inFileURL, outDataSize, outDataFormat, outSampleRate);
244 }
245}
246
diff --git a/libs/CocosDenshion/CocosDenshion.h b/libs/CocosDenshion/CocosDenshion.h new file mode 100755 index 0000000..638d852 --- /dev/null +++ b/libs/CocosDenshion/CocosDenshion.h
@@ -0,0 +1,440 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25
26
27/**
28@file
29@b IMPORTANT
30There are 3 different ways of using CocosDenshion. Depending on which you choose you
31will need to include different files and frameworks.
32
33@par SimpleAudioEngine
34This is recommended for basic audio requirements. If you just want to play some sound fx
35and some background music and have no interest in learning the lower level workings then
36this is the interface to use.
37
38Requirements:
39 - Firmware: OS 2.2 or greater
40 - Files: SimpleAudioEngine.*, CocosDenshion.*
41 - Frameworks: OpenAL, AudioToolbox, AVFoundation
42
43@par CDAudioManager
44CDAudioManager is basically a thin wrapper around an AVAudioPlayer object used for playing
45background music and a CDSoundEngine object used for playing sound effects. It manages the
46audio session for you deals with audio session interruption. It is fairly low level and it
47is expected you have some understanding of the underlying technologies. For example, for
48many use cases regarding background music it is expected you will work directly with the
49backgroundMusic AVAudioPlayer which is exposed as a property.
50
51Requirements:
52 - Firmware: OS 2.2 or greater
53 - Files: CDAudioManager.*, CocosDenshion.*
54 - Frameworks: OpenAL, AudioToolbox, AVFoundation
55
56@par CDSoundEngine
57CDSoundEngine is a sound engine built upon OpenAL and derived from Apple's oalTouch
58example. It can playback up to 32 sounds simultaneously with control over pitch, pan
59and gain. It can be set up to handle audio session interruption automatically. You
60may decide to use CDSoundEngine directly instead of CDAudioManager or SimpleAudioEngine
61because you require OS 2.0 compatibility.
62
63Requirements:
64 - Firmware: OS 2.0 or greater
65 - Files: CocosDenshion.*
66 - Frameworks: OpenAL, AudioToolbox
67
68*/
69
70#import <OpenAL/al.h>
71#import <OpenAL/alc.h>
72#import <AudioToolbox/AudioToolbox.h>
73#import <Foundation/Foundation.h>
74#import "CDConfig.h"
75
76
77#if !defined(CD_DEBUG) || CD_DEBUG == 0
78#define CDLOG(...) do {} while (0)
79#define CDLOGINFO(...) do {} while (0)
80
81#elif CD_DEBUG == 1
82#define CDLOG(...) NSLog(__VA_ARGS__)
83#define CDLOGINFO(...) do {} while (0)
84
85#elif CD_DEBUG > 1
86#define CDLOG(...) NSLog(__VA_ARGS__)
87#define CDLOGINFO(...) NSLog(__VA_ARGS__)
88#endif // CD_DEBUG
89
90
91#import "CDOpenALSupport.h"
92
93//Tested source limit on 2.2.1 and 3.1.2 with up to 128 sources and appears to work. Older OS versions e.g 2.2 may support only 32
94#define CD_SOURCE_LIMIT 32 //Total number of sources we will ever want, may actually get less
95#define CD_NO_SOURCE 0xFEEDFAC //Return value indicating playback failed i.e. no source
96#define CD_IGNORE_AUDIO_SESSION 0xBEEFBEE //Used internally to indicate audio session will not be handled
97#define CD_MUTE 0xFEEDBAB //Return value indicating sound engine is muted or non functioning
98#define CD_NO_SOUND = -1;
99
100#define CD_SAMPLE_RATE_HIGH 44100
101#define CD_SAMPLE_RATE_MID 22050
102#define CD_SAMPLE_RATE_LOW 16000
103#define CD_SAMPLE_RATE_BASIC 8000
104#define CD_SAMPLE_RATE_DEFAULT 44100
105
106extern NSString * const kCDN_BadAlContext;
107extern NSString * const kCDN_AsynchLoadComplete;
108
109extern float const kCD_PitchDefault;
110extern float const kCD_PitchLowerOneOctave;
111extern float const kCD_PitchHigherOneOctave;
112extern float const kCD_PanDefault;
113extern float const kCD_PanFullLeft;
114extern float const kCD_PanFullRight;
115extern float const kCD_GainDefault;
116
117enum bufferState {
118 CD_BS_EMPTY = 0,
119 CD_BS_LOADED = 1,
120 CD_BS_FAILED = 2
121};
122
123typedef struct _sourceGroup {
124 int startIndex;
125 int currentIndex;
126 int totalSources;
127 bool enabled;
128 bool nonInterruptible;
129 int *sourceStatuses;//pointer into array of source status information
130} sourceGroup;
131
132typedef struct _bufferInfo {
133 ALuint bufferId;
134 int bufferState;
135 void* bufferData;
136 ALenum format;
137 ALsizei sizeInBytes;
138 ALsizei frequencyInHertz;
139} bufferInfo;
140
141typedef struct _sourceInfo {
142 bool usable;
143 ALuint sourceId;
144 ALuint attachedBufferId;
145} sourceInfo;
146
147#pragma mark CDAudioTransportProtocol
148
149@protocol CDAudioTransportProtocol <NSObject>
150/** Play the audio */
151-(BOOL) play;
152/** Pause the audio, retain resources */
153-(BOOL) pause;
154/** Stop the audio, release resources */
155-(BOOL) stop;
156/** Return playback to beginning */
157-(BOOL) rewind;
158@end
159
160#pragma mark CDAudioInterruptProtocol
161
162@protocol CDAudioInterruptProtocol <NSObject>
163/** Is audio mute */
164-(BOOL) mute;
165/** If YES then audio is silenced but not stopped, calls to start new audio will proceed but silently */
166-(void) setMute:(BOOL) muteValue;
167/** Is audio enabled */
168-(BOOL) enabled;
169/** If NO then all audio is stopped and any calls to start new audio will be ignored */
170-(void) setEnabled:(BOOL) enabledValue;
171@end
172
173#pragma mark CDUtilities
174/**
175 Collection of utilities required by CocosDenshion
176 */
177@interface CDUtilities : NSObject
178{
179}
180
181/** Fundamentally the same as the corresponding method is CCFileUtils but added to break binding to cocos2d */
182+(NSString*) fullPathFromRelativePath:(NSString*) relPath;
183
184@end
185
186
187#pragma mark CDSoundEngine
188
189/** CDSoundEngine is built upon OpenAL and works with SDK 2.0.
190 CDSoundEngine is a sound engine built upon OpenAL and derived from Apple's oalTouch
191 example. It can playback up to 32 sounds simultaneously with control over pitch, pan
192 and gain. It can be set up to handle audio session interruption automatically. You
193 may decide to use CDSoundEngine directly instead of CDAudioManager or SimpleAudioEngine
194 because you require OS 2.0 compatibility.
195
196 Requirements:
197 - Firmware: OS 2.0 or greater
198 - Files: CocosDenshion.*
199 - Frameworks: OpenAL, AudioToolbox
200
201 @since v0.8
202 */
203@class CDSoundSource;
204@interface CDSoundEngine : NSObject <CDAudioInterruptProtocol> {
205
206 bufferInfo *_buffers;
207 sourceInfo *_sources;
208 sourceGroup *_sourceGroups;
209 ALCcontext *context;
210 NSUInteger _sourceGroupTotal;
211 UInt32 _audioSessionCategory;
212 BOOL _handleAudioSession;
213 ALfloat _preMuteGain;
214 NSObject *_mutexBufferLoad;
215 BOOL mute_;
216 BOOL enabled_;
217
218 ALenum lastErrorCode_;
219 BOOL functioning_;
220 float asynchLoadProgress_;
221 BOOL getGainWorks_;
222
223 //For managing dynamic allocation of sources and buffers
224 int sourceTotal_;
225 int bufferTotal;
226
227}
228
229@property (readwrite, nonatomic) ALfloat masterGain;
230@property (readonly) ALenum lastErrorCode;//Last OpenAL error code that was generated
231@property (readonly) BOOL functioning;//Is the sound engine functioning
232@property (readwrite) float asynchLoadProgress;
233@property (readonly) BOOL getGainWorks;//Does getting the gain for a source work
234/** Total number of sources available */
235@property (readonly) int sourceTotal;
236/** Total number of source groups that have been defined */
237@property (readonly) NSUInteger sourceGroupTotal;
238
239/** Sets the sample rate for the audio mixer. For best performance this should match the sample rate of your audio content */
240+(void) setMixerSampleRate:(Float32) sampleRate;
241
242/** Initializes the engine with a group definition and a total number of groups */
243-(id)init;
244
245/** Plays a sound in a channel group with a pitch, pan and gain. The sound could played looped or not */
246-(ALuint) playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop;
247
248/** Creates and returns a sound source object for the specified sound within the specified source group.
249 */
250-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId;
251
252/** Stops playing a sound */
253- (void) stopSound:(ALuint) sourceId;
254/** Stops playing a source group */
255- (void) stopSourceGroup:(int) sourceGroupId;
256/** Stops all playing sounds */
257-(void) stopAllSounds;
258-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions;
259-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total;
260-(void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible;
261-(void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled;
262-(BOOL) sourceGroupEnabled:(int) sourceGroupId;
263-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq;
264-(BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath;
265-(void) loadBuffersAsynchronously:(NSArray *) loadRequests;
266-(BOOL) unloadBuffer:(int) soundId;
267-(ALCcontext *) openALContext;
268
269/** Returns the duration of the buffer in seconds or a negative value if the buffer id is invalid */
270-(float) bufferDurationInSeconds:(int) soundId;
271/** Returns the size of the buffer in bytes or a negative value if the buffer id is invalid */
272-(ALsizei) bufferSizeInBytes:(int) soundId;
273/** Returns the sampling frequency of the buffer in hertz or a negative value if the buffer id is invalid */
274-(ALsizei) bufferFrequencyInHertz:(int) soundId;
275
276/** Used internally, never call unless you know what you are doing */
277-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource;
278
279@end
280
281#pragma mark CDSoundSource
282/** CDSoundSource is a wrapper around an OpenAL sound source.
283 It allows you to manipulate properties such as pitch, gain, pan and looping while the
284 sound is playing. CDSoundSource is based on the old CDSourceWrapper class but with much
285 added functionality.
286
287 @since v1.0
288 */
289@interface CDSoundSource : NSObject <CDAudioTransportProtocol, CDAudioInterruptProtocol> {
290 ALenum lastError;
291@public
292 ALuint _sourceId;
293 ALuint _sourceIndex;
294 CDSoundEngine* _engine;
295 int _soundId;
296 float _preMuteGain;
297 BOOL enabled_;
298 BOOL mute_;
299}
300@property (readwrite, nonatomic) float pitch;
301@property (readwrite, nonatomic) float gain;
302@property (readwrite, nonatomic) float pan;
303@property (readwrite, nonatomic) BOOL looping;
304@property (readonly) BOOL isPlaying;
305@property (readwrite, nonatomic) int soundId;
306/** Returns the duration of the attached buffer in seconds or a negative value if the buffer is invalid */
307@property (readonly) float durationInSeconds;
308
309/** Stores the last error code that occurred. Check against AL_NO_ERROR */
310@property (readonly) ALenum lastError;
311/** Do not init yourself, get an instance from the sourceForSound factory method on CDSoundEngine */
312-(id)init:(ALuint) theSourceId sourceIndex:(int) index soundEngine:(CDSoundEngine*) engine;
313
314@end
315
316#pragma mark CDAudioInterruptTargetGroup
317
318/** Container for objects that implement audio interrupt protocol i.e. they can be muted and enabled.
319 Setting mute and enabled for the group propagates to all children.
320 Designed to be used with your CDSoundSource objects to get them to comply with global enabled and mute settings
321 if that is what you want to do.*/
322@interface CDAudioInterruptTargetGroup : NSObject <CDAudioInterruptProtocol> {
323 BOOL mute_;
324 BOOL enabled_;
325 NSMutableArray *children_;
326}
327-(void) addAudioInterruptTarget:(NSObject<CDAudioInterruptProtocol>*) interruptibleTarget;
328@end
329
330#pragma mark CDAsynchBufferLoader
331
332/** CDAsynchBufferLoader
333 TODO
334 */
335@interface CDAsynchBufferLoader : NSOperation {
336 NSArray *_loadRequests;
337 CDSoundEngine *_soundEngine;
338}
339
340-(id) init:(NSArray *)loadRequests soundEngine:(CDSoundEngine *) theSoundEngine;
341
342@end
343
344#pragma mark CDBufferLoadRequest
345
346/** CDBufferLoadRequest */
347@interface CDBufferLoadRequest: NSObject
348{
349 NSString *filePath;
350 int soundId;
351 //id loader;
352}
353
354@property (readonly) NSString *filePath;
355@property (readonly) int soundId;
356
357- (id)init:(int) theSoundId filePath:(const NSString *) theFilePath;
358@end
359
360/** Interpolation type */
361typedef enum {
362 kIT_Linear, //!Straight linear interpolation fade
363 kIT_SCurve, //!S curved interpolation
364 kIT_Exponential //!Exponential interpolation
365} tCDInterpolationType;
366
367#pragma mark CDFloatInterpolator
368@interface CDFloatInterpolator: NSObject
369{
370 float start;
371 float end;
372 float lastValue;
373 tCDInterpolationType interpolationType;
374}
375@property (readwrite, nonatomic) float start;
376@property (readwrite, nonatomic) float end;
377@property (readwrite, nonatomic) tCDInterpolationType interpolationType;
378
379/** Return a value between min and max based on t which represents fractional progress where 0 is the start
380 and 1 is the end */
381-(float) interpolate:(float) t;
382-(id) init:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal;
383
384@end
385
386#pragma mark CDPropertyModifier
387
388/** Base class for classes that modify properties such as pitch, pan and gain */
389@interface CDPropertyModifier: NSObject
390{
391 CDFloatInterpolator *interpolator;
392 float startValue;
393 float endValue;
394 id target;
395 BOOL stopTargetWhenComplete;
396
397}
398@property (readwrite, nonatomic) BOOL stopTargetWhenComplete;
399@property (readwrite, nonatomic) float startValue;
400@property (readwrite, nonatomic) float endValue;
401@property (readwrite, nonatomic) tCDInterpolationType interpolationType;
402
403-(id) init:(id) theTarget interpolationType:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal;
404/** Set to a fractional value between 0 and 1 where 0 equals the start and 1 equals the end*/
405-(void) modify:(float) t;
406
407-(void) _setTargetProperty:(float) newVal;
408-(float) _getTargetProperty;
409-(void) _stopTarget;
410-(Class) _allowableType;
411
412@end
413
414#pragma mark CDSoundSourceFader
415
416/** Fader for CDSoundSource objects */
417@interface CDSoundSourceFader : CDPropertyModifier{}
418@end
419
420#pragma mark CDSoundSourcePanner
421
422/** Panner for CDSoundSource objects */
423@interface CDSoundSourcePanner : CDPropertyModifier{}
424@end
425
426#pragma mark CDSoundSourcePitchBender
427
428/** Pitch bender for CDSoundSource objects */
429@interface CDSoundSourcePitchBender : CDPropertyModifier{}
430@end
431
432#pragma mark CDSoundEngineFader
433
434/** Fader for CDSoundEngine objects */
435@interface CDSoundEngineFader : CDPropertyModifier{}
436@end
437
438
439
440
diff --git a/libs/CocosDenshion/CocosDenshion.m b/libs/CocosDenshion/CocosDenshion.m new file mode 100755 index 0000000..6956c3a --- /dev/null +++ b/libs/CocosDenshion/CocosDenshion.m
@@ -0,0 +1,1602 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25#import "CocosDenshion.h"
26
27ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq);
28ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value);
29
30
31typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq);
32ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq)
33{
34 static alBufferDataStaticProcPtr proc = NULL;
35
36 if (proc == NULL) {
37 proc = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic");
38 }
39
40 if (proc)
41 proc(bid, format, data, size, freq);
42
43 return;
44}
45
46typedef ALvoid AL_APIENTRY (*alcMacOSXMixerOutputRateProcPtr) (const ALdouble value);
47ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value)
48{
49 static alcMacOSXMixerOutputRateProcPtr proc = NULL;
50
51 if (proc == NULL) {
52 proc = (alcMacOSXMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXMixerOutputRate");
53 }
54
55 if (proc)
56 proc(value);
57
58 return;
59}
60
61NSString * const kCDN_BadAlContext = @"kCDN_BadAlContext";
62NSString * const kCDN_AsynchLoadComplete = @"kCDN_AsynchLoadComplete";
63float const kCD_PitchDefault = 1.0f;
64float const kCD_PitchLowerOneOctave = 0.5f;
65float const kCD_PitchHigherOneOctave = 2.0f;
66float const kCD_PanDefault = 0.0f;
67float const kCD_PanFullLeft = -1.0f;
68float const kCD_PanFullRight = 1.0f;
69float const kCD_GainDefault = 1.0f;
70
71@interface CDSoundEngine (PrivateMethods)
72-(BOOL) _initOpenAL;
73-(void) _testGetGain;
74-(void) _dumpSourceGroupsInfo;
75-(void) _getSourceIndexForSourceGroup;
76-(void) _freeSourceGroups;
77-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total;
78@end
79
80#pragma mark -
81#pragma mark CDUtilities
82
83@implementation CDUtilities
84
85+(NSString*) fullPathFromRelativePath:(NSString*) relPath
86{
87 // do not convert an absolute path (starting with '/')
88 if(([relPath length] > 0) && ([relPath characterAtIndex:0] == '/'))
89 {
90 return relPath;
91 }
92
93 NSMutableArray *imagePathComponents = [NSMutableArray arrayWithArray:[relPath pathComponents]];
94 NSString *file = [imagePathComponents lastObject];
95
96 [imagePathComponents removeLastObject];
97 NSString *imageDirectory = [NSString pathWithComponents:imagePathComponents];
98
99 NSString *fullpath = [[NSBundle mainBundle] pathForResource:file ofType:nil inDirectory:imageDirectory];
100 if (fullpath == nil)
101 fullpath = relPath;
102
103 return fullpath;
104}
105
106@end
107
108#pragma mark -
109#pragma mark CDSoundEngine
110
111@implementation CDSoundEngine
112
113static Float32 _mixerSampleRate;
114static BOOL _mixerRateSet = NO;
115
116@synthesize lastErrorCode = lastErrorCode_;
117@synthesize functioning = functioning_;
118@synthesize asynchLoadProgress = asynchLoadProgress_;
119@synthesize getGainWorks = getGainWorks_;
120@synthesize sourceTotal = sourceTotal_;
121
122+ (void) setMixerSampleRate:(Float32) sampleRate {
123 _mixerRateSet = YES;
124 _mixerSampleRate = sampleRate;
125}
126
127- (void) _testGetGain {
128 float testValue = 0.7f;
129 ALuint testSourceId = _sources[0].sourceId;
130 alSourcef(testSourceId, AL_GAIN, 0.0f);//Start from know value
131 alSourcef(testSourceId, AL_GAIN, testValue);
132 ALfloat gainVal;
133 alGetSourcef(testSourceId, AL_GAIN, &gainVal);
134 getGainWorks_ = (gainVal == testValue);
135}
136
137//Generate sources one at a time until we fail
138-(void) _generateSources {
139
140 _sources = (sourceInfo*)malloc( sizeof(_sources[0]) * CD_SOURCE_LIMIT);
141 BOOL hasFailed = NO;
142 sourceTotal_ = 0;
143 alGetError();//Clear error
144 while (!hasFailed && sourceTotal_ < CD_SOURCE_LIMIT) {
145 alGenSources(1, &(_sources[sourceTotal_].sourceId));
146 if (alGetError() == AL_NO_ERROR) {
147 //Now try attaching source to null buffer
148 alSourcei(_sources[sourceTotal_].sourceId, AL_BUFFER, 0);
149 if (alGetError() == AL_NO_ERROR) {
150 _sources[sourceTotal_].usable = true;
151 sourceTotal_++;
152 } else {
153 hasFailed = YES;
154 }
155 } else {
156 _sources[sourceTotal_].usable = false;
157 hasFailed = YES;
158 }
159 }
160 //Mark the rest of the sources as not usable
161 for (int i=sourceTotal_; i < CD_SOURCE_LIMIT; i++) {
162 _sources[i].usable = false;
163 }
164}
165
166-(void) _generateBuffers:(int) startIndex endIndex:(int) endIndex {
167 if (_buffers) {
168 alGetError();
169 for (int i=startIndex; i <= endIndex; i++) {
170 alGenBuffers(1, &_buffers[i].bufferId);
171 _buffers[i].bufferData = NULL;
172 if (alGetError() == AL_NO_ERROR) {
173 _buffers[i].bufferState = CD_BS_EMPTY;
174 } else {
175 _buffers[i].bufferState = CD_BS_FAILED;
176 CDLOG(@"Denshion::CDSoundEngine - buffer creation failed %i",i);
177 }
178 }
179 }
180}
181
182/**
183 * Internal method called during init
184 */
185- (BOOL) _initOpenAL
186{
187 //ALenum error;
188 context = NULL;
189 ALCdevice *newDevice = NULL;
190
191 //Set the mixer rate for the audio mixer
192 if (!_mixerRateSet) {
193 _mixerSampleRate = CD_SAMPLE_RATE_DEFAULT;
194 }
195 alcMacOSXMixerOutputRateProc(_mixerSampleRate);
196 CDLOGINFO(@"Denshion::CDSoundEngine - mixer output rate set to %0.2f",_mixerSampleRate);
197
198 // Create a new OpenAL Device
199 // Pass NULL to specify the system's default output device
200 newDevice = alcOpenDevice(NULL);
201 if (newDevice != NULL)
202 {
203 // Create a new OpenAL Context
204 // The new context will render to the OpenAL Device just created
205 context = alcCreateContext(newDevice, 0);
206 if (context != NULL)
207 {
208 // Make the new context the Current OpenAL Context
209 alcMakeContextCurrent(context);
210
211 // Create some OpenAL Buffer Objects
212 [self _generateBuffers:0 endIndex:bufferTotal-1];
213
214 // Create some OpenAL Source Objects
215 [self _generateSources];
216
217 }
218 } else {
219 return FALSE;//No device
220 }
221 alGetError();//Clear error
222 return TRUE;
223}
224
225- (void) dealloc {
226
227 ALCcontext *currentContext = NULL;
228 ALCdevice *device = NULL;
229
230 [self stopAllSounds];
231
232 CDLOGINFO(@"Denshion::CDSoundEngine - Deallocing sound engine.");
233 [self _freeSourceGroups];
234
235 // Delete the Sources
236 CDLOGINFO(@"Denshion::CDSoundEngine - deleting sources.");
237 for (int i=0; i < sourceTotal_; i++) {
238 alSourcei(_sources[i].sourceId, AL_BUFFER, 0);//Detach from current buffer
239 alDeleteSources(1, &(_sources[i].sourceId));
240 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
241 CDLOG(@"Denshion::CDSoundEngine - Error deleting source! %x\n", lastErrorCode_);
242 }
243 }
244
245 // Delete the Buffers
246 CDLOGINFO(@"Denshion::CDSoundEngine - deleting buffers.");
247 for (int i=0; i < bufferTotal; i++) {
248 alDeleteBuffers(1, &_buffers[i].bufferId);
249#ifdef CD_USE_STATIC_BUFFERS
250 if (_buffers[i].bufferData) {
251 free(_buffers[i].bufferData);
252 }
253#endif
254 }
255 CDLOGINFO(@"Denshion::CDSoundEngine - free buffers.");
256 free(_buffers);
257 currentContext = alcGetCurrentContext();
258 //Get device for active context
259 device = alcGetContextsDevice(currentContext);
260 //Release context
261 CDLOGINFO(@"Denshion::CDSoundEngine - destroy context.");
262 alcDestroyContext(currentContext);
263 //Close device
264 CDLOGINFO(@"Denshion::CDSoundEngine - close device.");
265 alcCloseDevice(device);
266 CDLOGINFO(@"Denshion::CDSoundEngine - free sources.");
267 free(_sources);
268
269 //Release mutexes
270 [_mutexBufferLoad release];
271
272 [super dealloc];
273}
274
275-(NSUInteger) sourceGroupTotal {
276 return _sourceGroupTotal;
277}
278
279-(void) _freeSourceGroups
280{
281 CDLOGINFO(@"Denshion::CDSoundEngine freeing source groups");
282 if(_sourceGroups) {
283 for (int i=0; i < _sourceGroupTotal; i++) {
284 if (_sourceGroups[i].sourceStatuses) {
285 free(_sourceGroups[i].sourceStatuses);
286 CDLOGINFO(@"Denshion::CDSoundEngine freed source statuses %i",i);
287 }
288 }
289 free(_sourceGroups);
290 }
291}
292
293-(BOOL) _redefineSourceGroups:(int[]) definitions total:(NSUInteger) total
294{
295 if (_sourceGroups) {
296 //Stop all sounds
297 [self stopAllSounds];
298 //Need to free source groups
299 [self _freeSourceGroups];
300 }
301 return [self _setUpSourceGroups:definitions total:total];
302}
303
304-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total
305{
306 _sourceGroups = (sourceGroup *)malloc( sizeof(_sourceGroups[0]) * total);
307 if(!_sourceGroups) {
308 CDLOG(@"Denshion::CDSoundEngine - source groups memory allocation failed");
309 return NO;
310 }
311
312 _sourceGroupTotal = total;
313 int sourceCount = 0;
314 for (int i=0; i < _sourceGroupTotal; i++) {
315
316 _sourceGroups[i].startIndex = 0;
317 _sourceGroups[i].currentIndex = _sourceGroups[i].startIndex;
318 _sourceGroups[i].enabled = false;
319 _sourceGroups[i].nonInterruptible = false;
320 _sourceGroups[i].totalSources = definitions[i];
321 _sourceGroups[i].sourceStatuses = malloc(sizeof(_sourceGroups[i].sourceStatuses[0]) * _sourceGroups[i].totalSources);
322 if (_sourceGroups[i].sourceStatuses) {
323 for (int j=0; j < _sourceGroups[i].totalSources; j++) {
324 //First bit is used to indicate whether source is locked, index is shifted back 1 bit
325 _sourceGroups[i].sourceStatuses[j] = (sourceCount + j) << 1;
326 }
327 }
328 sourceCount += definitions[i];
329 }
330 return YES;
331}
332
333-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total {
334 [self _redefineSourceGroups:sourceGroupDefinitions total:total];
335}
336
337-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions {
338 CDLOGINFO(@"Denshion::CDSoundEngine - source groups defined by NSArray.");
339 NSUInteger totalDefs = [sourceGroupDefinitions count];
340 int* defs = (int *)malloc( sizeof(int) * totalDefs);
341 int currentIndex = 0;
342 for (id currentDef in sourceGroupDefinitions) {
343 if ([currentDef isKindOfClass:[NSNumber class]]) {
344 defs[currentIndex] = (int)[(NSNumber*)currentDef integerValue];
345 CDLOGINFO(@"Denshion::CDSoundEngine - found definition %i.",defs[currentIndex]);
346 } else {
347 CDLOG(@"Denshion::CDSoundEngine - warning, did not understand source definition.");
348 defs[currentIndex] = 0;
349 }
350 currentIndex++;
351 }
352 [self _redefineSourceGroups:defs total:totalDefs];
353 free(defs);
354}
355
356- (id)init
357{
358 if ((self = [super init])) {
359
360 //Create mutexes
361 _mutexBufferLoad = [[NSObject alloc] init];
362
363 asynchLoadProgress_ = 0.0f;
364
365 bufferTotal = CD_BUFFERS_START;
366 _buffers = (bufferInfo *)malloc( sizeof(_buffers[0]) * bufferTotal);
367
368 // Initialize our OpenAL environment
369 if ([self _initOpenAL]) {
370 //Set up the default source group - a single group that contains all the sources
371 int sourceDefs[1];
372 sourceDefs[0] = self.sourceTotal;
373 [self _setUpSourceGroups:sourceDefs total:1];
374
375 functioning_ = YES;
376 //Synchronize premute gain
377 _preMuteGain = self.masterGain;
378 mute_ = NO;
379 enabled_ = YES;
380 //Test whether get gain works for sources
381 [self _testGetGain];
382 } else {
383 //Something went wrong with OpenAL
384 functioning_ = NO;
385 }
386 }
387
388 return self;
389}
390
391/**
392 * Delete the buffer identified by soundId
393 * @return true if buffer deleted successfully, otherwise false
394 */
395- (BOOL) unloadBuffer:(int) soundId
396{
397 //Ensure soundId is within array bounds otherwise memory corruption will occur
398 if (soundId < 0 || soundId >= bufferTotal) {
399 CDLOG(@"Denshion::CDSoundEngine - soundId is outside array bounds, maybe you need to increase CD_MAX_BUFFERS");
400 return FALSE;
401 }
402
403 //Before a buffer can be deleted any sources that are attached to it must be stopped
404 for (int i=0; i < sourceTotal_; i++) {
405 //Note: tried getting the AL_BUFFER attribute of the source instead but doesn't
406 //appear to work on a device - just returned zero.
407 if (_buffers[soundId].bufferId == _sources[i].attachedBufferId) {
408
409 CDLOG(@"Denshion::CDSoundEngine - Found attached source %i %i %i",i,_buffers[soundId].bufferId,_sources[i].sourceId);
410#ifdef CD_USE_STATIC_BUFFERS
411 //When using static buffers a crash may occur if a source is playing with a buffer that is about
412 //to be deleted even though we stop the source and successfully delete the buffer. Crash is confirmed
413 //on 2.2.1 and 3.1.2, however, it will only occur if a source is used rapidly after having its prior
414 //data deleted. To avoid any possibility of the crash we wait for the source to finish playing.
415 ALint state;
416
417 alGetSourcei(_sources[i].sourceId, AL_SOURCE_STATE, &state);
418
419 if (state == AL_PLAYING) {
420 CDLOG(@"Denshion::CDSoundEngine - waiting for source to complete playing before removing buffer data");
421 alSourcei(_sources[i].sourceId, AL_LOOPING, FALSE);//Turn off looping otherwise loops will never end
422 while (state == AL_PLAYING) {
423 alGetSourcei(_sources[i].sourceId, AL_SOURCE_STATE, &state);
424 usleep(10000);
425 }
426 }
427#endif
428 //Stop source and detach
429 alSourceStop(_sources[i].sourceId);
430 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
431 CDLOG(@"Denshion::CDSoundEngine - error stopping source: %x\n", lastErrorCode_);
432 }
433
434 alSourcei(_sources[i].sourceId, AL_BUFFER, 0);//Attach to "NULL" buffer to detach
435 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
436 CDLOG(@"Denshion::CDSoundEngine - error detaching buffer: %x\n", lastErrorCode_);
437 } else {
438 //Record that source is now attached to nothing
439 _sources[i].attachedBufferId = 0;
440 }
441 }
442 }
443
444 alDeleteBuffers(1, &_buffers[soundId].bufferId);
445 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
446 CDLOG(@"Denshion::CDSoundEngine - error deleting buffer: %x\n", lastErrorCode_);
447 _buffers[soundId].bufferState = CD_BS_FAILED;
448 return FALSE;
449 } else {
450#ifdef CD_USE_STATIC_BUFFERS
451 //Free previous data, if alDeleteBuffer has returned without error then no
452 if (_buffers[soundId].bufferData) {
453 CDLOGINFO(@"Denshion::CDSoundEngine - freeing static data for soundId %i @ %i",soundId,_buffers[soundId].bufferData);
454 free(_buffers[soundId].bufferData);//Free the old data
455 _buffers[soundId].bufferData = NULL;
456 }
457#endif
458 }
459
460 alGenBuffers(1, &_buffers[soundId].bufferId);
461 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
462 CDLOG(@"Denshion::CDSoundEngine - error regenerating buffer: %x\n", lastErrorCode_);
463 _buffers[soundId].bufferState = CD_BS_FAILED;
464 return FALSE;
465 } else {
466 //We now have an empty buffer
467 _buffers[soundId].bufferState = CD_BS_EMPTY;
468 CDLOGINFO(@"Denshion::CDSoundEngine - buffer %i successfully unloaded\n",soundId);
469 return TRUE;
470 }
471}
472
473/**
474 * Load buffers asynchronously
475 * Check asynchLoadProgress for progress. asynchLoadProgress represents fraction of completion. When it equals 1.0 loading
476 * is complete. NB: asynchLoadProgress is simply based on the number of load requests, it does not take into account
477 * file sizes.
478 * @param An array of CDBufferLoadRequest objects
479 */
480- (void) loadBuffersAsynchronously:(NSArray *) loadRequests {
481 @synchronized(self) {
482 asynchLoadProgress_ = 0.0f;
483 CDAsynchBufferLoader *loaderOp = [[[CDAsynchBufferLoader alloc] init:loadRequests soundEngine:self] autorelease];
484 NSOperationQueue *opQ = [[[NSOperationQueue alloc] init] autorelease];
485 [opQ addOperation:loaderOp];
486 }
487}
488
489-(BOOL) _resizeBuffers:(int) increment {
490
491 void * tmpBufferInfos = realloc( _buffers, sizeof(_buffers[0]) * (bufferTotal + increment) );
492
493 if(!tmpBufferInfos) {
494 free(tmpBufferInfos);
495 return NO;
496 } else {
497 _buffers = tmpBufferInfos;
498 int oldBufferTotal = bufferTotal;
499 bufferTotal = bufferTotal + increment;
500 [self _generateBuffers:oldBufferTotal endIndex:bufferTotal-1];
501 return YES;
502 }
503}
504
505-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq {
506
507 @synchronized(_mutexBufferLoad) {
508
509 if (!functioning_) {
510 //OpenAL initialisation has previously failed
511 CDLOG(@"Denshion::CDSoundEngine - Loading buffer failed because sound engine state != functioning");
512 return FALSE;
513 }
514
515 //Ensure soundId is within array bounds otherwise memory corruption will occur
516 if (soundId < 0) {
517 CDLOG(@"Denshion::CDSoundEngine - soundId is negative");
518 return FALSE;
519 }
520
521 if (soundId >= bufferTotal) {
522 //Need to resize the buffers
523 int requiredIncrement = CD_BUFFERS_INCREMENT;
524 while (bufferTotal + requiredIncrement < soundId) {
525 requiredIncrement += CD_BUFFERS_INCREMENT;
526 }
527 CDLOGINFO(@"Denshion::CDSoundEngine - attempting to resize buffers by %i for sound %i",requiredIncrement,soundId);
528 if (![self _resizeBuffers:requiredIncrement]) {
529 CDLOG(@"Denshion::CDSoundEngine - buffer resize failed");
530 return FALSE;
531 }
532 }
533
534 if (soundData)
535 {
536 if (_buffers[soundId].bufferState != CD_BS_EMPTY) {
537 CDLOGINFO(@"Denshion::CDSoundEngine - non empty buffer, regenerating");
538 if (![self unloadBuffer:soundId]) {
539 //Deletion of buffer failed, delete buffer routine has set buffer state and lastErrorCode
540 return NO;
541 }
542 }
543
544#ifdef CD_DEBUG
545 //Check that sample rate matches mixer rate and warn if they do not
546 if (freq != (int)_mixerSampleRate) {
547 CDLOGINFO(@"Denshion::CDSoundEngine - WARNING sample rate does not match mixer sample rate performance may not be optimal.");
548 }
549#endif
550
551#ifdef CD_USE_STATIC_BUFFERS
552 alBufferDataStaticProc(_buffers[soundId].bufferId, format, soundData, size, freq);
553 _buffers[soundId].bufferData = data;//Save the pointer to the new data
554#else
555 alBufferData(_buffers[soundId].bufferId, format, soundData, size, freq);
556#endif
557 if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) {
558 CDLOG(@"Denshion::CDSoundEngine - error attaching audio to buffer: %x", lastErrorCode_);
559 _buffers[soundId].bufferState = CD_BS_FAILED;
560 return FALSE;
561 }
562 } else {
563 CDLOG(@"Denshion::CDSoundEngine Buffer data is null!");
564 _buffers[soundId].bufferState = CD_BS_FAILED;
565 return FALSE;
566 }
567
568 _buffers[soundId].format = format;
569 _buffers[soundId].sizeInBytes = size;
570 _buffers[soundId].frequencyInHertz = freq;
571 _buffers[soundId].bufferState = CD_BS_LOADED;
572 CDLOGINFO(@"Denshion::CDSoundEngine Buffer %i loaded format:%i freq:%i size:%i",soundId,format,freq,size);
573 return TRUE;
574 }//end mutex
575}
576
577/**
578 * Load sound data for later play back.
579 * @return TRUE if buffer loaded okay for play back otherwise false
580 */
581- (BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath
582{
583
584 ALvoid* data;
585 ALenum format;
586 ALsizei size;
587 ALsizei freq;
588
589 CDLOGINFO(@"Denshion::CDSoundEngine - Loading openAL buffer %i %@", soundId, filePath);
590
591 CFURLRef fileURL = nil;
592 NSString *path = [CDUtilities fullPathFromRelativePath:filePath];
593 if (path) {
594 fileURL = (CFURLRef)[[NSURL fileURLWithPath:path] retain];
595 }
596
597 if (fileURL)
598 {
599 data = CDGetOpenALAudioData(fileURL, &size, &format, &freq);
600 CFRelease(fileURL);
601 BOOL result = [self loadBufferFromData:soundId soundData:data format:format size:size freq:freq];
602#ifndef CD_USE_STATIC_BUFFERS
603 free(data);//Data can be freed here because alBufferData performs a memcpy
604#endif
605 return result;
606 } else {
607 CDLOG(@"Denshion::CDSoundEngine Could not find file!\n");
608 //Don't change buffer state here as it will be the same as before method was called
609 return FALSE;
610 }
611}
612
613-(BOOL) validateBufferId:(int) soundId {
614 if (soundId < 0 || soundId >= bufferTotal) {
615 CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId buffer outside range %i",soundId);
616 return NO;
617 } else if (_buffers[soundId].bufferState != CD_BS_LOADED) {
618 CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId invalide buffer state %i",soundId);
619 return NO;
620 } else {
621 return YES;
622 }
623}
624
625-(float) bufferDurationInSeconds:(int) soundId {
626 if ([self validateBufferId:soundId]) {
627 float factor = 0.0f;
628 switch (_buffers[soundId].format) {
629 case AL_FORMAT_MONO8:
630 factor = 1.0f;
631 break;
632 case AL_FORMAT_MONO16:
633 factor = 0.5f;
634 break;
635 case AL_FORMAT_STEREO8:
636 factor = 0.5f;
637 break;
638 case AL_FORMAT_STEREO16:
639 factor = 0.25f;
640 break;
641 }
642 return (float)_buffers[soundId].sizeInBytes/(float)_buffers[soundId].frequencyInHertz * factor;
643 } else {
644 return -1.0f;
645 }
646}
647
648-(ALsizei) bufferSizeInBytes:(int) soundId {
649 if ([self validateBufferId:soundId]) {
650 return _buffers[soundId].sizeInBytes;
651 } else {
652 return -1.0f;
653 }
654}
655
656-(ALsizei) bufferFrequencyInHertz:(int) soundId {
657 if ([self validateBufferId:soundId]) {
658 return _buffers[soundId].frequencyInHertz;
659 } else {
660 return -1.0f;
661 }
662}
663
664- (ALfloat) masterGain {
665 if (mute_) {
666 //When mute the real gain will always be 0 therefore return the preMuteGain value
667 return _preMuteGain;
668 } else {
669 ALfloat gain;
670 alGetListenerf(AL_GAIN, &gain);
671 return gain;
672 }
673}
674
675/**
676 * Overall gain setting multiplier. e.g 0.5 is half the gain.
677 */
678- (void) setMasterGain:(ALfloat) newGainValue {
679 if (mute_) {
680 _preMuteGain = newGainValue;
681 } else {
682 alListenerf(AL_GAIN, newGainValue);
683 }
684}
685
686#pragma mark CDSoundEngine AudioInterrupt protocol
687- (BOOL) mute {
688 return mute_;
689}
690
691/**
692 * Setting mute silences all sounds but playing sounds continue to advance playback
693 */
694- (void) setMute:(BOOL) newMuteValue {
695
696 if (newMuteValue == mute_) {
697 return;
698 }
699
700 mute_ = newMuteValue;
701 if (mute_) {
702 //Remember what the gain was
703 _preMuteGain = self.masterGain;
704 //Set gain to 0 - do not use the property as this will adjust preMuteGain when muted
705 alListenerf(AL_GAIN, 0.0f);
706 } else {
707 //Restore gain to what it was before being muted
708 self.masterGain = _preMuteGain;
709 }
710}
711
712- (BOOL) enabled {
713 return enabled_;
714}
715
716- (void) setEnabled:(BOOL)enabledValue
717{
718 if (enabled_ == enabledValue) {
719 return;
720 }
721 enabled_ = enabledValue;
722 if (enabled_ == NO) {
723 [self stopAllSounds];
724 }
725}
726
727-(void) _lockSource:(int) sourceIndex lock:(BOOL) lock {
728 BOOL found = NO;
729 for (int i=0; i < _sourceGroupTotal && !found; i++) {
730 if (_sourceGroups[i].sourceStatuses) {
731 for (int j=0; j < _sourceGroups[i].totalSources && !found; j++) {
732 //First bit is used to indicate whether source is locked, index is shifted back 1 bit
733 if((_sourceGroups[i].sourceStatuses[j] >> 1)==sourceIndex) {
734 if (lock) {
735 //Set first bit to lock this source
736 _sourceGroups[i].sourceStatuses[j] |= 1;
737 } else {
738 //Unset first bit to unlock this source
739 _sourceGroups[i].sourceStatuses[j] &= ~1;
740 }
741 found = YES;
742 }
743 }
744 }
745 }
746}
747
748-(int) _getSourceIndexForSourceGroup:(int)sourceGroupId
749{
750 //Ensure source group id is valid to prevent memory corruption
751 if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) {
752 CDLOG(@"Denshion::CDSoundEngine invalid source group id %i",sourceGroupId);
753 return CD_NO_SOURCE;
754 }
755
756 int sourceIndex = -1;//Using -1 to indicate no source found
757 BOOL complete = NO;
758 ALint sourceState = 0;
759 sourceGroup *thisSourceGroup = &_sourceGroups[sourceGroupId];
760 thisSourceGroup->currentIndex = thisSourceGroup->startIndex;
761 while (!complete) {
762 //Iterate over sources looking for one that is not locked, first bit indicates if source is locked
763 if ((thisSourceGroup->sourceStatuses[thisSourceGroup->currentIndex] & 1) == 0) {
764 //This source is not locked
765 sourceIndex = thisSourceGroup->sourceStatuses[thisSourceGroup->currentIndex] >> 1;//shift back to get the index
766 if (thisSourceGroup->nonInterruptible) {
767 //Check if this source is playing, if so it can't be interrupted
768 alGetSourcei(_sources[sourceIndex].sourceId, AL_SOURCE_STATE, &sourceState);
769 if (sourceState != AL_PLAYING) {
770 //complete = YES;
771 //Set start index so next search starts at the next position
772 thisSourceGroup->startIndex = thisSourceGroup->currentIndex + 1;
773 break;
774 } else {
775 sourceIndex = -1;//The source index was no good because the source was playing
776 }
777 } else {
778 //complete = YES;
779 //Set start index so next search starts at the next position
780 thisSourceGroup->startIndex = thisSourceGroup->currentIndex + 1;
781 break;
782 }
783 }
784 thisSourceGroup->currentIndex++;
785 if (thisSourceGroup->currentIndex >= thisSourceGroup->totalSources) {
786 //Reset to the beginning
787 thisSourceGroup->currentIndex = 0;
788 }
789 if (thisSourceGroup->currentIndex == thisSourceGroup->startIndex) {
790 //We have looped around and got back to the start
791 complete = YES;
792 }
793 }
794
795 //Reset start index to beginning if beyond bounds
796 if (thisSourceGroup->startIndex >= thisSourceGroup->totalSources) {
797 thisSourceGroup->startIndex = 0;
798 }
799
800 if (sourceIndex >= 0) {
801 return sourceIndex;
802 } else {
803 return CD_NO_SOURCE;
804 }
805
806}
807
808/**
809 * Play a sound.
810 * @param soundId the id of the sound to play (buffer id).
811 * @param SourceGroupId the source group that will be used to play the sound.
812 * @param pitch pitch multiplier. e.g 1.0 is unaltered, 0.5 is 1 octave lower.
813 * @param pan stereo position. -1 is fully left, 0 is centre and 1 is fully right.
814 * @param gain gain multiplier. e.g. 1.0 is unaltered, 0.5 is half the gain
815 * @param loop should the sound be looped or one shot.
816 * @return the id of the source being used to play the sound or CD_MUTE if the sound engine is muted or non functioning
817 * or CD_NO_SOURCE if a problem occurs setting up the source
818 *
819 */
820- (ALuint)playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop {
821
822#ifdef CD_DEBUG
823 //Sanity check parameters - only in DEBUG
824 NSAssert(soundId >= 0, @"soundId can not be negative");
825 NSAssert(soundId < bufferTotal, @"soundId exceeds limit");
826 NSAssert(sourceGroupId >= 0, @"sourceGroupId can not be negative");
827 NSAssert(sourceGroupId < _sourceGroupTotal, @"sourceGroupId exceeds limit");
828 NSAssert(pitch > 0, @"pitch must be greater than zero");
829 NSAssert(pan >= -1 && pan <= 1, @"pan must be between -1 and 1");
830 NSAssert(gain >= 0, @"gain can not be negative");
831#endif
832 //If mute or initialisation has failed or buffer is not loaded then do nothing
833 if (!enabled_ || !functioning_ || _buffers[soundId].bufferState != CD_BS_LOADED || _sourceGroups[sourceGroupId].enabled) {
834#ifdef CD_DEBUG
835 if (!functioning_) {
836 CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because sound engine is not functioning");
837 } else if (_buffers[soundId].bufferState != CD_BS_LOADED) {
838 CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because buffer %i is not loaded", soundId);
839 }
840#endif
841 return CD_MUTE;
842 }
843
844 int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId];//This method ensures sourceIndex is valid
845
846 if (sourceIndex != CD_NO_SOURCE) {
847 ALint state;
848 ALuint source = _sources[sourceIndex].sourceId;
849 ALuint buffer = _buffers[soundId].bufferId;
850 alGetError();//Clear the error code
851 alGetSourcei(source, AL_SOURCE_STATE, &state);
852 if (state == AL_PLAYING) {
853 alSourceStop(source);
854 }
855 alSourcei(source, AL_BUFFER, buffer);//Attach to sound
856 alSourcef(source, AL_PITCH, pitch);//Set pitch
857 alSourcei(source, AL_LOOPING, loop);//Set looping
858 alSourcef(source, AL_GAIN, gain);//Set gain/volume
859 float sourcePosAL[] = {pan, 0.0f, 0.0f};//Set position - just using left and right panning
860 alSourcefv(source, AL_POSITION, sourcePosAL);
861 alGetError();//Clear the error code
862 alSourcePlay(source);
863 if((lastErrorCode_ = alGetError()) == AL_NO_ERROR) {
864 //Everything was okay
865 _sources[sourceIndex].attachedBufferId = buffer;
866 return source;
867 } else {
868 if (alcGetCurrentContext() == NULL) {
869 CDLOGINFO(@"Denshion::CDSoundEngine - posting bad OpenAL context message");
870 [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil];
871 }
872 return CD_NO_SOURCE;
873 }
874 } else {
875 return CD_NO_SOURCE;
876 }
877}
878
879-(BOOL) _soundSourceAttachToBuffer:(CDSoundSource*) soundSource soundId:(int) soundId {
880 //Attach the source to the buffer
881 ALint state;
882 ALuint source = soundSource->_sourceId;
883 ALuint buffer = _buffers[soundId].bufferId;
884 alGetSourcei(source, AL_SOURCE_STATE, &state);
885 if (state == AL_PLAYING) {
886 alSourceStop(source);
887 }
888 alGetError();//Clear the error code
889 alSourcei(source, AL_BUFFER, buffer);//Attach to sound data
890 if((lastErrorCode_ = alGetError()) == AL_NO_ERROR) {
891 _sources[soundSource->_sourceIndex].attachedBufferId = buffer;
892 //_sourceBufferAttachments[soundSource->_sourceIndex] = buffer;//Keep track of which
893 soundSource->_soundId = soundId;
894 return YES;
895 } else {
896 return NO;
897 }
898}
899
900/**
901 * Get a sound source for the specified sound in the specified source group
902 */
903-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId
904{
905 if (!functioning_) {
906 return nil;
907 }
908 //Check if a source is available
909 int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId];
910 if (sourceIndex != CD_NO_SOURCE) {
911 CDSoundSource *result = [[CDSoundSource alloc] init:_sources[sourceIndex].sourceId sourceIndex:sourceIndex soundEngine:self];
912 [self _lockSource:sourceIndex lock:YES];
913 //Try to attach to the buffer
914 if ([self _soundSourceAttachToBuffer:result soundId:soundId]) {
915 //Set to a known state
916 result.pitch = 1.0f;
917 result.pan = 0.0f;
918 result.gain = 1.0f;
919 result.looping = NO;
920 return [result autorelease];
921 } else {
922 //Release the sound source we just created, this will also unlock the source
923 [result release];
924 return nil;
925 }
926 } else {
927 //No available source within that source group
928 return nil;
929 }
930}
931
932-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource {
933 CDLOGINFO(@"Denshion::CDSoundEngine _soundSourcePreRelease %i",soundSource->_sourceIndex);
934 //Unlock the sound source's source
935 [self _lockSource:soundSource->_sourceIndex lock:NO];
936}
937
938/**
939 * Stop all sounds playing within a source group
940 */
941- (void) stopSourceGroup:(int) sourceGroupId {
942
943 if (!functioning_ || sourceGroupId >= _sourceGroupTotal || sourceGroupId < 0) {
944 return;
945 }
946 int sourceCount = _sourceGroups[sourceGroupId].totalSources;
947 for (int i=0; i < sourceCount; i++) {
948 int sourceIndex = _sourceGroups[sourceGroupId].sourceStatuses[i] >> 1;
949 alSourceStop(_sources[sourceIndex].sourceId);
950 }
951 alGetError();//Clear error in case we stopped any sounds that couldn't be stopped
952}
953
954/**
955 * Stop a sound playing.
956 * @param sourceId an OpenAL source identifier i.e. the return value of playSound
957 */
958- (void)stopSound:(ALuint) sourceId {
959 if (!functioning_) {
960 return;
961 }
962 alSourceStop(sourceId);
963 alGetError();//Clear error in case we stopped any sounds that couldn't be stopped
964}
965
966- (void) stopAllSounds {
967 for (int i=0; i < sourceTotal_; i++) {
968 alSourceStop(_sources[i].sourceId);
969 }
970 alGetError();//Clear error in case we stopped any sounds that couldn't be stopped
971}
972
973/**
974 * Set a source group as non interruptible. Default is that source groups are interruptible.
975 * Non interruptible means that if a request to play a sound is made for a source group and there are
976 * no free sources available then the play request will be ignored and CD_NO_SOURCE will be returned.
977 */
978- (void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible {
979 //Ensure source group id is valid to prevent memory corruption
980 if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) {
981 CDLOG(@"Denshion::CDSoundEngine setSourceGroupNonInterruptible invalid source group id %i",sourceGroupId);
982 return;
983 }
984
985 if (isNonInterruptible) {
986 _sourceGroups[sourceGroupId].nonInterruptible = true;
987 } else {
988 _sourceGroups[sourceGroupId].nonInterruptible = false;
989 }
990}
991
992/**
993 * Set the mute property for a source group. If mute is turned on any sounds in that source group
994 * will be stopped and further sounds in that source group will play. However, turning mute off
995 * will not restart any sounds that were playing when mute was turned on. Also the mute setting
996 * for the sound engine must be taken into account. If the sound engine is mute no sounds will play
997 * no matter what the source group mute setting is.
998 */
999- (void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled {
1000 //Ensure source group id is valid to prevent memory corruption
1001 if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) {
1002 CDLOG(@"Denshion::CDSoundEngine setSourceGroupEnabled invalid source group id %i",sourceGroupId);
1003 return;
1004 }
1005
1006 if (enabled) {
1007 _sourceGroups[sourceGroupId].enabled = true;
1008 [self stopSourceGroup:sourceGroupId];
1009 } else {
1010 _sourceGroups[sourceGroupId].enabled = false;
1011 }
1012}
1013
1014/**
1015 * Return the mute property for the source group identified by sourceGroupId
1016 */
1017- (BOOL) sourceGroupEnabled:(int) sourceGroupId {
1018 return _sourceGroups[sourceGroupId].enabled;
1019}
1020
1021-(ALCcontext *) openALContext {
1022 return context;
1023}
1024
1025- (void) _dumpSourceGroupsInfo {
1026#ifdef CD_DEBUG
1027 CDLOGINFO(@"-------------- source Group Info --------------");
1028 for (int i=0; i < _sourceGroupTotal; i++) {
1029 CDLOGINFO(@"Group: %i start:%i total:%i",i,_sourceGroups[i].startIndex, _sourceGroups[i].totalSources);
1030 CDLOGINFO(@"----- mute:%i nonInterruptible:%i",_sourceGroups[i].enabled, _sourceGroups[i].nonInterruptible);
1031 CDLOGINFO(@"----- Source statuses ----");
1032 for (int j=0; j < _sourceGroups[i].totalSources; j++) {
1033 CDLOGINFO(@"Source status:%i index=%i locked=%i",j,_sourceGroups[i].sourceStatuses[j] >> 1, _sourceGroups[i].sourceStatuses[j] & 1);
1034 }
1035 }
1036#endif
1037}
1038
1039@end
1040
1041///////////////////////////////////////////////////////////////////////////////////////
1042@implementation CDSoundSource
1043
1044@synthesize lastError;
1045
1046//Macro for handling the al error code
1047#define CDSOUNDSOURCE_UPDATE_LAST_ERROR (lastError = alGetError())
1048#define CDSOUNDSOURCE_ERROR_HANDLER ( CDSOUNDSOURCE_UPDATE_LAST_ERROR == AL_NO_ERROR)
1049
1050-(id)init:(ALuint) theSourceId sourceIndex:(int) index soundEngine:(CDSoundEngine*) engine {
1051 if ((self = [super init])) {
1052 _sourceId = theSourceId;
1053 _engine = engine;
1054 _sourceIndex = index;
1055 enabled_ = YES;
1056 mute_ = NO;
1057 _preMuteGain = self.gain;
1058 }
1059 return self;
1060}
1061
1062-(void) dealloc
1063{
1064 CDLOGINFO(@"Denshion::CDSoundSource deallocated %i",self->_sourceIndex);
1065
1066 //Notify sound engine we are about to release
1067 [_engine _soundSourcePreRelease:self];
1068 [super dealloc];
1069}
1070
1071- (void) setPitch:(float) newPitchValue {
1072 alSourcef(_sourceId, AL_PITCH, newPitchValue);
1073 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1074}
1075
1076- (void) setGain:(float) newGainValue {
1077 if (!mute_) {
1078 alSourcef(_sourceId, AL_GAIN, newGainValue);
1079 } else {
1080 _preMuteGain = newGainValue;
1081 }
1082 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1083}
1084
1085- (void) setPan:(float) newPanValue {
1086 float sourcePosAL[] = {newPanValue, 0.0f, 0.0f};//Set position - just using left and right panning
1087 alSourcefv(_sourceId, AL_POSITION, sourcePosAL);
1088 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1089
1090}
1091
1092- (void) setLooping:(BOOL) newLoopingValue {
1093 alSourcei(_sourceId, AL_LOOPING, newLoopingValue);
1094 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1095
1096}
1097
1098- (BOOL) isPlaying {
1099 ALint state;
1100 alGetSourcei(_sourceId, AL_SOURCE_STATE, &state);
1101 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1102 return (state == AL_PLAYING);
1103}
1104
1105- (float) pitch {
1106 ALfloat pitchVal;
1107 alGetSourcef(_sourceId, AL_PITCH, &pitchVal);
1108 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1109 return pitchVal;
1110}
1111
1112- (float) pan {
1113 ALfloat sourcePosAL[] = {0.0f,0.0f,0.0f};
1114 alGetSourcefv(_sourceId, AL_POSITION, sourcePosAL);
1115 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1116 return sourcePosAL[0];
1117}
1118
1119- (float) gain {
1120 if (!mute_) {
1121 ALfloat val;
1122 alGetSourcef(_sourceId, AL_GAIN, &val);
1123 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1124 return val;
1125 } else {
1126 return _preMuteGain;
1127 }
1128}
1129
1130- (BOOL) looping {
1131 ALfloat val;
1132 alGetSourcef(_sourceId, AL_LOOPING, &val);
1133 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1134 return val;
1135}
1136
1137-(BOOL) stop {
1138 alSourceStop(_sourceId);
1139 return CDSOUNDSOURCE_ERROR_HANDLER;
1140}
1141
1142-(BOOL) play {
1143 if (enabled_) {
1144 alSourcePlay(_sourceId);
1145 CDSOUNDSOURCE_UPDATE_LAST_ERROR;
1146 if (lastError != AL_NO_ERROR) {
1147 if (alcGetCurrentContext() == NULL) {
1148 CDLOGINFO(@"Denshion::CDSoundSource - posting bad OpenAL context message");
1149 [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil];
1150 }
1151 return NO;
1152 } else {
1153 return YES;
1154 }
1155 } else {
1156 return NO;
1157 }
1158}
1159
1160-(BOOL) pause {
1161 alSourcePause(_sourceId);
1162 return CDSOUNDSOURCE_ERROR_HANDLER;
1163}
1164
1165-(BOOL) rewind {
1166 alSourceRewind(_sourceId);
1167 return CDSOUNDSOURCE_ERROR_HANDLER;
1168}
1169
1170-(void) setSoundId:(int) soundId {
1171 [_engine _soundSourceAttachToBuffer:self soundId:soundId];
1172}
1173
1174-(int) soundId {
1175 return _soundId;
1176}
1177
1178-(float) durationInSeconds {
1179 return [_engine bufferDurationInSeconds:_soundId];
1180}
1181
1182#pragma mark CDSoundSource AudioInterrupt protocol
1183- (BOOL) mute {
1184 return mute_;
1185}
1186
1187/**
1188 * Setting mute silences all sounds but playing sounds continue to advance playback
1189 */
1190- (void) setMute:(BOOL) newMuteValue {
1191
1192 if (newMuteValue == mute_) {
1193 return;
1194 }
1195
1196 if (newMuteValue) {
1197 //Remember what the gain was
1198 _preMuteGain = self.gain;
1199 self.gain = 0.0f;
1200 mute_ = newMuteValue;//Make sure this is done after setting the gain property as the setter behaves differently depending on mute value
1201 } else {
1202 //Restore gain to what it was before being muted
1203 mute_ = newMuteValue;
1204 self.gain = _preMuteGain;
1205 }
1206}
1207
1208- (BOOL) enabled {
1209 return enabled_;
1210}
1211
1212- (void) setEnabled:(BOOL)enabledValue
1213{
1214 if (enabled_ == enabledValue) {
1215 return;
1216 }
1217 enabled_ = enabledValue;
1218 if (enabled_ == NO) {
1219 [self stop];
1220 }
1221}
1222
1223@end
1224
1225////////////////////////////////////////////////////////////////////////////
1226#pragma mark -
1227#pragma mark CDAudioInterruptTargetGroup
1228
1229@implementation CDAudioInterruptTargetGroup
1230
1231-(id) init {
1232 if ((self = [super init])) {
1233 children_ = [[NSMutableArray alloc] initWithCapacity:32];
1234 enabled_ = YES;
1235 mute_ = NO;
1236 }
1237 return self;
1238}
1239
1240-(void) addAudioInterruptTarget:(NSObject<CDAudioInterruptProtocol>*) interruptibleTarget {
1241 //Synchronize child with group settings;
1242 [interruptibleTarget setMute:mute_];
1243 [interruptibleTarget setEnabled:enabled_];
1244 [children_ addObject:interruptibleTarget];
1245}
1246
1247-(void) removeAudioInterruptTarget:(NSObject<CDAudioInterruptProtocol>*) interruptibleTarget {
1248 [children_ removeObjectIdenticalTo:interruptibleTarget];
1249}
1250
1251- (BOOL) mute {
1252 return mute_;
1253}
1254
1255/**
1256 * Setting mute silences all sounds but playing sounds continue to advance playback
1257 */
1258- (void) setMute:(BOOL) newMuteValue {
1259
1260 if (newMuteValue == mute_) {
1261 return;
1262 }
1263
1264 for (NSObject<CDAudioInterruptProtocol>* target in children_) {
1265 [target setMute:newMuteValue];
1266 }
1267}
1268
1269- (BOOL) enabled {
1270 return enabled_;
1271}
1272
1273- (void) setEnabled:(BOOL)enabledValue
1274{
1275 if (enabledValue == enabled_) {
1276 return;
1277 }
1278
1279 for (NSObject<CDAudioInterruptProtocol>* target in children_) {
1280 [target setEnabled:enabledValue];
1281 }
1282}
1283
1284@end
1285
1286
1287
1288////////////////////////////////////////////////////////////////////////////
1289
1290#pragma mark -
1291#pragma mark CDAsynchBufferLoader
1292
1293@implementation CDAsynchBufferLoader
1294
1295-(id) init:(NSArray *)loadRequests soundEngine:(CDSoundEngine *) theSoundEngine {
1296 if ((self = [super init])) {
1297 _loadRequests = loadRequests;
1298 [_loadRequests retain];
1299 _soundEngine = theSoundEngine;
1300 [_soundEngine retain];
1301 }
1302 return self;
1303}
1304
1305-(void) main {
1306 CDLOGINFO(@"Denshion::CDAsynchBufferLoader - loading buffers");
1307 [super main];
1308 _soundEngine.asynchLoadProgress = 0.0f;
1309
1310 if ([_loadRequests count] > 0) {
1311 float increment = 1.0f / [_loadRequests count];
1312 //Iterate over load request and load
1313 for (CDBufferLoadRequest *loadRequest in _loadRequests) {
1314 [_soundEngine loadBuffer:loadRequest.soundId filePath:loadRequest.filePath];
1315 _soundEngine.asynchLoadProgress += increment;
1316 }
1317 }
1318
1319 //Completed
1320 _soundEngine.asynchLoadProgress = 1.0f;
1321 [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AsynchLoadComplete object:nil];
1322
1323}
1324
1325-(void) dealloc {
1326 [_loadRequests release];
1327 [_soundEngine release];
1328 [super dealloc];
1329}
1330
1331@end
1332
1333
1334///////////////////////////////////////////////////////////////////////////////////////
1335#pragma mark -
1336#pragma mark CDBufferLoadRequest
1337
1338@implementation CDBufferLoadRequest
1339
1340@synthesize filePath, soundId;
1341
1342-(id) init:(int) theSoundId filePath:(const NSString *) theFilePath {
1343 if ((self = [super init])) {
1344 soundId = theSoundId;
1345 filePath = [theFilePath copy];//TODO: is retain necessary or does copy set retain count
1346 [filePath retain];
1347 }
1348 return self;
1349}
1350
1351-(void) dealloc {
1352 [filePath release];
1353 [super dealloc];
1354}
1355
1356@end
1357
1358///////////////////////////////////////////////////////////////////////////////////////
1359#pragma mark -
1360#pragma mark CDFloatInterpolator
1361
1362@implementation CDFloatInterpolator
1363@synthesize start,end,interpolationType;
1364
1365-(float) interpolate:(float) t {
1366
1367 if (t < 1.0f) {
1368 switch (interpolationType) {
1369 case kIT_Linear:
1370 //Linear interpolation
1371 return ((end - start) * t) + start;
1372
1373 case kIT_SCurve:
1374 //Cubic s curve t^2 * (3 - 2t)
1375 return ((float)(t * t * (3.0 - (2.0 * t))) * (end - start)) + start;
1376
1377 case kIT_Exponential:
1378 //Formulas taken from EaseAction
1379 if (end > start) {
1380 //Fade in
1381 float logDelta = (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) - 1 * 0.001f;
1382 return ((end - start) * logDelta) + start;
1383 } else {
1384 //Fade Out
1385 float logDelta = (-powf(2, -10 * t/1) + 1);
1386 return ((end - start) * logDelta) + start;
1387 }
1388 default:
1389 return 0.0f;
1390 }
1391 } else {
1392 return end;
1393 }
1394}
1395
1396-(id) init:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal {
1397 if ((self = [super init])) {
1398 start = startVal;
1399 end = endVal;
1400 interpolationType = type;
1401 }
1402 return self;
1403}
1404
1405@end
1406
1407///////////////////////////////////////////////////////////////////////////////////////
1408#pragma mark -
1409#pragma mark CDPropertyModifier
1410
1411@implementation CDPropertyModifier
1412
1413@synthesize stopTargetWhenComplete;
1414
1415-(id) init:(id) theTarget interpolationType:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal {
1416 if ((self = [super init])) {
1417 if (target) {
1418 //Release the previous target if there is one
1419 [target release];
1420 }
1421 target = theTarget;
1422#if CD_DEBUG
1423 //Check target is of the required type
1424 if (![theTarget isMemberOfClass:[self _allowableType]] ) {
1425 CDLOG(@"Denshion::CDPropertyModifier target is not of type %@",[self _allowableType]);
1426 NSAssert([theTarget isKindOfClass:[CDSoundEngine class]], @"CDPropertyModifier target not of required type");
1427 }
1428#endif
1429 [target retain];
1430 startValue = startVal;
1431 endValue = endVal;
1432 if (interpolator) {
1433 //Release previous interpolator if there is one
1434 [interpolator release];
1435 }
1436 interpolator = [[CDFloatInterpolator alloc] init:type startVal:startVal endVal:endVal];
1437 stopTargetWhenComplete = NO;
1438 }
1439 return self;
1440}
1441
1442-(void) dealloc {
1443 CDLOGINFO(@"Denshion::CDPropertyModifier deallocated %@",self);
1444 [target release];
1445 [interpolator release];
1446 [super dealloc];
1447}
1448
1449-(void) modify:(float) t {
1450 if (t < 1.0) {
1451 [self _setTargetProperty:[interpolator interpolate:t]];
1452 } else {
1453 //At the end
1454 [self _setTargetProperty:endValue];
1455 if (stopTargetWhenComplete) {
1456 [self _stopTarget];
1457 }
1458 }
1459}
1460
1461-(float) startValue {
1462 return startValue;
1463}
1464
1465-(void) setStartValue:(float) startVal
1466{
1467 startValue = startVal;
1468 interpolator.start = startVal;
1469}
1470
1471-(float) endValue {
1472 return startValue;
1473}
1474
1475-(void) setEndValue:(float) endVal
1476{
1477 endValue = endVal;
1478 interpolator.end = endVal;
1479}
1480
1481-(tCDInterpolationType) interpolationType {
1482 return interpolator.interpolationType;
1483}
1484
1485-(void) setInterpolationType:(tCDInterpolationType) interpolationType {
1486 interpolator.interpolationType = interpolationType;
1487}
1488
1489-(void) _setTargetProperty:(float) newVal {
1490
1491}
1492
1493-(float) _getTargetProperty {
1494 return 0.0f;
1495}
1496
1497-(void) _stopTarget {
1498
1499}
1500
1501-(Class) _allowableType {
1502 return [NSObject class];
1503}
1504@end
1505
1506///////////////////////////////////////////////////////////////////////////////////////
1507#pragma mark -
1508#pragma mark CDSoundSourceFader
1509
1510@implementation CDSoundSourceFader
1511
1512-(void) _setTargetProperty:(float) newVal {
1513 ((CDSoundSource*)target).gain = newVal;
1514}
1515
1516-(float) _getTargetProperty {
1517 return ((CDSoundSource*)target).gain;
1518}
1519
1520-(void) _stopTarget {
1521 [((CDSoundSource*)target) stop];
1522}
1523
1524-(Class) _allowableType {
1525 return [CDSoundSource class];
1526}
1527
1528@end
1529
1530///////////////////////////////////////////////////////////////////////////////////////
1531#pragma mark -
1532#pragma mark CDSoundSourcePanner
1533
1534@implementation CDSoundSourcePanner
1535
1536-(void) _setTargetProperty:(float) newVal {
1537 ((CDSoundSource*)target).pan = newVal;
1538}
1539
1540-(float) _getTargetProperty {
1541 return ((CDSoundSource*)target).pan;
1542}
1543
1544-(void) _stopTarget {
1545 [((CDSoundSource*)target) stop];
1546}
1547
1548-(Class) _allowableType {
1549 return [CDSoundSource class];
1550}
1551
1552@end
1553
1554///////////////////////////////////////////////////////////////////////////////////////
1555#pragma mark -
1556#pragma mark CDSoundSourcePitchBender
1557
1558@implementation CDSoundSourcePitchBender
1559
1560-(void) _setTargetProperty:(float) newVal {
1561 ((CDSoundSource*)target).pitch = newVal;
1562}
1563
1564-(float) _getTargetProperty {
1565 return ((CDSoundSource*)target).pitch;
1566}
1567
1568-(void) _stopTarget {
1569 [((CDSoundSource*)target) stop];
1570}
1571
1572-(Class) _allowableType {
1573 return [CDSoundSource class];
1574}
1575
1576@end
1577
1578///////////////////////////////////////////////////////////////////////////////////////
1579#pragma mark -
1580#pragma mark CDSoundEngineFader
1581
1582@implementation CDSoundEngineFader
1583
1584-(void) _setTargetProperty:(float) newVal {
1585 ((CDSoundEngine*)target).masterGain = newVal;
1586}
1587
1588-(float) _getTargetProperty {
1589 return ((CDSoundEngine*)target).masterGain;
1590}
1591
1592-(void) _stopTarget {
1593 [((CDSoundEngine*)target) stopAllSounds];
1594}
1595
1596-(Class) _allowableType {
1597 return [CDSoundEngine class];
1598}
1599
1600@end
1601
1602
diff --git a/libs/CocosDenshion/SimpleAudioEngine.h b/libs/CocosDenshion/SimpleAudioEngine.h new file mode 100755 index 0000000..35396c6 --- /dev/null +++ b/libs/CocosDenshion/SimpleAudioEngine.h
@@ -0,0 +1,90 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25
26#import "CDAudioManager.h"
27
28/**
29 A wrapper to the CDAudioManager object.
30 This is recommended for basic audio requirements. If you just want to play some sound fx
31 and some background music and have no interest in learning the lower level workings then
32 this is the interface to use.
33
34 Requirements:
35 - Firmware: OS 2.2 or greater
36 - Files: SimpleAudioEngine.*, CocosDenshion.*
37 - Frameworks: OpenAL, AudioToolbox, AVFoundation
38 @since v0.8
39 */
40@interface SimpleAudioEngine : NSObject <CDAudioInterruptProtocol> {
41
42 BOOL mute_;
43 BOOL enabled_;
44}
45
46/** Background music volume. Range is 0.0f to 1.0f. This will only have an effect if willPlayBackgroundMusic returns YES */
47@property (readwrite) float backgroundMusicVolume;
48/** Effects volume. Range is 0.0f to 1.0f */
49@property (readwrite) float effectsVolume;
50/** If NO it indicates background music will not be played either because no background music is loaded or the audio session does not permit it.*/
51@property (readonly) BOOL willPlayBackgroundMusic;
52
53/** returns the shared instance of the SimpleAudioEngine object */
54+ (SimpleAudioEngine*) sharedEngine;
55
56/** Preloads a music file so it will be ready to play as background music */
57-(void) preloadBackgroundMusic:(NSString*) filePath;
58
59/** plays background music in a loop*/
60-(void) playBackgroundMusic:(NSString*) filePath;
61/** plays background music, if loop is true the music will repeat otherwise it will be played once */
62-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop;
63/** stops playing background music */
64-(void) stopBackgroundMusic;
65/** pauses the background music */
66-(void) pauseBackgroundMusic;
67/** resume background music that has been paused */
68-(void) resumeBackgroundMusic;
69/** rewind the background music */
70-(void) rewindBackgroundMusic;
71/** returns whether or not the background music is playing */
72-(BOOL) isBackgroundMusicPlaying;
73
74/** plays an audio effect with a file path*/
75-(ALuint) playEffect:(NSString*) filePath;
76/** stop a sound that is playing, note you must pass in the soundId that is returned when you started playing the sound with playEffect */
77-(void) stopEffect:(ALuint) soundId;
78/** plays an audio effect with a file path, pitch, pan and gain */
79-(ALuint) playEffect:(NSString*) filePath pitch:(Float32) pitch pan:(Float32) pan gain:(Float32) gain;
80/** preloads an audio effect */
81-(void) preloadEffect:(NSString*) filePath;
82/** unloads an audio effect from memory */
83-(void) unloadEffect:(NSString*) filePath;
84/** Gets a CDSoundSource object set up to play the specified file. */
85-(CDSoundSource *) soundSourceForFile:(NSString*) filePath;
86
87/** Shuts down the shared audio engine instance so that it can be reinitialised */
88+(void) end;
89
90@end
diff --git a/libs/CocosDenshion/SimpleAudioEngine.m b/libs/CocosDenshion/SimpleAudioEngine.m new file mode 100755 index 0000000..cdff26c --- /dev/null +++ b/libs/CocosDenshion/SimpleAudioEngine.m
@@ -0,0 +1,220 @@
1/*
2 Copyright (c) 2010 Steve Oldmeadow
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 $Id$
23 */
24
25#import "SimpleAudioEngine.h"
26
27@implementation SimpleAudioEngine
28
29static SimpleAudioEngine *sharedEngine = nil;
30static CDSoundEngine* soundEngine = nil;
31static CDAudioManager *am = nil;
32static CDBufferManager *bufferManager = nil;
33
34// Init
35+ (SimpleAudioEngine *) sharedEngine
36{
37 @synchronized(self) {
38 if (!sharedEngine)
39 sharedEngine = [[SimpleAudioEngine alloc] init];
40 }
41 return sharedEngine;
42}
43
44+ (id) alloc
45{
46 @synchronized(self) {
47 NSAssert(sharedEngine == nil, @"Attempted to allocate a second instance of a singleton.");
48 return [super alloc];
49 }
50 return nil;
51}
52
53-(id) init
54{
55 if((self=[super init])) {
56 am = [CDAudioManager sharedManager];
57 soundEngine = am.soundEngine;
58 bufferManager = [[CDBufferManager alloc] initWithEngine:soundEngine];
59 mute_ = NO;
60 enabled_ = YES;
61 }
62 return self;
63}
64
65// Memory
66- (void) dealloc
67{
68 am = nil;
69 soundEngine = nil;
70 bufferManager = nil;
71 [super dealloc];
72}
73
74+(void) end
75{
76 am = nil;
77 [CDAudioManager end];
78 [bufferManager release];
79 [sharedEngine release];
80 sharedEngine = nil;
81}
82
83#pragma mark SimpleAudioEngine - background music
84
85-(void) preloadBackgroundMusic:(NSString*) filePath {
86 [am preloadBackgroundMusic:filePath];
87}
88
89-(void) playBackgroundMusic:(NSString*) filePath
90{
91 [am playBackgroundMusic:filePath loop:TRUE];
92}
93
94-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop
95{
96 [am playBackgroundMusic:filePath loop:loop];
97}
98
99-(void) stopBackgroundMusic
100{
101 [am stopBackgroundMusic];
102}
103
104-(void) pauseBackgroundMusic {
105 [am pauseBackgroundMusic];
106}
107
108-(void) resumeBackgroundMusic {
109 [am resumeBackgroundMusic];
110}
111
112-(void) rewindBackgroundMusic {
113 [am rewindBackgroundMusic];
114}
115
116-(BOOL) isBackgroundMusicPlaying {
117 return [am isBackgroundMusicPlaying];
118}
119
120-(BOOL) willPlayBackgroundMusic {
121 return [am willPlayBackgroundMusic];
122}
123
124#pragma mark SimpleAudioEngine - sound effects
125
126-(ALuint) playEffect:(NSString*) filePath
127{
128 return [self playEffect:filePath pitch:1.0f pan:0.0f gain:1.0f];
129}
130
131-(ALuint) playEffect:(NSString*) filePath pitch:(Float32) pitch pan:(Float32) pan gain:(Float32) gain
132{
133 int soundId = [bufferManager bufferForFile:filePath create:YES];
134 if (soundId != kCDNoBuffer) {
135 return [soundEngine playSound:soundId sourceGroupId:0 pitch:pitch pan:pan gain:gain loop:false];
136 } else {
137 return CD_MUTE;
138 }
139}
140
141-(void) stopEffect:(ALuint) soundId {
142 [soundEngine stopSound:soundId];
143}
144
145-(void) preloadEffect:(NSString*) filePath
146{
147 int soundId = [bufferManager bufferForFile:filePath create:YES];
148 if (soundId == kCDNoBuffer) {
149 CDLOG(@"Denshion::SimpleAudioEngine sound failed to preload %@",filePath);
150 }
151}
152
153-(void) unloadEffect:(NSString*) filePath
154{
155 CDLOGINFO(@"Denshion::SimpleAudioEngine unloadedEffect %@",filePath);
156 [bufferManager releaseBufferForFile:filePath];
157}
158
159#pragma mark Audio Interrupt Protocol
160-(BOOL) mute
161{
162 return mute_;
163}
164
165-(void) setMute:(BOOL) muteValue
166{
167 if (mute_ != muteValue) {
168 mute_ = muteValue;
169 am.mute = mute_;
170 }
171}
172
173-(BOOL) enabled
174{
175 return enabled_;
176}
177
178-(void) setEnabled:(BOOL) enabledValue
179{
180 if (enabled_ != enabledValue) {
181 enabled_ = enabledValue;
182 am.enabled = enabled_;
183 }
184}
185
186
187#pragma mark SimpleAudioEngine - BackgroundMusicVolume
188-(float) backgroundMusicVolume
189{
190 return am.backgroundMusic.volume;
191}
192
193-(void) setBackgroundMusicVolume:(float) volume
194{
195 am.backgroundMusic.volume = volume;
196}
197
198#pragma mark SimpleAudioEngine - EffectsVolume
199-(float) effectsVolume
200{
201 return am.soundEngine.masterGain;
202}
203
204-(void) setEffectsVolume:(float) volume
205{
206 am.soundEngine.masterGain = volume;
207}
208
209-(CDSoundSource *) soundSourceForFile:(NSString*) filePath {
210 int soundId = [bufferManager bufferForFile:filePath create:YES];
211 if (soundId != kCDNoBuffer) {
212 CDSoundSource *result = [soundEngine soundSourceForSound:soundId sourceGroupId:0];
213 CDLOGINFO(@"Denshion::SimpleAudioEngine sound source created for %@",filePath);
214 return result;
215 } else {
216 return nil;
217 }
218}
219
220@end
diff --git a/libs/FontLabel/FontLabel.h b/libs/FontLabel/FontLabel.h new file mode 100755 index 0000000..6de9c2c --- /dev/null +++ b/libs/FontLabel/FontLabel.h
@@ -0,0 +1,44 @@
1//
2// FontLabel.h
3// FontLabel
4//
5// Created by Kevin Ballard on 5/8/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import <Foundation/Foundation.h>
23#import <UIKit/UIKit.h>
24
25@class ZFont;
26@class ZAttributedString;
27
28@interface FontLabel : UILabel {
29 void *reserved; // works around a bug in UILabel
30 ZFont *zFont;
31 ZAttributedString *zAttributedText;
32}
33@property (nonatomic, setter=setCGFont:) CGFontRef cgFont __AVAILABILITY_INTERNAL_DEPRECATED;
34@property (nonatomic, assign) CGFloat pointSize __AVAILABILITY_INTERNAL_DEPRECATED;
35@property (nonatomic, retain, setter=setZFont:) ZFont *zFont;
36// if attributedText is nil, fall back on using the inherited UILabel properties
37// if attributedText is non-nil, the font/text/textColor
38// in addition, adjustsFontSizeToFitWidth does not work with attributed text
39@property (nonatomic, copy) ZAttributedString *zAttributedText;
40// -initWithFrame:fontName:pointSize: uses FontManager to look up the font name
41- (id)initWithFrame:(CGRect)frame fontName:(NSString *)fontName pointSize:(CGFloat)pointSize;
42- (id)initWithFrame:(CGRect)frame zFont:(ZFont *)font;
43- (id)initWithFrame:(CGRect)frame font:(CGFontRef)font pointSize:(CGFloat)pointSize __AVAILABILITY_INTERNAL_DEPRECATED;
44@end
diff --git a/libs/FontLabel/FontLabel.m b/libs/FontLabel/FontLabel.m new file mode 100755 index 0000000..58975b1 --- /dev/null +++ b/libs/FontLabel/FontLabel.m
@@ -0,0 +1,195 @@
1//
2// FontLabel.m
3// FontLabel
4//
5// Created by Kevin Ballard on 5/8/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import "FontLabel.h"
23#import "FontManager.h"
24#import "FontLabelStringDrawing.h"
25#import "ZFont.h"
26
27@interface ZFont (ZFontPrivate)
28@property (nonatomic, readonly) CGFloat ratio;
29@end
30
31@implementation FontLabel
32@synthesize zFont;
33@synthesize zAttributedText;
34
35- (id)initWithFrame:(CGRect)frame fontName:(NSString *)fontName pointSize:(CGFloat)pointSize {
36 return [self initWithFrame:frame zFont:[[FontManager sharedManager] zFontWithName:fontName pointSize:pointSize]];
37}
38
39- (id)initWithFrame:(CGRect)frame zFont:(ZFont *)font {
40 if ((self = [super initWithFrame:frame])) {
41 zFont = [font retain];
42 }
43 return self;
44}
45
46- (id)initWithFrame:(CGRect)frame font:(CGFontRef)font pointSize:(CGFloat)pointSize {
47 return [self initWithFrame:frame zFont:[ZFont fontWithCGFont:font size:pointSize]];
48}
49
50- (CGFontRef)cgFont {
51 return self.zFont.cgFont;
52}
53
54- (void)setCGFont:(CGFontRef)font {
55 if (self.zFont.cgFont != font) {
56 self.zFont = [ZFont fontWithCGFont:font size:self.zFont.pointSize];
57 }
58}
59
60- (CGFloat)pointSize {
61 return self.zFont.pointSize;
62}
63
64- (void)setPointSize:(CGFloat)pointSize {
65 if (self.zFont.pointSize != pointSize) {
66 self.zFont = [ZFont fontWithCGFont:self.zFont.cgFont size:pointSize];
67 }
68}
69
70- (void)setZAttributedText:(ZAttributedString *)attStr {
71 if (zAttributedText != attStr) {
72 [zAttributedText release];
73 zAttributedText = [attStr copy];
74 [self setNeedsDisplay];
75 }
76}
77
78- (void)drawTextInRect:(CGRect)rect {
79 if (self.zFont == NULL && self.zAttributedText == nil) {
80 [super drawTextInRect:rect];
81 return;
82 }
83
84 if (self.zAttributedText == nil) {
85 // this method is documented as setting the text color for us, but that doesn't appear to be the case
86 if (self.highlighted) {
87 [(self.highlightedTextColor ?: [UIColor whiteColor]) setFill];
88 } else {
89 [(self.textColor ?: [UIColor blackColor]) setFill];
90 }
91
92 ZFont *actualFont = self.zFont;
93 CGSize origSize = rect.size;
94 if (self.numberOfLines == 1) {
95 origSize.height = actualFont.leading;
96 CGPoint point = CGPointMake(rect.origin.x,
97 rect.origin.y + roundf(((rect.size.height - actualFont.leading) / 2.0f)));
98 CGSize size = [self.text sizeWithZFont:actualFont];
99 if (self.adjustsFontSizeToFitWidth && self.minimumFontSize < actualFont.pointSize) {
100 if (size.width > origSize.width) {
101 CGFloat desiredRatio = (origSize.width * actualFont.ratio) / size.width;
102 CGFloat desiredPointSize = desiredRatio * actualFont.pointSize / actualFont.ratio;
103 actualFont = [actualFont fontWithSize:MAX(MAX(desiredPointSize, self.minimumFontSize), 1.0f)];
104 size = [self.text sizeWithZFont:actualFont];
105 }
106 if (!CGSizeEqualToSize(origSize, size)) {
107 switch (self.baselineAdjustment) {
108 case UIBaselineAdjustmentAlignCenters:
109 point.y += roundf((origSize.height - size.height) / 2.0f);
110 break;
111 case UIBaselineAdjustmentAlignBaselines:
112 point.y += (self.zFont.ascender - actualFont.ascender);
113 break;
114 case UIBaselineAdjustmentNone:
115 break;
116 }
117 }
118 }
119 size.width = MIN(size.width, origSize.width);
120 // adjust the point for alignment
121 switch (self.textAlignment) {
122 case UITextAlignmentLeft:
123 break;
124 case UITextAlignmentCenter:
125 point.x += (origSize.width - size.width) / 2.0f;
126 break;
127 case UITextAlignmentRight:
128 point.x += origSize.width - size.width;
129 break;
130 }
131 [self.text drawAtPoint:point forWidth:size.width withZFont:actualFont lineBreakMode:self.lineBreakMode];
132 } else {
133 CGSize size = [self.text sizeWithZFont:actualFont constrainedToSize:origSize lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
134 CGPoint point = rect.origin;
135 point.y += roundf((rect.size.height - size.height) / 2.0f);
136 rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
137 [self.text drawInRect:rect withZFont:actualFont lineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
138 }
139 } else {
140 ZAttributedString *attStr = self.zAttributedText;
141 if (self.highlighted) {
142 // modify the string to change the base color
143 ZMutableAttributedString *mutStr = [[attStr mutableCopy] autorelease];
144 NSRange activeRange = NSMakeRange(0, attStr.length);
145 while (activeRange.length > 0) {
146 NSRange effective;
147 UIColor *color = [attStr attribute:ZForegroundColorAttributeName atIndex:activeRange.location
148 longestEffectiveRange:&effective inRange:activeRange];
149 if (color == nil) {
150 [mutStr addAttribute:ZForegroundColorAttributeName value:[UIColor whiteColor] range:effective];
151 }
152 activeRange.location += effective.length, activeRange.length -= effective.length;
153 }
154 attStr = mutStr;
155 }
156 CGSize size = [attStr sizeConstrainedToSize:rect.size lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
157 CGPoint point = rect.origin;
158 point.y += roundf((rect.size.height - size.height) / 2.0f);
159 rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
160 [attStr drawInRect:rect withLineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
161 }
162}
163
164- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
165 if (self.zFont == NULL && self.zAttributedText == nil) {
166 return [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
167 }
168
169 if (numberOfLines == 1) {
170 // if numberOfLines == 1 we need to use the version that converts spaces
171 CGSize size;
172 if (self.zAttributedText == nil) {
173 size = [self.text sizeWithZFont:self.zFont];
174 } else {
175 size = [self.zAttributedText size];
176 }
177 bounds.size.width = MIN(bounds.size.width, size.width);
178 bounds.size.height = MIN(bounds.size.height, size.height);
179 } else {
180 if (numberOfLines > 0) bounds.size.height = MIN(bounds.size.height, self.zFont.leading * numberOfLines);
181 if (self.zAttributedText == nil) {
182 bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode];
183 } else {
184 bounds.size = [self.zAttributedText sizeConstrainedToSize:bounds.size lineBreakMode:self.lineBreakMode];
185 }
186 }
187 return bounds;
188}
189
190- (void)dealloc {
191 [zFont release];
192 [zAttributedText release];
193 [super dealloc];
194}
195@end
diff --git a/libs/FontLabel/FontLabelStringDrawing.h b/libs/FontLabel/FontLabelStringDrawing.h new file mode 100755 index 0000000..821da22 --- /dev/null +++ b/libs/FontLabel/FontLabelStringDrawing.h
@@ -0,0 +1,69 @@
1//
2// FontLabelStringDrawing.h
3// FontLabel
4//
5// Created by Kevin Ballard on 5/5/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import <UIKit/UIKit.h>
23#import "ZAttributedString.h"
24
25@class ZFont;
26
27@interface NSString (FontLabelStringDrawing)
28// CGFontRef-based methods
29- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize __AVAILABILITY_INTERNAL_DEPRECATED;
30- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize constrainedToSize:(CGSize)size __AVAILABILITY_INTERNAL_DEPRECATED;
31- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize constrainedToSize:(CGSize)size
32 lineBreakMode:(UILineBreakMode)lineBreakMode __AVAILABILITY_INTERNAL_DEPRECATED;
33- (CGSize)drawAtPoint:(CGPoint)point withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize __AVAILABILITY_INTERNAL_DEPRECATED;
34- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize __AVAILABILITY_INTERNAL_DEPRECATED;
35- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize
36 lineBreakMode:(UILineBreakMode)lineBreakMode __AVAILABILITY_INTERNAL_DEPRECATED;
37- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize
38 lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment __AVAILABILITY_INTERNAL_DEPRECATED;
39
40// ZFont-based methods
41- (CGSize)sizeWithZFont:(ZFont *)font;
42- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size;
43- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode;
44- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
45 numberOfLines:(NSUInteger)numberOfLines;
46- (CGSize)drawAtPoint:(CGPoint)point withZFont:(ZFont *)font;
47- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode;
48- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font;
49- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode;
50- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode
51 alignment:(UITextAlignment)alignment;
52- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode
53 alignment:(UITextAlignment)alignment numberOfLines:(NSUInteger)numberOfLines;
54@end
55
56@interface ZAttributedString (ZAttributedStringDrawing)
57- (CGSize)size;
58- (CGSize)sizeConstrainedToSize:(CGSize)size;
59- (CGSize)sizeConstrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode;
60- (CGSize)sizeConstrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
61 numberOfLines:(NSUInteger)numberOfLines;
62- (CGSize)drawAtPoint:(CGPoint)point;
63- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode;
64- (CGSize)drawInRect:(CGRect)rect;
65- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode;
66- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment;
67- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment
68 numberOfLines:(NSUInteger)numberOfLines;
69@end
diff --git a/libs/FontLabel/FontLabelStringDrawing.m b/libs/FontLabel/FontLabelStringDrawing.m new file mode 100755 index 0000000..2907372 --- /dev/null +++ b/libs/FontLabel/FontLabelStringDrawing.m
@@ -0,0 +1,892 @@
1//
2// FontLabelStringDrawing.m
3// FontLabel
4//
5// Created by Kevin Ballard on 5/5/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import "FontLabelStringDrawing.h"
23#import "ZFont.h"
24#import "ZAttributedStringPrivate.h"
25
26@interface ZFont (ZFontPrivate)
27@property (nonatomic, readonly) CGFloat ratio;
28@end
29
30#define kUnicodeHighSurrogateStart 0xD800
31#define kUnicodeHighSurrogateEnd 0xDBFF
32#define kUnicodeHighSurrogateMask kUnicodeHighSurrogateStart
33#define kUnicodeLowSurrogateStart 0xDC00
34#define kUnicodeLowSurrogateEnd 0xDFFF
35#define kUnicodeLowSurrogateMask kUnicodeLowSurrogateStart
36#define kUnicodeSurrogateTypeMask 0xFC00
37#define UnicharIsHighSurrogate(c) ((c & kUnicodeSurrogateTypeMask) == kUnicodeHighSurrogateMask)
38#define UnicharIsLowSurrogate(c) ((c & kUnicodeSurrogateTypeMask) == kUnicodeLowSurrogateMask)
39#define ConvertSurrogatePairToUTF32(high, low) ((UInt32)((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000))
40
41typedef enum {
42 kFontTableFormat4 = 4,
43 kFontTableFormat12 = 12,
44} FontTableFormat;
45
46typedef struct fontTable {
47 NSUInteger retainCount;
48 CFDataRef cmapTable;
49 FontTableFormat format;
50 union {
51 struct {
52 UInt16 segCountX2;
53 UInt16 *endCodes;
54 UInt16 *startCodes;
55 UInt16 *idDeltas;
56 UInt16 *idRangeOffsets;
57 } format4;
58 struct {
59 UInt32 nGroups;
60 struct {
61 UInt32 startCharCode;
62 UInt32 endCharCode;
63 UInt32 startGlyphCode;
64 } *groups;
65 } format12;
66 } cmap;
67} fontTable;
68
69static FontTableFormat supportedFormats[] = { kFontTableFormat4, kFontTableFormat12 };
70static size_t supportedFormatsCount = sizeof(supportedFormats) / sizeof(FontTableFormat);
71
72static fontTable *newFontTable(CFDataRef cmapTable, FontTableFormat format) {
73 fontTable *table = (struct fontTable *)malloc(sizeof(struct fontTable));
74 table->retainCount = 1;
75 table->cmapTable = CFRetain(cmapTable);
76 table->format = format;
77 return table;
78}
79
80static fontTable *retainFontTable(fontTable *table) {
81 if (table != NULL) {
82 table->retainCount++;
83 }
84 return table;
85}
86
87static void releaseFontTable(fontTable *table) {
88 if (table != NULL) {
89 if (table->retainCount <= 1) {
90 CFRelease(table->cmapTable);
91 free(table);
92 } else {
93 table->retainCount--;
94 }
95 }
96}
97
98static const void *fontTableRetainCallback(CFAllocatorRef allocator, const void *value) {
99 return retainFontTable((fontTable *)value);
100}
101
102static void fontTableReleaseCallback(CFAllocatorRef allocator, const void *value) {
103 releaseFontTable((fontTable *)value);
104}
105
106static const CFDictionaryValueCallBacks kFontTableDictionaryValueCallBacks = {
107 .version = 0,
108 .retain = &fontTableRetainCallback,
109 .release = &fontTableReleaseCallback,
110 .copyDescription = NULL,
111 .equal = NULL
112};
113
114// read the cmap table from the font
115// we only know how to understand some of the table formats at the moment
116static fontTable *readFontTableFromCGFont(CGFontRef font) {
117 CFDataRef cmapTable = CGFontCopyTableForTag(font, 'cmap');
118 NSCAssert1(cmapTable != NULL, @"CGFontCopyTableForTag returned NULL for 'cmap' tag in font %@",
119 (font ? [(id)CFCopyDescription(font) autorelease] : @"(null)"));
120 const UInt8 * const bytes = CFDataGetBytePtr(cmapTable);
121 NSCAssert1(OSReadBigInt16(bytes, 0) == 0, @"cmap table for font %@ has bad version number",
122 (font ? [(id)CFCopyDescription(font) autorelease] : @"(null)"));
123 UInt16 numberOfSubtables = OSReadBigInt16(bytes, 2);
124 const UInt8 *unicodeSubtable = NULL;
125 //UInt16 unicodeSubtablePlatformID;
126 UInt16 unicodeSubtablePlatformSpecificID;
127 FontTableFormat unicodeSubtableFormat;
128 const UInt8 * const encodingSubtables = &bytes[4];
129 for (UInt16 i = 0; i < numberOfSubtables; i++) {
130 const UInt8 * const encodingSubtable = &encodingSubtables[8 * i];
131 UInt16 platformID = OSReadBigInt16(encodingSubtable, 0);
132 UInt16 platformSpecificID = OSReadBigInt16(encodingSubtable, 2);
133 // find the best subtable
134 // best is defined by a combination of encoding and format
135 // At the moment we only support format 4, so ignore all other format tables
136 // We prefer platformID == 0, but we will also accept Microsoft's unicode format
137 if (platformID == 0 || (platformID == 3 && platformSpecificID == 1)) {
138 BOOL preferred = NO;
139 if (unicodeSubtable == NULL) {
140 preferred = YES;
141 } else if (platformID == 0 && platformSpecificID > unicodeSubtablePlatformSpecificID) {
142 preferred = YES;
143 }
144 if (preferred) {
145 UInt32 offset = OSReadBigInt32(encodingSubtable, 4);
146 const UInt8 *subtable = &bytes[offset];
147 UInt16 format = OSReadBigInt16(subtable, 0);
148 for (size_t i = 0; i < supportedFormatsCount; i++) {
149 if (format == supportedFormats[i]) {
150 if (format >= 8) {
151 // the version is a fixed-point
152 UInt16 formatFrac = OSReadBigInt16(subtable, 2);
153 if (formatFrac != 0) {
154 // all the current formats with a Fixed version are always *.0
155 continue;
156 }
157 }
158 unicodeSubtable = subtable;
159 //unicodeSubtablePlatformID = platformID;
160 unicodeSubtablePlatformSpecificID = platformSpecificID;
161 unicodeSubtableFormat = format;
162 break;
163 }
164 }
165 }
166 }
167 }
168 fontTable *table = NULL;
169 if (unicodeSubtable != NULL) {
170 table = newFontTable(cmapTable, unicodeSubtableFormat);
171 switch (unicodeSubtableFormat) {
172 case kFontTableFormat4:
173 // subtable format 4
174 //UInt16 length = OSReadBigInt16(unicodeSubtable, 2);
175 //UInt16 language = OSReadBigInt16(unicodeSubtable, 4);
176 table->cmap.format4.segCountX2 = OSReadBigInt16(unicodeSubtable, 6);
177 //UInt16 searchRange = OSReadBigInt16(unicodeSubtable, 8);
178 //UInt16 entrySelector = OSReadBigInt16(unicodeSubtable, 10);
179 //UInt16 rangeShift = OSReadBigInt16(unicodeSubtable, 12);
180 table->cmap.format4.endCodes = (UInt16*)&unicodeSubtable[14];
181 table->cmap.format4.startCodes = (UInt16*)&((UInt8*)table->cmap.format4.endCodes)[table->cmap.format4.segCountX2+2];
182 table->cmap.format4.idDeltas = (UInt16*)&((UInt8*)table->cmap.format4.startCodes)[table->cmap.format4.segCountX2];
183 table->cmap.format4.idRangeOffsets = (UInt16*)&((UInt8*)table->cmap.format4.idDeltas)[table->cmap.format4.segCountX2];
184 //UInt16 *glyphIndexArray = &idRangeOffsets[segCountX2];
185 break;
186 case kFontTableFormat12:
187 table->cmap.format12.nGroups = OSReadBigInt32(unicodeSubtable, 12);
188 table->cmap.format12.groups = (void *)&unicodeSubtable[16];
189 break;
190 default:
191 releaseFontTable(table);
192 table = NULL;
193 }
194 }
195 CFRelease(cmapTable);
196 return table;
197}
198
199// outGlyphs must be at least size n
200static void mapCharactersToGlyphsInFont(const fontTable *table, unichar characters[], size_t charLen, CGGlyph outGlyphs[], size_t *outGlyphLen) {
201 if (table != NULL) {
202 NSUInteger j = 0;
203 switch (table->format) {
204 case kFontTableFormat4: {
205 for (NSUInteger i = 0; i < charLen; i++, j++) {
206 unichar c = characters[i];
207 UInt16 segOffset;
208 BOOL foundSegment = NO;
209 for (segOffset = 0; segOffset < table->cmap.format4.segCountX2; segOffset += 2) {
210 UInt16 endCode = OSReadBigInt16(table->cmap.format4.endCodes, segOffset);
211 if (endCode >= c) {
212 foundSegment = YES;
213 break;
214 }
215 }
216 if (!foundSegment) {
217 // no segment
218 // this is an invalid font
219 outGlyphs[j] = 0;
220 } else {
221 UInt16 startCode = OSReadBigInt16(table->cmap.format4.startCodes, segOffset);
222 if (!(startCode <= c)) {
223 // the code falls in a hole between segments
224 outGlyphs[j] = 0;
225 } else {
226 UInt16 idRangeOffset = OSReadBigInt16(table->cmap.format4.idRangeOffsets, segOffset);
227 if (idRangeOffset == 0) {
228 UInt16 idDelta = OSReadBigInt16(table->cmap.format4.idDeltas, segOffset);
229 outGlyphs[j] = (c + idDelta) % 65536;
230 } else {
231 // use the glyphIndexArray
232 UInt16 glyphOffset = idRangeOffset + 2 * (c - startCode);
233 outGlyphs[j] = OSReadBigInt16(&((UInt8*)table->cmap.format4.idRangeOffsets)[segOffset], glyphOffset);
234 }
235 }
236 }
237 }
238 break;
239 }
240 case kFontTableFormat12: {
241 UInt32 lastSegment = UINT32_MAX;
242 for (NSUInteger i = 0; i < charLen; i++, j++) {
243 unichar c = characters[i];
244 UInt32 c32 = c;
245 if (UnicharIsHighSurrogate(c)) {
246 if (i+1 < charLen) { // do we have another character after this one?
247 unichar cc = characters[i+1];
248 if (UnicharIsLowSurrogate(cc)) {
249 c32 = ConvertSurrogatePairToUTF32(c, cc);
250 i++;
251 }
252 }
253 }
254 // Start the heuristic search
255 // If this is an ASCII char, just do a linear search
256 // Otherwise do a hinted, modified binary search
257 // Start the first pivot at the last range found
258 // And when moving the pivot, limit the movement by increasing
259 // powers of two. This should help with locality
260 __typeof__(table->cmap.format12.groups[0]) *foundGroup = NULL;
261 if (c32 <= 0x7F) {
262 // ASCII
263 for (UInt32 idx = 0; idx < table->cmap.format12.nGroups; idx++) {
264 __typeof__(table->cmap.format12.groups[idx]) *group = &table->cmap.format12.groups[idx];
265 if (c32 < OSSwapBigToHostInt32(group->startCharCode)) {
266 // we've fallen into a hole
267 break;
268 } else if (c32 <= OSSwapBigToHostInt32(group->endCharCode)) {
269 // this is the range
270 foundGroup = group;
271 break;
272 }
273 }
274 } else {
275 // heuristic search
276 UInt32 maxJump = (lastSegment == UINT32_MAX ? UINT32_MAX / 2 : 8);
277 UInt32 lowIdx = 0, highIdx = table->cmap.format12.nGroups; // highIdx is the first invalid idx
278 UInt32 pivot = (lastSegment == UINT32_MAX ? lowIdx + (highIdx - lowIdx) / 2 : lastSegment);
279 while (highIdx > lowIdx) {
280 __typeof__(table->cmap.format12.groups[pivot]) *group = &table->cmap.format12.groups[pivot];
281 if (c32 < OSSwapBigToHostInt32(group->startCharCode)) {
282 highIdx = pivot;
283 } else if (c32 > OSSwapBigToHostInt32(group->endCharCode)) {
284 lowIdx = pivot + 1;
285 } else {
286 // we've hit the range
287 foundGroup = group;
288 break;
289 }
290 if (highIdx - lowIdx > maxJump * 2) {
291 if (highIdx == pivot) {
292 pivot -= maxJump;
293 } else {
294 pivot += maxJump;
295 }
296 maxJump *= 2;
297 } else {
298 pivot = lowIdx + (highIdx - lowIdx) / 2;
299 }
300 }
301 if (foundGroup != NULL) lastSegment = pivot;
302 }
303 if (foundGroup == NULL) {
304 outGlyphs[j] = 0;
305 } else {
306 outGlyphs[j] = (CGGlyph)(OSSwapBigToHostInt32(foundGroup->startGlyphCode) +
307 (c32 - OSSwapBigToHostInt32(foundGroup->startCharCode)));
308 }
309 }
310 break;
311 }
312 }
313 if (outGlyphLen != NULL) *outGlyphLen = j;
314 } else {
315 // we have no table, so just null out the glyphs
316 bzero(outGlyphs, charLen*sizeof(CGGlyph));
317 if (outGlyphLen != NULL) *outGlyphLen = 0;
318 }
319}
320
321static BOOL mapGlyphsToAdvancesInFont(ZFont *font, size_t n, CGGlyph glyphs[], CGFloat outAdvances[]) {
322 int advances[n];
323 if (CGFontGetGlyphAdvances(font.cgFont, glyphs, n, advances)) {
324 CGFloat ratio = font.ratio;
325
326 for (size_t i = 0; i < n; i++) {
327 outAdvances[i] = advances[i]*ratio;
328 }
329 return YES;
330 } else {
331 bzero(outAdvances, n*sizeof(CGFloat));
332 }
333 return NO;
334}
335
336static id getValueOrDefaultForRun(ZAttributeRun *run, NSString *key) {
337 id value = [run.attributes objectForKey:key];
338 if (value == nil) {
339 static NSDictionary *defaultValues = nil;
340 if (defaultValues == nil) {
341 defaultValues = [[NSDictionary alloc] initWithObjectsAndKeys:
342 [ZFont fontWithUIFont:[UIFont systemFontOfSize:12]], ZFontAttributeName,
343 [UIColor blackColor], ZForegroundColorAttributeName,
344 [UIColor clearColor], ZBackgroundColorAttributeName,
345 [NSNumber numberWithInt:ZUnderlineStyleNone], ZUnderlineStyleAttributeName,
346 nil];
347 }
348 value = [defaultValues objectForKey:key];
349 }
350 return value;
351}
352
353static void readRunInformation(NSArray *attributes, NSUInteger len, CFMutableDictionaryRef fontTableMap,
354 NSUInteger index, ZAttributeRun **currentRun, NSUInteger *nextRunStart,
355 ZFont **currentFont, fontTable **currentTable) {
356 *currentRun = [attributes objectAtIndex:index];
357 *nextRunStart = ([attributes count] > index+1 ? [[attributes objectAtIndex:index+1] index] : len);
358 *currentFont = getValueOrDefaultForRun(*currentRun, ZFontAttributeName);
359 if (!CFDictionaryGetValueIfPresent(fontTableMap, (*currentFont).cgFont, (const void **)currentTable)) {
360 *currentTable = readFontTableFromCGFont((*currentFont).cgFont);
361 CFDictionarySetValue(fontTableMap, (*currentFont).cgFont, *currentTable);
362 releaseFontTable(*currentTable);
363 }
364}
365
366static CGSize drawOrSizeTextConstrainedToSize(BOOL performDraw, NSString *string, NSArray *attributes, CGSize constrainedSize, NSUInteger maxLines,
367 UILineBreakMode lineBreakMode, UITextAlignment alignment, BOOL ignoreColor) {
368 NSUInteger len = [string length];
369 NSUInteger idx = 0;
370 CGPoint drawPoint = CGPointZero;
371 CGSize retValue = CGSizeZero;
372 CGContextRef ctx = (performDraw ? UIGraphicsGetCurrentContext() : NULL);
373
374 BOOL convertNewlines = (maxLines == 1);
375
376 // Extract the characters from the string
377 // Convert newlines to spaces if necessary
378 unichar *characters = (unichar *)malloc(sizeof(unichar) * len);
379 if (convertNewlines) {
380 NSCharacterSet *charset = [NSCharacterSet newlineCharacterSet];
381 NSRange range = NSMakeRange(0, len);
382 size_t cIdx = 0;
383 while (range.length > 0) {
384 NSRange newlineRange = [string rangeOfCharacterFromSet:charset options:0 range:range];
385 if (newlineRange.location == NSNotFound) {
386 [string getCharacters:&characters[cIdx] range:range];
387 cIdx += range.length;
388 break;
389 } else {
390 NSUInteger delta = newlineRange.location - range.location;
391 if (newlineRange.location > range.location) {
392 [string getCharacters:&characters[cIdx] range:NSMakeRange(range.location, delta)];
393 }
394 cIdx += delta;
395 characters[cIdx] = (unichar)' ';
396 cIdx++;
397 delta += newlineRange.length;
398 range.location += delta, range.length -= delta;
399 if (newlineRange.length == 1 && range.length >= 1 &&
400 [string characterAtIndex:newlineRange.location] == (unichar)'\r' &&
401 [string characterAtIndex:range.location] == (unichar)'\n') {
402 // CRLF sequence, skip the LF
403 range.location += 1, range.length -= 1;
404 }
405 }
406 }
407 len = cIdx;
408 } else {
409 [string getCharacters:characters range:NSMakeRange(0, len)];
410 }
411
412 // Create storage for glyphs and advances
413 CGGlyph *glyphs;
414 CGFloat *advances;
415 {
416 NSUInteger maxRunLength = 0;
417 ZAttributeRun *a = [attributes objectAtIndex:0];
418 for (NSUInteger i = 1; i < [attributes count]; i++) {
419 ZAttributeRun *b = [attributes objectAtIndex:i];
420 maxRunLength = MAX(maxRunLength, b.index - a.index);
421 a = b;
422 }
423 maxRunLength = MAX(maxRunLength, len - a.index);
424 maxRunLength++; // for a potential ellipsis
425 glyphs = (CGGlyph *)malloc(sizeof(CGGlyph) * maxRunLength);
426 advances = (CGFloat *)malloc(sizeof(CGFloat) * maxRunLength);
427 }
428
429 // Use this table to cache all fontTable objects
430 CFMutableDictionaryRef fontTableMap = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
431 &kFontTableDictionaryValueCallBacks);
432
433 // Fetch initial style values
434 NSUInteger currentRunIdx = 0;
435 ZAttributeRun *currentRun;
436 NSUInteger nextRunStart;
437 ZFont *currentFont;
438 fontTable *currentTable;
439
440#define READ_RUN() readRunInformation(attributes, len, fontTableMap, \
441 currentRunIdx, &currentRun, &nextRunStart, \
442 &currentFont, &currentTable)
443
444 READ_RUN();
445
446 // fetch the glyphs for the first run
447 size_t glyphCount;
448 NSUInteger glyphIdx;
449
450#define READ_GLYPHS() do { \
451 mapCharactersToGlyphsInFont(currentTable, &characters[currentRun.index], (nextRunStart - currentRun.index), glyphs, &glyphCount); \
452 mapGlyphsToAdvancesInFont(currentFont, (nextRunStart - currentRun.index), glyphs, advances); \
453 glyphIdx = 0; \
454 } while (0)
455
456 READ_GLYPHS();
457
458 NSMutableCharacterSet *alphaCharset = [NSMutableCharacterSet alphanumericCharacterSet];
459 [alphaCharset addCharactersInString:@"([{'\"\u2019\u02BC"];
460
461 // scan left-to-right looking for newlines or until we hit the width constraint
462 // When we hit a wrapping point, calculate truncation as follows:
463 // If we have room to draw at least one more character on the next line, no truncation
464 // Otherwise apply the truncation algorithm to the current line.
465 // After calculating any truncation, draw.
466 // Each time we hit the end of an attribute run, calculate the new font and make sure
467 // it fits (vertically) within the size constraint. If not, truncate this line.
468 // When we draw, iterate over the attribute runs for this line and draw each run separately
469 BOOL lastLine = NO; // used to indicate truncation and to stop the iterating
470 NSUInteger lineCount = 1;
471 while (idx < len && !lastLine) {
472 if (maxLines > 0 && lineCount == maxLines) {
473 lastLine = YES;
474 }
475 // scan left-to-right
476 struct {
477 NSUInteger index;
478 NSUInteger glyphIndex;
479 NSUInteger currentRunIdx;
480 } indexCache = { idx, glyphIdx, currentRunIdx };
481 CGSize lineSize = CGSizeMake(0, currentFont.leading);
482 CGFloat lineAscender = currentFont.ascender;
483 struct {
484 NSUInteger index;
485 NSUInteger glyphIndex;
486 NSUInteger currentRunIdx;
487 CGSize lineSize;
488 } lastWrapCache = {0, 0, 0, CGSizeZero};
489 BOOL inAlpha = NO; // used for calculating wrap points
490
491 BOOL finishLine = NO;
492 for (;idx <= len && !finishLine;) {
493 NSUInteger skipCount = 0;
494 if (idx == len) {
495 finishLine = YES;
496 lastLine = YES;
497 } else {
498 if (idx >= nextRunStart) {
499 // cycle the font and table and grab the next set of glyphs
500 do {
501 currentRunIdx++;
502 READ_RUN();
503 } while (idx >= nextRunStart);
504 READ_GLYPHS();
505 // re-scan the characters to synchronize the glyph index
506 for (NSUInteger j = currentRun.index; j < idx; j++) {
507 if (UnicharIsHighSurrogate(characters[j]) && j+1<len && UnicharIsLowSurrogate(characters[j+1])) {
508 j++;
509 }
510 glyphIdx++;
511 }
512 if (currentFont.leading > lineSize.height) {
513 lineSize.height = currentFont.leading;
514 if (retValue.height + currentFont.ascender > constrainedSize.height) {
515 lastLine = YES;
516 finishLine = YES;
517 }
518 }
519 lineAscender = MAX(lineAscender, currentFont.ascender);
520 }
521 unichar c = characters[idx];
522 // Mark a wrap point before spaces and after any stretch of non-alpha characters
523 BOOL markWrap = NO;
524 if (c == (unichar)' ') {
525 markWrap = YES;
526 } else if ([alphaCharset characterIsMember:c]) {
527 if (!inAlpha) {
528 markWrap = YES;
529 inAlpha = YES;
530 }
531 } else {
532 inAlpha = NO;
533 }
534 if (markWrap) {
535 lastWrapCache = (__typeof__(lastWrapCache)){
536 .index = idx,
537 .glyphIndex = glyphIdx,
538 .currentRunIdx = currentRunIdx,
539 .lineSize = lineSize
540 };
541 }
542 // process the line
543 if (c == (unichar)'\n' || c == 0x0085) { // U+0085 is the NEXT_LINE unicode character
544 finishLine = YES;
545 skipCount = 1;
546 } else if (c == (unichar)'\r') {
547 finishLine = YES;
548 // check for CRLF
549 if (idx+1 < len && characters[idx+1] == (unichar)'\n') {
550 skipCount = 2;
551 } else {
552 skipCount = 1;
553 }
554 } else if (lineSize.width + advances[glyphIdx] > constrainedSize.width) {
555 finishLine = YES;
556 if (retValue.height + lineSize.height + currentFont.ascender > constrainedSize.height) {
557 lastLine = YES;
558 }
559 // walk backwards if wrapping is necessary
560 if (lastWrapCache.index > indexCache.index && lineBreakMode != UILineBreakModeCharacterWrap &&
561 (!lastLine || lineBreakMode != UILineBreakModeClip)) {
562 // we're doing some sort of word wrapping
563 idx = lastWrapCache.index;
564 lineSize = lastWrapCache.lineSize;
565 if (!lastLine) {
566 // re-check if this is the last line
567 if (lastWrapCache.currentRunIdx != currentRunIdx) {
568 currentRunIdx = lastWrapCache.currentRunIdx;
569 READ_RUN();
570 READ_GLYPHS();
571 }
572 if (retValue.height + lineSize.height + currentFont.ascender > constrainedSize.height) {
573 lastLine = YES;
574 }
575 }
576 glyphIdx = lastWrapCache.glyphIndex;
577 // skip any spaces
578 for (NSUInteger j = idx; j < len && characters[j] == (unichar)' '; j++) {
579 skipCount++;
580 }
581 }
582 }
583 }
584 if (finishLine) {
585 // TODO: support head/middle truncation
586 if (lastLine && idx < len && lineBreakMode == UILineBreakModeTailTruncation) {
587 // truncate
588 unichar ellipsis = 0x2026; // ellipsis (…)
589 CGGlyph ellipsisGlyph;
590 mapCharactersToGlyphsInFont(currentTable, &ellipsis, 1, &ellipsisGlyph, NULL);
591 CGFloat ellipsisWidth;
592 mapGlyphsToAdvancesInFont(currentFont, 1, &ellipsisGlyph, &ellipsisWidth);
593 while ((idx - indexCache.index) > 1 && lineSize.width + ellipsisWidth > constrainedSize.width) {
594 // we have more than 1 character and we're too wide, so back up
595 idx--;
596 if (UnicharIsHighSurrogate(characters[idx]) && UnicharIsLowSurrogate(characters[idx+1])) {
597 idx--;
598 }
599 if (idx < currentRun.index) {
600 ZFont *oldFont = currentFont;
601 do {
602 currentRunIdx--;
603 READ_RUN();
604 } while (idx < currentRun.index);
605 READ_GLYPHS();
606 glyphIdx = glyphCount-1;
607 if (oldFont != currentFont) {
608 mapCharactersToGlyphsInFont(currentTable, &ellipsis, 1, &ellipsisGlyph, NULL);
609 mapGlyphsToAdvancesInFont(currentFont, 1, &ellipsisGlyph, &ellipsisWidth);
610 }
611 } else {
612 glyphIdx--;
613 }
614 lineSize.width -= advances[glyphIdx];
615 }
616 // skip any spaces before truncating
617 while ((idx - indexCache.index) > 1 && characters[idx-1] == (unichar)' ') {
618 idx--;
619 if (idx < currentRun.index) {
620 currentRunIdx--;
621 READ_RUN();
622 READ_GLYPHS();
623 glyphIdx = glyphCount-1;
624 } else {
625 glyphIdx--;
626 }
627 lineSize.width -= advances[glyphIdx];
628 }
629 lineSize.width += ellipsisWidth;
630 glyphs[glyphIdx] = ellipsisGlyph;
631 idx++;
632 glyphIdx++;
633 }
634 retValue.width = MAX(retValue.width, lineSize.width);
635 retValue.height += lineSize.height;
636
637 // draw
638 if (performDraw) {
639 switch (alignment) {
640 case UITextAlignmentLeft:
641 drawPoint.x = 0;
642 break;
643 case UITextAlignmentCenter:
644 drawPoint.x = (constrainedSize.width - lineSize.width) / 2.0f;
645 break;
646 case UITextAlignmentRight:
647 drawPoint.x = constrainedSize.width - lineSize.width;
648 break;
649 }
650 NSUInteger stopGlyphIdx = glyphIdx;
651 NSUInteger lastRunIdx = currentRunIdx;
652 NSUInteger stopCharIdx = idx;
653 idx = indexCache.index;
654 if (currentRunIdx != indexCache.currentRunIdx) {
655 currentRunIdx = indexCache.currentRunIdx;
656 READ_RUN();
657 READ_GLYPHS();
658 }
659 glyphIdx = indexCache.glyphIndex;
660 for (NSUInteger drawIdx = currentRunIdx; drawIdx <= lastRunIdx; drawIdx++) {
661 if (drawIdx != currentRunIdx) {
662 currentRunIdx = drawIdx;
663 READ_RUN();
664 READ_GLYPHS();
665 }
666 NSUInteger numGlyphs;
667 if (drawIdx == lastRunIdx) {
668 numGlyphs = stopGlyphIdx - glyphIdx;
669 idx = stopCharIdx;
670 } else {
671 numGlyphs = glyphCount - glyphIdx;
672 idx = nextRunStart;
673 }
674 CGContextSetFont(ctx, currentFont.cgFont);
675 CGContextSetFontSize(ctx, currentFont.pointSize);
676 // calculate the fragment size
677 CGFloat fragmentWidth = 0;
678 for (NSUInteger g = 0; g < numGlyphs; g++) {
679 fragmentWidth += advances[glyphIdx + g];
680 }
681
682 if (!ignoreColor) {
683 UIColor *foregroundColor = getValueOrDefaultForRun(currentRun, ZForegroundColorAttributeName);
684 UIColor *backgroundColor = getValueOrDefaultForRun(currentRun, ZBackgroundColorAttributeName);
685 if (backgroundColor != nil && ![backgroundColor isEqual:[UIColor clearColor]]) {
686 [backgroundColor setFill];
687 UIRectFillUsingBlendMode((CGRect){ drawPoint, { fragmentWidth, lineSize.height } }, kCGBlendModeNormal);
688 }
689 [foregroundColor setFill];
690 }
691
692 CGContextShowGlyphsAtPoint(ctx, drawPoint.x, drawPoint.y + lineAscender, &glyphs[glyphIdx], numGlyphs);
693 NSNumber *underlineStyle = getValueOrDefaultForRun(currentRun, ZUnderlineStyleAttributeName);
694 if ([underlineStyle integerValue] & ZUnderlineStyleMask) {
695 // we only support single for the time being
696 UIRectFill(CGRectMake(drawPoint.x, drawPoint.y + lineAscender, fragmentWidth, 1));
697 }
698 drawPoint.x += fragmentWidth;
699 glyphIdx += numGlyphs;
700 }
701 drawPoint.y += lineSize.height;
702 }
703 idx += skipCount;
704 glyphIdx += skipCount;
705 lineCount++;
706 } else {
707 lineSize.width += advances[glyphIdx];
708 glyphIdx++;
709 idx++;
710 if (idx < len && UnicharIsHighSurrogate(characters[idx-1]) && UnicharIsLowSurrogate(characters[idx])) {
711 // skip the second half of the surrogate pair
712 idx++;
713 }
714 }
715 }
716 }
717 CFRelease(fontTableMap);
718 free(glyphs);
719 free(advances);
720 free(characters);
721
722#undef READ_GLYPHS
723#undef READ_RUN
724
725 return retValue;
726}
727
728static NSArray *attributeRunForFont(ZFont *font) {
729 return [NSArray arrayWithObject:[ZAttributeRun attributeRunWithIndex:0
730 attributes:[NSDictionary dictionaryWithObject:font
731 forKey:ZFontAttributeName]]];
732}
733
734static CGSize drawTextInRect(CGRect rect, NSString *text, NSArray *attributes, UILineBreakMode lineBreakMode,
735 UITextAlignment alignment, NSUInteger numberOfLines, BOOL ignoreColor) {
736 CGContextRef ctx = UIGraphicsGetCurrentContext();
737
738 CGContextSaveGState(ctx);
739
740 // flip it upside-down because our 0,0 is upper-left, whereas ttfs are for screens where 0,0 is lower-left
741 CGAffineTransform textTransform = CGAffineTransformMake(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
742 CGContextSetTextMatrix(ctx, textTransform);
743
744 CGContextTranslateCTM(ctx, rect.origin.x, rect.origin.y);
745
746 CGContextSetTextDrawingMode(ctx, kCGTextFill);
747 CGSize size = drawOrSizeTextConstrainedToSize(YES, text, attributes, rect.size, numberOfLines, lineBreakMode, alignment, ignoreColor);
748
749 CGContextRestoreGState(ctx);
750
751 return size;
752}
753
754@implementation NSString (FontLabelStringDrawing)
755// CGFontRef-based methods
756- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize {
757 return [self sizeWithZFont:[ZFont fontWithCGFont:font size:pointSize]];
758}
759
760- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize constrainedToSize:(CGSize)size {
761 return [self sizeWithZFont:[ZFont fontWithCGFont:font size:pointSize] constrainedToSize:size];
762}
763
764- (CGSize)sizeWithCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize constrainedToSize:(CGSize)size
765 lineBreakMode:(UILineBreakMode)lineBreakMode {
766 return [self sizeWithZFont:[ZFont fontWithCGFont:font size:pointSize] constrainedToSize:size lineBreakMode:lineBreakMode];
767}
768
769- (CGSize)drawAtPoint:(CGPoint)point withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize {
770 return [self drawAtPoint:point withZFont:[ZFont fontWithCGFont:font size:pointSize]];
771}
772
773- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize {
774 return [self drawInRect:rect withZFont:[ZFont fontWithCGFont:font size:pointSize]];
775}
776
777- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize lineBreakMode:(UILineBreakMode)lineBreakMode {
778 return [self drawInRect:rect withZFont:[ZFont fontWithCGFont:font size:pointSize] lineBreakMode:lineBreakMode];
779}
780
781- (CGSize)drawInRect:(CGRect)rect withCGFont:(CGFontRef)font pointSize:(CGFloat)pointSize
782 lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment {
783 return [self drawInRect:rect withZFont:[ZFont fontWithCGFont:font size:pointSize] lineBreakMode:lineBreakMode alignment:alignment];
784}
785
786// ZFont-based methods
787- (CGSize)sizeWithZFont:(ZFont *)font {
788 CGSize size = drawOrSizeTextConstrainedToSize(NO, self, attributeRunForFont(font), CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), 1,
789 UILineBreakModeClip, UITextAlignmentLeft, YES);
790 return CGSizeMake(ceilf(size.width), ceilf(size.height));
791}
792
793- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size {
794 return [self sizeWithZFont:font constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
795}
796
797/*
798 According to experimentation with UIStringDrawing, this can actually return a CGSize whose height is greater
799 than the one passed in. The two cases are as follows:
800 1. If the given size parameter's height is smaller than a single line, the returned value will
801 be the height of one line.
802 2. If the given size parameter's height falls between multiples of a line height, and the wrapped string
803 actually extends past the size.height, and the difference between size.height and the previous multiple
804 of a line height is >= the font's ascender, then the returned size's height is extended to the next line.
805 To put it simply, if the baseline point of a given line falls in the given size, the entire line will
806 be present in the output size.
807 */
808- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode {
809 size = drawOrSizeTextConstrainedToSize(NO, self, attributeRunForFont(font), size, 0, lineBreakMode, UITextAlignmentLeft, YES);
810 return CGSizeMake(ceilf(size.width), ceilf(size.height));
811}
812
813- (CGSize)sizeWithZFont:(ZFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
814 numberOfLines:(NSUInteger)numberOfLines {
815 size = drawOrSizeTextConstrainedToSize(NO, self, attributeRunForFont(font), size, numberOfLines, lineBreakMode, UITextAlignmentLeft, YES);
816 return CGSizeMake(ceilf(size.width), ceilf(size.height));
817}
818
819- (CGSize)drawAtPoint:(CGPoint)point withZFont:(ZFont *)font {
820 return [self drawAtPoint:point forWidth:CGFLOAT_MAX withZFont:font lineBreakMode:UILineBreakModeClip];
821}
822
823- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode {
824 return drawTextInRect((CGRect){ point, { width, CGFLOAT_MAX } }, self, attributeRunForFont(font), lineBreakMode, UITextAlignmentLeft, 1, YES);
825}
826
827- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font {
828 return [self drawInRect:rect withZFont:font lineBreakMode:UILineBreakModeWordWrap];
829}
830
831- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode {
832 return [self drawInRect:rect withZFont:font lineBreakMode:lineBreakMode alignment:UITextAlignmentLeft];
833}
834
835- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode
836 alignment:(UITextAlignment)alignment {
837 return drawTextInRect(rect, self, attributeRunForFont(font), lineBreakMode, alignment, 0, YES);
838}
839
840- (CGSize)drawInRect:(CGRect)rect withZFont:(ZFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode
841 alignment:(UITextAlignment)alignment numberOfLines:(NSUInteger)numberOfLines {
842 return drawTextInRect(rect, self, attributeRunForFont(font), lineBreakMode, alignment, numberOfLines, YES);
843}
844@end
845
846@implementation ZAttributedString (ZAttributedStringDrawing)
847- (CGSize)size {
848 CGSize size = drawOrSizeTextConstrainedToSize(NO, self.string, self.attributes, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), 1,
849 UILineBreakModeClip, UITextAlignmentLeft, NO);
850 return CGSizeMake(ceilf(size.width), ceilf(size.height));
851}
852
853- (CGSize)sizeConstrainedToSize:(CGSize)size {
854 return [self sizeConstrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
855}
856
857- (CGSize)sizeConstrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode {
858 size = drawOrSizeTextConstrainedToSize(NO, self.string, self.attributes, size, 0, lineBreakMode, UITextAlignmentLeft, NO);
859 return CGSizeMake(ceilf(size.width), ceilf(size.height));
860}
861
862- (CGSize)sizeConstrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
863 numberOfLines:(NSUInteger)numberOfLines {
864 size = drawOrSizeTextConstrainedToSize(NO, self.string, self.attributes, size, numberOfLines, lineBreakMode, UITextAlignmentLeft, NO);
865 return CGSizeMake(ceilf(size.width), ceilf(size.height));
866}
867
868- (CGSize)drawAtPoint:(CGPoint)point {
869 return [self drawAtPoint:point forWidth:CGFLOAT_MAX lineBreakMode:UILineBreakModeClip];
870}
871
872- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode {
873 return drawTextInRect((CGRect){ point, { width, CGFLOAT_MAX } }, self.string, self.attributes, lineBreakMode, UITextAlignmentLeft, 1, NO);
874}
875
876- (CGSize)drawInRect:(CGRect)rect {
877 return [self drawInRect:rect withLineBreakMode:UILineBreakModeWordWrap];
878}
879
880- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode {
881 return [self drawInRect:rect withLineBreakMode:lineBreakMode alignment:UITextAlignmentLeft];
882}
883
884- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment {
885 return drawTextInRect(rect, self.string, self.attributes, lineBreakMode, alignment, 0, NO);
886}
887
888- (CGSize)drawInRect:(CGRect)rect withLineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment
889 numberOfLines:(NSUInteger)numberOfLines {
890 return drawTextInRect(rect, self.string, self.attributes, lineBreakMode, alignment, numberOfLines, NO);
891}
892@end
diff --git a/libs/FontLabel/FontManager.h b/libs/FontLabel/FontManager.h new file mode 100755 index 0000000..1592b8a --- /dev/null +++ b/libs/FontLabel/FontManager.h
@@ -0,0 +1,85 @@
1//
2// FontManager.h
3// FontLabel
4//
5// Created by Kevin Ballard on 5/5/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import <Foundation/Foundation.h>
23#import <CoreGraphics/CoreGraphics.h>
24
25@class ZFont;
26
27@interface FontManager : NSObject {
28 CFMutableDictionaryRef fonts;
29 NSMutableDictionary *urls;
30}
31+ (FontManager *)sharedManager;
32/*!
33 @method
34 @abstract Loads a TTF font from the main bundle
35 @param filename The name of the font file to load (with or without extension).
36 @return YES if the font was loaded, NO if an error occurred
37 @discussion If the font has already been loaded, this method does nothing and returns YES.
38 This method first attempts to load the font by appending .ttf to the filename.
39 If that file does not exist, it tries the filename exactly as given.
40*/
41- (BOOL)loadFont:(NSString *)filename;
42/*!
43 @method
44 @abstract Loads a font from the given file URL
45 @param url A file URL that points to a font file
46 @return YES if the font was loaded, NO if an error occurred
47 @discussion If the font has already been loaded, this method does nothing and returns YES.
48*/
49- (BOOL)loadFontURL:(NSURL *)url;
50/*!
51 @method
52 @abstract Returns the loaded font with the given filename
53 @param filename The name of the font file that was given to -loadFont:
54 @return A CGFontRef, or NULL if the specified font cannot be found
55 @discussion If the font has not been loaded yet, -loadFont: will be
56 called with the given name first.
57*/
58- (CGFontRef)fontWithName:(NSString *)filename __AVAILABILITY_INTERNAL_DEPRECATED;
59/*!
60 @method
61 @abstract Returns a ZFont object corresponding to the loaded font with the given filename and point size
62 @param filename The name of the font file that was given to -loadFont:
63 @param pointSize The point size of the font
64 @return A ZFont, or NULL if the specified font cannot be found
65 @discussion If the font has not been loaded yet, -loadFont: will be
66 called with the given name first.
67*/
68- (ZFont *)zFontWithName:(NSString *)filename pointSize:(CGFloat)pointSize;
69/*!
70 @method
71 @abstract Returns a ZFont object corresponding to the loaded font with the given file URL and point size
72 @param url A file URL that points to a font file
73 @param pointSize The point size of the font
74 @return A ZFont, or NULL if the specified font cannot be loaded
75 @discussion If the font has not been loaded yet, -loadFontURL: will be called with the given URL first.
76*/
77- (ZFont *)zFontWithURL:(NSURL *)url pointSize:(CGFloat)pointSize;
78/*!
79 @method
80 @abstract Returns a CFArrayRef of all loaded CGFont objects
81 @return A CFArrayRef of all loaded CGFont objects
82 @description You are responsible for releasing the CFArrayRef
83*/
84- (CFArrayRef)copyAllFonts;
85@end
diff --git a/libs/FontLabel/FontManager.m b/libs/FontLabel/FontManager.m new file mode 100755 index 0000000..12eac2d --- /dev/null +++ b/libs/FontLabel/FontManager.m
@@ -0,0 +1,123 @@
1//
2// FontManager.m
3// FontLabel
4//
5// Created by Kevin Ballard on 5/5/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import "FontManager.h"
23#import "ZFont.h"
24
25static FontManager *sharedFontManager = nil;
26
27@implementation FontManager
28+ (FontManager *)sharedManager {
29 @synchronized(self) {
30 if (sharedFontManager == nil) {
31 sharedFontManager = [[self alloc] init];
32 }
33 }
34 return sharedFontManager;
35}
36
37- (id)init {
38 if ((self = [super init])) {
39 fonts = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
40 urls = [[NSMutableDictionary alloc] init];
41 }
42 return self;
43}
44
45- (BOOL)loadFont:(NSString *)filename {
46 NSString *fontPath = [[NSBundle mainBundle] pathForResource:filename ofType:@"ttf"];
47 if (fontPath == nil) {
48 fontPath = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
49 }
50 if (fontPath == nil) return NO;
51
52 NSURL *url = [NSURL fileURLWithPath:fontPath];
53 if ([self loadFontURL:url]) {
54 [urls setObject:url forKey:filename];
55 return YES;
56 }
57 return NO;
58}
59
60- (BOOL)loadFontURL:(NSURL *)url {
61 CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((CFURLRef)url);
62 if (fontDataProvider == NULL) return NO;
63 CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider);
64 CGDataProviderRelease(fontDataProvider);
65 if (newFont == NULL) return NO;
66
67 CFDictionarySetValue(fonts, url, newFont);
68 CGFontRelease(newFont);
69 return YES;
70}
71
72- (CGFontRef)fontWithName:(NSString *)filename {
73 CGFontRef font = NULL;
74 NSURL *url = [urls objectForKey:filename];
75 if (url == nil && [self loadFont:filename]) {
76 url = [urls objectForKey:filename];
77 }
78 if (url != nil) {
79 font = (CGFontRef)CFDictionaryGetValue(fonts, url);
80 }
81 return font;
82}
83
84- (ZFont *)zFontWithName:(NSString *)filename pointSize:(CGFloat)pointSize {
85 NSURL *url = [urls objectForKey:filename];
86 if (url == nil && [self loadFont:filename]) {
87 url = [urls objectForKey:filename];
88 }
89 if (url != nil) {
90 CGFontRef cgFont = (CGFontRef)CFDictionaryGetValue(fonts, url);
91 if (cgFont != NULL) {
92 return [ZFont fontWithCGFont:cgFont size:pointSize];
93 }
94 }
95 return nil;
96}
97
98- (ZFont *)zFontWithURL:(NSURL *)url pointSize:(CGFloat)pointSize {
99 CGFontRef cgFont = (CGFontRef)CFDictionaryGetValue(fonts, url);
100 if (cgFont == NULL && [self loadFontURL:url]) {
101 cgFont = (CGFontRef)CFDictionaryGetValue(fonts, url);
102 }
103 if (cgFont != NULL) {
104 return [ZFont fontWithCGFont:cgFont size:pointSize];
105 }
106 return nil;
107}
108
109- (CFArrayRef)copyAllFonts {
110 CFIndex count = CFDictionaryGetCount(fonts);
111 CGFontRef *values = (CGFontRef *)malloc(sizeof(CGFontRef) * count);
112 CFDictionaryGetKeysAndValues(fonts, NULL, (const void **)values);
113 CFArrayRef array = CFArrayCreate(NULL, (const void **)values, count, &kCFTypeArrayCallBacks);
114 free(values);
115 return array;
116}
117
118- (void)dealloc {
119 CFRelease(fonts);
120 [urls release];
121 [super dealloc];
122}
123@end
diff --git a/libs/FontLabel/ZAttributedString.h b/libs/FontLabel/ZAttributedString.h new file mode 100755 index 0000000..e194c81 --- /dev/null +++ b/libs/FontLabel/ZAttributedString.h
@@ -0,0 +1,77 @@
1//
2// ZAttributedString.h
3// FontLabel
4//
5// Created by Kevin Ballard on 9/22/09.
6// Copyright 2009 Zynga Game Networks. All rights reserved.
7//
8
9#import <Foundation/Foundation.h>
10
11#if NS_BLOCKS_AVAILABLE
12#define Z_BLOCKS 1
13#else
14// set this to 1 if you are using PLBlocks
15#define Z_BLOCKS 0
16#endif
17
18#if Z_BLOCKS
19enum {
20 ZAttributedStringEnumerationReverse = (1UL << 1),
21 ZAttributedStringEnumerationLongestEffectiveRangeNotRequired = (1UL << 20)
22};
23typedef NSUInteger ZAttributedStringEnumerationOptions;
24#endif
25
26@interface ZAttributedString : NSObject <NSCoding, NSCopying, NSMutableCopying> {
27 NSMutableString *_buffer;
28 NSMutableArray *_attributes;
29}
30@property (nonatomic, readonly) NSUInteger length;
31@property (nonatomic, readonly) NSString *string;
32- (id)initWithAttributedString:(ZAttributedString *)attr;
33- (id)initWithString:(NSString *)str;
34- (id)initWithString:(NSString *)str attributes:(NSDictionary *)attributes;
35- (id)attribute:(NSString *)attributeName atIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange;
36- (id)attribute:(NSString *)attributeName atIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange inRange:(NSRange)rangeLimit;
37- (ZAttributedString *)attributedSubstringFromRange:(NSRange)aRange;
38- (NSDictionary *)attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange;
39- (NSDictionary *)attributesAtIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange inRange:(NSRange)rangeLimit;
40#if Z_BLOCKS
41- (void)enumerateAttribute:(NSString *)attrName inRange:(NSRange)enumerationRange options:(ZAttributedStringEnumerationOptions)opts
42 usingBlock:(void (^)(id value, NSRange range, BOOL *stop))block;
43- (void)enumerateAttributesInRange:(NSRange)enumerationRange options:(ZAttributedStringEnumerationOptions)opts
44 usingBlock:(void (^)(NSDictionary *attrs, NSRange range, BOOL *stop))block;
45#endif
46- (BOOL)isEqualToAttributedString:(ZAttributedString *)otherString;
47@end
48
49@interface ZMutableAttributedString : ZAttributedString {
50}
51- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
52- (void)addAttributes:(NSDictionary *)attributes range:(NSRange)range;
53- (void)appendAttributedString:(ZAttributedString *)str;
54- (void)deleteCharactersInRange:(NSRange)range;
55- (void)insertAttributedString:(ZAttributedString *)str atIndex:(NSUInteger)idx;
56- (void)removeAttribute:(NSString *)name range:(NSRange)range;
57- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(ZAttributedString *)str;
58- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str;
59- (void)setAttributedString:(ZAttributedString *)str;
60- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)range;
61@end
62
63extern NSString * const ZFontAttributeName;
64extern NSString * const ZForegroundColorAttributeName;
65extern NSString * const ZBackgroundColorAttributeName;
66extern NSString * const ZUnderlineStyleAttributeName;
67
68enum {
69 ZUnderlineStyleNone = 0x00,
70 ZUnderlineStyleSingle = 0x01
71};
72#define ZUnderlineStyleMask 0x00FF
73
74enum {
75 ZUnderlinePatternSolid = 0x0000
76};
77#define ZUnderlinePatternMask 0xFF00
diff --git a/libs/FontLabel/ZAttributedString.m b/libs/FontLabel/ZAttributedString.m new file mode 100755 index 0000000..a4163bc --- /dev/null +++ b/libs/FontLabel/ZAttributedString.m
@@ -0,0 +1,597 @@
1//
2// ZAttributedString.m
3// FontLabel
4//
5// Created by Kevin Ballard on 9/22/09.
6// Copyright 2009 Zynga Game Networks. All rights reserved.
7//
8
9#import "ZAttributedString.h"
10#import "ZAttributedStringPrivate.h"
11
12@interface ZAttributedString ()
13- (NSUInteger)indexOfEffectiveAttributeRunForIndex:(NSUInteger)index;
14- (NSDictionary *)attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange uniquingOnName:(NSString *)attributeName;
15- (NSDictionary *)attributesAtIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange
16 inRange:(NSRange)rangeLimit uniquingOnName:(NSString *)attributeName;
17@end
18
19@interface ZAttributedString ()
20@property (nonatomic, readonly) NSArray *attributes;
21@end
22
23@implementation ZAttributedString
24@synthesize string = _buffer;
25@synthesize attributes = _attributes;
26
27- (id)initWithAttributedString:(ZAttributedString *)attr {
28 NSParameterAssert(attr != nil);
29 if ((self = [super init])) {
30 _buffer = [attr->_buffer mutableCopy];
31 _attributes = [[NSMutableArray alloc] initWithArray:attr->_attributes copyItems:YES];
32 }
33 return self;
34}
35
36- (id)initWithString:(NSString *)str {
37 return [self initWithString:str attributes:nil];
38}
39
40- (id)initWithString:(NSString *)str attributes:(NSDictionary *)attributes {
41 if ((self = [super init])) {
42 _buffer = [str mutableCopy];
43 _attributes = [[NSMutableArray alloc] initWithObjects:[ZAttributeRun attributeRunWithIndex:0 attributes:attributes], nil];
44 }
45 return self;
46}
47
48- (id)init {
49 return [self initWithString:@"" attributes:nil];
50}
51
52- (id)initWithCoder:(NSCoder *)decoder {
53 if ((self = [super init])) {
54 _buffer = [[decoder decodeObjectForKey:@"buffer"] mutableCopy];
55 _attributes = [[decoder decodeObjectForKey:@"attributes"] mutableCopy];
56 }
57 return self;
58}
59
60- (void)encodeWithCoder:(NSCoder *)aCoder {
61 [aCoder encodeObject:_buffer forKey:@"buffer"];
62 [aCoder encodeObject:_attributes forKey:@"attributes"];
63}
64
65- (id)copyWithZone:(NSZone *)zone {
66 return [self retain];
67}
68
69- (id)mutableCopyWithZone:(NSZone *)zone {
70 return [(ZMutableAttributedString *)[ZMutableAttributedString allocWithZone:zone] initWithAttributedString:self];
71}
72
73- (NSUInteger)length {
74 return [_buffer length];
75}
76
77- (NSString *)description {
78 NSMutableArray *components = [NSMutableArray arrayWithCapacity:[_attributes count]*2];
79 NSRange range = NSMakeRange(0, 0);
80 for (NSUInteger i = 0; i <= [_attributes count]; i++) {
81 range.location = NSMaxRange(range);
82 ZAttributeRun *run;
83 if (i < [_attributes count]) {
84 run = [_attributes objectAtIndex:i];
85 range.length = run.index - range.location;
86 } else {
87 run = nil;
88 range.length = [_buffer length] - range.location;
89 }
90 if (range.length > 0) {
91 [components addObject:[NSString stringWithFormat:@"\"%@\"", [_buffer substringWithRange:range]]];
92 }
93 if (run != nil) {
94 NSMutableArray *attrDesc = [NSMutableArray arrayWithCapacity:[run.attributes count]];
95 for (id key in run.attributes) {
96 [attrDesc addObject:[NSString stringWithFormat:@"%@: %@", key, [run.attributes objectForKey:key]]];
97 }
98 [components addObject:[NSString stringWithFormat:@"{%@}", [attrDesc componentsJoinedByString:@", "]]];
99 }
100 }
101 return [NSString stringWithFormat:@"%@", [components componentsJoinedByString:@" "]];
102}
103
104- (id)attribute:(NSString *)attributeName atIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange {
105 NSParameterAssert(attributeName != nil);
106 return [[self attributesAtIndex:index effectiveRange:aRange uniquingOnName:attributeName] objectForKey:attributeName];
107}
108
109- (id)attribute:(NSString *)attributeName atIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange inRange:(NSRange)rangeLimit {
110 NSParameterAssert(attributeName != nil);
111 return [[self attributesAtIndex:index longestEffectiveRange:aRange inRange:rangeLimit uniquingOnName:attributeName] objectForKey:attributeName];
112}
113
114- (ZAttributedString *)attributedSubstringFromRange:(NSRange)aRange {
115 if (NSMaxRange(aRange) > [_buffer length]) {
116 @throw [NSException exceptionWithName:NSRangeException reason:@"range was outisde of the attributed string" userInfo:nil];
117 }
118 ZMutableAttributedString *newStr = [self mutableCopy];
119 if (aRange.location > 0) {
120 [newStr deleteCharactersInRange:NSMakeRange(0, aRange.location)];
121 }
122 if (NSMaxRange(aRange) < [_buffer length]) {
123 [newStr deleteCharactersInRange:NSMakeRange(aRange.length, [_buffer length] - NSMaxRange(aRange))];
124 }
125 return [newStr autorelease];
126}
127
128- (NSDictionary *)attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange {
129 return [NSDictionary dictionaryWithDictionary:[self attributesAtIndex:index effectiveRange:aRange uniquingOnName:nil]];
130}
131
132- (NSDictionary *)attributesAtIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange inRange:(NSRange)rangeLimit {
133 return [NSDictionary dictionaryWithDictionary:[self attributesAtIndex:index longestEffectiveRange:aRange inRange:rangeLimit uniquingOnName:nil]];
134}
135
136#if Z_BLOCKS
137// Warning: this code has not been tested. The only guarantee is that it compiles.
138- (void)enumerateAttribute:(NSString *)attrName inRange:(NSRange)enumerationRange options:(ZAttributedStringEnumerationOptions)opts
139 usingBlock:(void (^)(id, NSRange, BOOL*))block {
140 if (opts & ZAttributedStringEnumerationLongestEffectiveRangeNotRequired) {
141 [self enumerateAttributesInRange:enumerationRange options:opts usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
142 id value = [attrs objectForKey:attrName];
143 if (value != nil) {
144 block(value, range, stop);
145 }
146 }];
147 } else {
148 __block id oldValue = nil;
149 __block NSRange effectiveRange = NSMakeRange(0, 0);
150 [self enumerateAttributesInRange:enumerationRange options:opts usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
151 id value = [attrs objectForKey:attrName];
152 if (oldValue == nil) {
153 oldValue = value;
154 effectiveRange = range;
155 } else if (value != nil && [oldValue isEqual:value]) {
156 // combine the attributes
157 effectiveRange = NSUnionRange(effectiveRange, range);
158 } else {
159 BOOL innerStop = NO;
160 block(oldValue, effectiveRange, &innerStop);
161 if (innerStop) {
162 *stop = YES;
163 oldValue = nil;
164 } else {
165 oldValue = value;
166 }
167 }
168 }];
169 if (oldValue != nil) {
170 BOOL innerStop = NO; // necessary for the block, but unused
171 block(oldValue, effectiveRange, &innerStop);
172 }
173 }
174}
175
176- (void)enumerateAttributesInRange:(NSRange)enumerationRange options:(ZAttributedStringEnumerationOptions)opts
177 usingBlock:(void (^)(NSDictionary*, NSRange, BOOL*))block {
178 // copy the attributes so we can mutate the string if necessary during enumeration
179 // also clip the array during copy to only the subarray of attributes that cover the requested range
180 NSArray *attrs;
181 if (NSEqualRanges(enumerationRange, NSMakeRange(0, 0))) {
182 attrs = [NSArray arrayWithArray:_attributes];
183 } else {
184 // in this binary search, last is the first run after the range
185 NSUInteger first = 0, last = [_attributes count];
186 while (last > first+1) {
187 NSUInteger pivot = (last + first) / 2;
188 ZAttributeRun *run = [_attributes objectAtIndex:pivot];
189 if (run.index < enumerationRange.location) {
190 first = pivot;
191 } else if (run.index >= NSMaxRange(enumerationRange)) {
192 last = pivot;
193 }
194 }
195 attrs = [_attributes subarrayWithRange:NSMakeRange(first, last-first)];
196 }
197 if (opts & ZAttributedStringEnumerationReverse) {
198 NSUInteger end = [_buffer length];
199 for (ZAttributeRun *run in [attrs reverseObjectEnumerator]) {
200 BOOL stop = NO;
201 NSUInteger start = run.index;
202 // clip to enumerationRange
203 start = MAX(start, enumerationRange.location);
204 end = MIN(end, NSMaxRange(enumerationRange));
205 block(run.attributes, NSMakeRange(start, end - start), &stop);
206 if (stop) break;
207 end = run.index;
208 }
209 } else {
210 NSUInteger start = 0;
211 ZAttributeRun *run = [attrs objectAtIndex:0];
212 NSInteger offset = 0;
213 NSInteger oldLength = [_buffer length];
214 for (NSUInteger i = 1;;i++) {
215 NSUInteger end;
216 if (i >= [attrs count]) {
217 end = oldLength;
218 } else {
219 end = [[attrs objectAtIndex:i] index];
220 }
221 BOOL stop = NO;
222 NSUInteger clippedStart = MAX(start, enumerationRange.location);
223 NSUInteger clippedEnd = MIN(end, NSMaxRange(enumerationRange));
224 block(run.attributes, NSMakeRange(clippedStart + offset, clippedEnd - start), &stop);
225 if (stop || i >= [attrs count]) break;
226 start = end;
227 NSUInteger newLength = [_buffer length];
228 offset += (newLength - oldLength);
229 oldLength = newLength;
230 }
231 }
232}
233#endif
234
235- (BOOL)isEqualToAttributedString:(ZAttributedString *)otherString {
236 return ([_buffer isEqualToString:otherString->_buffer] && [_attributes isEqualToArray:otherString->_attributes]);
237}
238
239- (BOOL)isEqual:(id)object {
240 return [object isKindOfClass:[ZAttributedString class]] && [self isEqualToAttributedString:(ZAttributedString *)object];
241}
242
243#pragma mark -
244
245- (NSUInteger)indexOfEffectiveAttributeRunForIndex:(NSUInteger)index {
246 NSUInteger first = 0, last = [_attributes count];
247 while (last > first + 1) {
248 NSUInteger pivot = (last + first) / 2;
249 ZAttributeRun *run = [_attributes objectAtIndex:pivot];
250 if (run.index > index) {
251 last = pivot;
252 } else if (run.index < index) {
253 first = pivot;
254 } else {
255 first = pivot;
256 break;
257 }
258 }
259 return first;
260}
261
262- (NSDictionary *)attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange uniquingOnName:(NSString *)attributeName {
263 if (index >= [_buffer length]) {
264 @throw [NSException exceptionWithName:NSRangeException reason:@"index beyond range of attributed string" userInfo:nil];
265 }
266 NSUInteger runIndex = [self indexOfEffectiveAttributeRunForIndex:index];
267 ZAttributeRun *run = [_attributes objectAtIndex:runIndex];
268 if (aRange != NULL) {
269 aRange->location = run.index;
270 runIndex++;
271 if (runIndex < [_attributes count]) {
272 aRange->length = [[_attributes objectAtIndex:runIndex] index] - aRange->location;
273 } else {
274 aRange->length = [_buffer length] - aRange->location;
275 }
276 }
277 return run.attributes;
278}
279- (NSDictionary *)attributesAtIndex:(NSUInteger)index longestEffectiveRange:(NSRangePointer)aRange
280 inRange:(NSRange)rangeLimit uniquingOnName:(NSString *)attributeName {
281 if (index >= [_buffer length]) {
282 @throw [NSException exceptionWithName:NSRangeException reason:@"index beyond range of attributed string" userInfo:nil];
283 } else if (NSMaxRange(rangeLimit) > [_buffer length]) {
284 @throw [NSException exceptionWithName:NSRangeException reason:@"rangeLimit beyond range of attributed string" userInfo:nil];
285 }
286 NSUInteger runIndex = [self indexOfEffectiveAttributeRunForIndex:index];
287 ZAttributeRun *run = [_attributes objectAtIndex:runIndex];
288 if (aRange != NULL) {
289 if (attributeName != nil) {
290 id value = [run.attributes objectForKey:attributeName];
291 NSUInteger endRunIndex = runIndex+1;
292 runIndex--;
293 // search backwards
294 while (1) {
295 if (run.index <= rangeLimit.location) {
296 break;
297 }
298 ZAttributeRun *prevRun = [_attributes objectAtIndex:runIndex];
299 id prevValue = [prevRun.attributes objectForKey:attributeName];
300 if (prevValue == value || (value != nil && [prevValue isEqual:value])) {
301 runIndex--;
302 run = prevRun;
303 } else {
304 break;
305 }
306 }
307 // search forwards
308 ZAttributeRun *endRun = nil;
309 while (endRunIndex < [_attributes count]) {
310 ZAttributeRun *nextRun = [_attributes objectAtIndex:endRunIndex];
311 if (nextRun.index >= NSMaxRange(rangeLimit)) {
312 endRun = nextRun;
313 break;
314 }
315 id nextValue = [nextRun.attributes objectForKey:attributeName];
316 if (nextValue == value || (value != nil && [nextValue isEqual:value])) {
317 endRunIndex++;
318 } else {
319 endRun = nextRun;
320 break;
321 }
322 }
323 aRange->location = MAX(run.index, rangeLimit.location);
324 aRange->length = MIN((endRun ? endRun.index : [_buffer length]), NSMaxRange(rangeLimit)) - aRange->location;
325 } else {
326 // with no attribute name, we don't need to do any real searching,
327 // as we already guarantee each run has unique attributes.
328 // just make sure to clip the range to the rangeLimit
329 aRange->location = MAX(run.index, rangeLimit.location);
330 ZAttributeRun *endRun = (runIndex+1 < [_attributes count] ? [_attributes objectAtIndex:runIndex+1] : nil);
331 aRange->length = MIN((endRun ? endRun.index : [_buffer length]), NSMaxRange(rangeLimit)) - aRange->location;
332 }
333 }
334 return run.attributes;
335}
336
337- (void)dealloc {
338 [_buffer release];
339 [_attributes release];
340 [super dealloc];
341}
342@end
343
344@interface ZMutableAttributedString ()
345- (void)cleanupAttributesInRange:(NSRange)range;
346- (NSRange)rangeOfAttributeRunsForRange:(NSRange)range;
347- (void)offsetRunsInRange:(NSRange )range byOffset:(NSInteger)offset;
348@end
349
350@implementation ZMutableAttributedString
351- (id)copyWithZone:(NSZone *)zone {
352 return [(ZAttributedString *)[ZAttributedString allocWithZone:zone] initWithAttributedString:self];
353}
354
355- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range {
356 range = [self rangeOfAttributeRunsForRange:range];
357 for (ZAttributeRun *run in [_attributes subarrayWithRange:range]) {
358 [run.attributes setObject:value forKey:name];
359 }
360 [self cleanupAttributesInRange:range];
361}
362
363- (void)addAttributes:(NSDictionary *)attributes range:(NSRange)range {
364 range = [self rangeOfAttributeRunsForRange:range];
365 for (ZAttributeRun *run in [_attributes subarrayWithRange:range]) {
366 [run.attributes addEntriesFromDictionary:attributes];
367 }
368 [self cleanupAttributesInRange:range];
369}
370
371- (void)appendAttributedString:(ZAttributedString *)str {
372 [self insertAttributedString:str atIndex:[_buffer length]];
373}
374
375- (void)deleteCharactersInRange:(NSRange)range {
376 NSRange runRange = [self rangeOfAttributeRunsForRange:range];
377 [_buffer replaceCharactersInRange:range withString:@""];
378 [_attributes removeObjectsInRange:runRange];
379 for (NSUInteger i = runRange.location; i < [_attributes count]; i++) {
380 ZAttributeRun *run = [_attributes objectAtIndex:i];
381 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:(run.index - range.length) attributes:run.attributes];
382 [_attributes replaceObjectAtIndex:i withObject:newRun];
383 [newRun release];
384 }
385 [self cleanupAttributesInRange:NSMakeRange(runRange.location, 0)];
386}
387
388- (void)insertAttributedString:(ZAttributedString *)str atIndex:(NSUInteger)idx {
389 [self replaceCharactersInRange:NSMakeRange(idx, 0) withAttributedString:str];
390}
391
392- (void)removeAttribute:(NSString *)name range:(NSRange)range {
393 range = [self rangeOfAttributeRunsForRange:range];
394 for (ZAttributeRun *run in [_attributes subarrayWithRange:range]) {
395 [run.attributes removeObjectForKey:name];
396 }
397 [self cleanupAttributesInRange:range];
398}
399
400- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(ZAttributedString *)str {
401 NSRange replaceRange = [self rangeOfAttributeRunsForRange:range];
402 NSInteger offset = [str->_buffer length] - range.length;
403 [_buffer replaceCharactersInRange:range withString:str->_buffer];
404 [_attributes replaceObjectsInRange:replaceRange withObjectsFromArray:str->_attributes];
405 NSRange newRange = NSMakeRange(replaceRange.location, [str->_attributes count]);
406 [self offsetRunsInRange:newRange byOffset:range.location];
407 [self offsetRunsInRange:NSMakeRange(NSMaxRange(newRange), [_attributes count] - NSMaxRange(newRange)) byOffset:offset];
408 [self cleanupAttributesInRange:NSMakeRange(newRange.location, 0)];
409 [self cleanupAttributesInRange:NSMakeRange(NSMaxRange(newRange), 0)];
410}
411
412- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str {
413 [self replaceCharactersInRange:range withAttributedString:[[[ZAttributedString alloc] initWithString:str] autorelease]];
414}
415
416- (void)setAttributedString:(ZAttributedString *)str {
417 [_buffer release], _buffer = [str->_buffer mutableCopy];
418 [_attributes release], _attributes = [str->_attributes mutableCopy];
419}
420
421- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)range {
422 range = [self rangeOfAttributeRunsForRange:range];
423 for (ZAttributeRun *run in [_attributes subarrayWithRange:range]) {
424 [run.attributes setDictionary:attributes];
425 }
426 [self cleanupAttributesInRange:range];
427}
428
429#pragma mark -
430
431// splits the existing runs to provide one or more new runs for the given range
432- (NSRange)rangeOfAttributeRunsForRange:(NSRange)range {
433 NSParameterAssert(NSMaxRange(range) <= [_buffer length]);
434
435 // find (or create) the first run
436 NSUInteger first = 0;
437 ZAttributeRun *lastRun = nil;
438 for (;;first++) {
439 if (first >= [_attributes count]) {
440 // we didn't find a run
441 first = [_attributes count];
442 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:range.location attributes:lastRun.attributes];
443 [_attributes addObject:newRun];
444 [newRun release];
445 break;
446 }
447 ZAttributeRun *run = [_attributes objectAtIndex:first];
448 if (run.index == range.location) {
449 break;
450 } else if (run.index > range.location) {
451 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:range.location attributes:lastRun.attributes];
452 [_attributes insertObject:newRun atIndex:first];
453 [newRun release];
454 break;
455 }
456 lastRun = run;
457 }
458
459 if (((ZAttributeRun *)[_attributes lastObject]).index < NSMaxRange(range)) {
460 NSRange subrange = NSMakeRange(first, [_attributes count] - first);
461 if (NSMaxRange(range) < [_buffer length]) {
462 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range)
463 attributes:(NSDictionary*)[(ZAttributeRun *)[_attributes lastObject] attributes]];
464 [_attributes addObject:newRun];
465 [newRun release];
466 }
467 return subrange;
468 } else {
469 // find the last run within and the first run after the range
470 NSUInteger lastIn = first, firstAfter = [_attributes count]-1;
471 while (firstAfter > lastIn + 1) {
472 NSUInteger idx = (firstAfter + lastIn) / 2;
473 ZAttributeRun *run = [_attributes objectAtIndex:idx];
474 if (run.index < range.location) {
475 lastIn = idx;
476 } else if (run.index > range.location) {
477 firstAfter = idx;
478 } else {
479 // this is definitively the first run after the range
480 firstAfter = idx;
481 break;
482 }
483 }
484 if ([[_attributes objectAtIndex:firstAfter] index] > NSMaxRange(range)) {
485 // the first after is too far after, insert another run!
486 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range)
487 attributes:[(ZAttributeRun *)[_attributes objectAtIndex:firstAfter-1] attributes]];
488 [_attributes insertObject:newRun atIndex:firstAfter];
489 [newRun release];
490 }
491 return NSMakeRange(lastIn, firstAfter - lastIn);
492 }
493}
494
495- (void)cleanupAttributesInRange:(NSRange)range {
496 // expand the range to include one surrounding attribute on each side
497 if (range.location > 0) {
498 range.location -= 1;
499 range.length += 1;
500 }
501 if (NSMaxRange(range) < [_attributes count]) {
502 range.length += 1;
503 } else {
504 // make sure the range is capped to the attributes count
505 range.length = [_attributes count] - range.location;
506 }
507 if (range.length == 0) return;
508 ZAttributeRun *lastRun = [_attributes objectAtIndex:range.location];
509 for (NSUInteger i = range.location+1; i < NSMaxRange(range);) {
510 ZAttributeRun *run = [_attributes objectAtIndex:i];
511 if ([lastRun.attributes isEqualToDictionary:run.attributes]) {
512 [_attributes removeObjectAtIndex:i];
513 range.length -= 1;
514 } else {
515 lastRun = run;
516 i++;
517 }
518 }
519}
520
521- (void)offsetRunsInRange:(NSRange)range byOffset:(NSInteger)offset {
522 for (NSUInteger i = range.location; i < NSMaxRange(range); i++) {
523 ZAttributeRun *run = [_attributes objectAtIndex:i];
524 ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:run.index + offset attributes:run.attributes];
525 [_attributes replaceObjectAtIndex:i withObject:newRun];
526 [newRun release];
527 }
528}
529@end
530
531@implementation ZAttributeRun
532@synthesize index = _index;
533@synthesize attributes = _attributes;
534
535+ (id)attributeRunWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs {
536 return [[[self alloc] initWithIndex:idx attributes:attrs] autorelease];
537}
538
539- (id)initWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs {
540 NSParameterAssert(idx >= 0);
541 if ((self = [super init])) {
542 _index = idx;
543 if (attrs == nil) {
544 _attributes = [[NSMutableDictionary alloc] init];
545 } else {
546 _attributes = [attrs mutableCopy];
547 }
548 }
549 return self;
550}
551
552- (id)initWithCoder:(NSCoder *)decoder {
553 if ((self = [super init])) {
554 _index = [[decoder decodeObjectForKey:@"index"] unsignedIntegerValue];
555 _attributes = [[decoder decodeObjectForKey:@"attributes"] mutableCopy];
556 }
557 return self;
558}
559
560- (id)init {
561 return [self initWithIndex:0 attributes:[NSDictionary dictionary]];
562}
563
564- (id)copyWithZone:(NSZone *)zone {
565 return [[ZAttributeRun allocWithZone:zone] initWithIndex:_index attributes:_attributes];
566}
567
568- (void)encodeWithCoder:(NSCoder *)aCoder {
569 [aCoder encodeObject:[NSNumber numberWithUnsignedInteger:_index] forKey:@"index"];
570 [aCoder encodeObject:_attributes forKey:@"attributes"];
571}
572
573- (NSString *)description {
574 NSMutableArray *components = [NSMutableArray arrayWithCapacity:[_attributes count]];
575 for (id key in _attributes) {
576 [components addObject:[NSString stringWithFormat:@"%@=%@", key, [_attributes objectForKey:key]]];
577 }
578 return [NSString stringWithFormat:@"<%@: %p index=%lu attributes={%@}>",
579 NSStringFromClass([self class]), self, (unsigned long)_index, [components componentsJoinedByString:@" "]];
580}
581
582- (BOOL)isEqual:(id)object {
583 if (![object isKindOfClass:[ZAttributeRun class]]) return NO;
584 ZAttributeRun *other = (ZAttributeRun *)object;
585 return _index == other->_index && [_attributes isEqualToDictionary:other->_attributes];
586}
587
588- (void)dealloc {
589 [_attributes release];
590 [super dealloc];
591}
592@end
593
594NSString * const ZFontAttributeName = @"ZFontAttributeName";
595NSString * const ZForegroundColorAttributeName = @"ZForegroundColorAttributeName";
596NSString * const ZBackgroundColorAttributeName = @"ZBackgroundColorAttributeName";
597NSString * const ZUnderlineStyleAttributeName = @"ZUnderlineStyleAttributeName";
diff --git a/libs/FontLabel/ZAttributedStringPrivate.h b/libs/FontLabel/ZAttributedStringPrivate.h new file mode 100755 index 0000000..1021d7b --- /dev/null +++ b/libs/FontLabel/ZAttributedStringPrivate.h
@@ -0,0 +1,24 @@
1//
2// ZAttributedStringPrivate.h
3// FontLabel
4//
5// Created by Kevin Ballard on 9/23/09.
6// Copyright 2009 Zynga Game Networks. All rights reserved.
7//
8
9#import <Foundation/Foundation.h>
10#import "ZAttributedString.h"
11
12@interface ZAttributeRun : NSObject <NSCopying, NSCoding> {
13 NSUInteger _index;
14 NSMutableDictionary *_attributes;
15}
16@property (nonatomic, readonly) NSUInteger index;
17@property (nonatomic, readonly) NSMutableDictionary *attributes;
18+ (id)attributeRunWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs;
19- (id)initWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs;
20@end
21
22@interface ZAttributedString (ZAttributedStringPrivate)
23@property (nonatomic, readonly) NSArray *attributes;
24@end
diff --git a/libs/FontLabel/ZFont.h b/libs/FontLabel/ZFont.h new file mode 100755 index 0000000..05ae823 --- /dev/null +++ b/libs/FontLabel/ZFont.h
@@ -0,0 +1,47 @@
1//
2// ZFont.h
3// FontLabel
4//
5// Created by Kevin Ballard on 7/2/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import <Foundation/Foundation.h>
23#import <UIKit/UIKit.h>
24
25@interface ZFont : NSObject {
26 CGFontRef _cgFont;
27 CGFloat _pointSize;
28 CGFloat _ratio;
29 NSString *_familyName;
30 NSString *_fontName;
31 NSString *_postScriptName;
32}
33@property (nonatomic, readonly) CGFontRef cgFont;
34@property (nonatomic, readonly) CGFloat pointSize;
35@property (nonatomic, readonly) CGFloat ascender;
36@property (nonatomic, readonly) CGFloat descender;
37@property (nonatomic, readonly) CGFloat leading;
38@property (nonatomic, readonly) CGFloat xHeight;
39@property (nonatomic, readonly) CGFloat capHeight;
40@property (nonatomic, readonly) NSString *familyName;
41@property (nonatomic, readonly) NSString *fontName;
42@property (nonatomic, readonly) NSString *postScriptName;
43+ (ZFont *)fontWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize;
44+ (ZFont *)fontWithUIFont:(UIFont *)uiFont;
45- (id)initWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize;
46- (ZFont *)fontWithSize:(CGFloat)fontSize;
47@end
diff --git a/libs/FontLabel/ZFont.m b/libs/FontLabel/ZFont.m new file mode 100755 index 0000000..793b13a --- /dev/null +++ b/libs/FontLabel/ZFont.m
@@ -0,0 +1,170 @@
1//
2// ZFont.m
3// FontLabel
4//
5// Created by Kevin Ballard on 7/2/09.
6// Copyright © 2009 Zynga Game Networks
7//
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#import "ZFont.h"
23
24@interface ZFont ()
25@property (nonatomic, readonly) CGFloat ratio;
26- (NSString *)copyNameTableEntryForID:(UInt16)nameID;
27@end
28
29@implementation ZFont
30@synthesize cgFont=_cgFont, pointSize=_pointSize, ratio=_ratio;
31
32+ (ZFont *)fontWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize {
33 return [[[self alloc] initWithCGFont:cgFont size:fontSize] autorelease];
34}
35
36+ (ZFont *)fontWithUIFont:(UIFont *)uiFont {
37 NSParameterAssert(uiFont != nil);
38 CGFontRef cgFont = CGFontCreateWithFontName((CFStringRef)uiFont.fontName);
39 ZFont *zFont = [[self alloc] initWithCGFont:cgFont size:uiFont.pointSize];
40 CGFontRelease(cgFont);
41 return [zFont autorelease];
42}
43
44- (id)initWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize {
45 if ((self = [super init])) {
46 _cgFont = CGFontRetain(cgFont);
47 _pointSize = fontSize;
48 _ratio = fontSize/CGFontGetUnitsPerEm(cgFont);
49 }
50 return self;
51}
52
53- (id)init {
54 NSAssert(NO, @"-init is not valid for ZFont");
55 return nil;
56}
57
58- (CGFloat)ascender {
59 return ceilf(self.ratio * CGFontGetAscent(self.cgFont));
60}
61
62- (CGFloat)descender {
63 return floorf(self.ratio * CGFontGetDescent(self.cgFont));
64}
65
66- (CGFloat)leading {
67 return (self.ascender - self.descender);
68}
69
70- (CGFloat)capHeight {
71 return ceilf(self.ratio * CGFontGetCapHeight(self.cgFont));
72}
73
74- (CGFloat)xHeight {
75 return ceilf(self.ratio * CGFontGetXHeight(self.cgFont));
76}
77
78- (NSString *)familyName {
79 if (_familyName == nil) {
80 _familyName = [self copyNameTableEntryForID:1];
81 }
82 return _familyName;
83}
84
85- (NSString *)fontName {
86 if (_fontName == nil) {
87 _fontName = [self copyNameTableEntryForID:4];
88 }
89 return _fontName;
90}
91
92- (NSString *)postScriptName {
93 if (_postScriptName == nil) {
94 _postScriptName = [self copyNameTableEntryForID:6];
95 }
96 return _postScriptName;
97}
98
99- (ZFont *)fontWithSize:(CGFloat)fontSize {
100 if (fontSize == self.pointSize) return self;
101 NSParameterAssert(fontSize > 0.0);
102 return [[[ZFont alloc] initWithCGFont:self.cgFont size:fontSize] autorelease];
103}
104
105- (BOOL)isEqual:(id)object {
106 if (![object isKindOfClass:[ZFont class]]) return NO;
107 ZFont *font = (ZFont *)object;
108 return (font.cgFont == self.cgFont && font.pointSize == self.pointSize);
109}
110
111- (NSString *)copyNameTableEntryForID:(UInt16)aNameID {
112 CFDataRef nameTable = CGFontCopyTableForTag(self.cgFont, 'name');
113 NSAssert1(nameTable != NULL, @"CGFontCopyTableForTag returned NULL for 'name' tag in font %@",
114 [(id)CFCopyDescription(self.cgFont) autorelease]);
115 const UInt8 * const bytes = CFDataGetBytePtr(nameTable);
116 NSAssert1(OSReadBigInt16(bytes, 0) == 0, @"name table for font %@ has bad version number",
117 [(id)CFCopyDescription(self.cgFont) autorelease]);
118 const UInt16 count = OSReadBigInt16(bytes, 2);
119 const UInt16 stringOffset = OSReadBigInt16(bytes, 4);
120 const UInt8 * const nameRecords = &bytes[6];
121 UInt16 nameLength = 0;
122 UInt16 nameOffset = 0;
123 NSStringEncoding encoding = 0;
124 for (UInt16 idx = 0; idx < count; idx++) {
125 const uintptr_t recordOffset = 12 * idx;
126 const UInt16 nameID = OSReadBigInt16(nameRecords, recordOffset + 6);
127 if (nameID != aNameID) continue;
128 const UInt16 platformID = OSReadBigInt16(nameRecords, recordOffset + 0);
129 const UInt16 platformSpecificID = OSReadBigInt16(nameRecords, recordOffset + 2);
130 encoding = 0;
131 // for now, we only support a subset of encodings
132 switch (platformID) {
133 case 0: // Unicode
134 encoding = NSUTF16StringEncoding;
135 break;
136 case 1: // Macintosh
137 switch (platformSpecificID) {
138 case 0:
139 encoding = NSMacOSRomanStringEncoding;
140 break;
141 }
142 case 3: // Microsoft
143 switch (platformSpecificID) {
144 case 1:
145 encoding = NSUTF16StringEncoding;
146 break;
147 }
148 }
149 if (encoding == 0) continue;
150 nameLength = OSReadBigInt16(nameRecords, recordOffset + 8);
151 nameOffset = OSReadBigInt16(nameRecords, recordOffset + 10);
152 break;
153 }
154 NSString *result = nil;
155 if (nameOffset > 0) {
156 const UInt8 *nameBytes = &bytes[stringOffset + nameOffset];
157 result = [[NSString alloc] initWithBytes:nameBytes length:nameLength encoding:encoding];
158 }
159 CFRelease(nameTable);
160 return result;
161}
162
163- (void)dealloc {
164 CGFontRelease(_cgFont);
165 [_familyName release];
166 [_fontName release];
167 [_postScriptName release];
168 [super dealloc];
169}
170@end
diff --git a/libs/README b/libs/README new file mode 100755 index 0000000..0d4d8fc --- /dev/null +++ b/libs/README
@@ -0,0 +1 @@
This directory contains the libraries used in cocos2d
diff --git a/libs/TouchJSON/CDataScanner.h b/libs/TouchJSON/CDataScanner.h new file mode 100755 index 0000000..41f68e8 --- /dev/null +++ b/libs/TouchJSON/CDataScanner.h
@@ -0,0 +1,71 @@
1//
2// CDataScanner.h
3// TouchCode
4//
5// Created by Jonathan Wight on 04/16/08.
6// Copyright 2008 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import <Foundation/Foundation.h>
31
32// NSScanner
33
34@interface CDataScanner : NSObject {
35 NSData *data;
36
37 u_int8_t *start;
38 u_int8_t *end;
39 u_int8_t *current;
40 NSUInteger length;
41}
42
43@property (readwrite, nonatomic, retain) NSData *data;
44@property (readwrite, nonatomic, assign) NSUInteger scanLocation;
45@property (readonly, nonatomic, assign) NSUInteger bytesRemaining;
46@property (readonly, nonatomic, assign) BOOL isAtEnd;
47
48- (id)initWithData:(NSData *)inData;
49
50- (unichar)currentCharacter;
51- (unichar)scanCharacter;
52- (BOOL)scanCharacter:(unichar)inCharacter;
53
54- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue;
55- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue;
56- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
57
58- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)outValue;
59- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
60
61- (BOOL)scanNumber:(NSNumber **)outValue;
62- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue;
63
64- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData;
65
66- (void)skipWhitespace;
67
68- (NSString *)remainingString;
69- (NSData *)remainingData;
70
71@end
diff --git a/libs/TouchJSON/CDataScanner.m b/libs/TouchJSON/CDataScanner.m new file mode 100755 index 0000000..b3cee6f --- /dev/null +++ b/libs/TouchJSON/CDataScanner.m
@@ -0,0 +1,340 @@
1//
2// CDataScanner.m
3// TouchCode
4//
5// Created by Jonathan Wight on 04/16/08.
6// Copyright 2008 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CDataScanner.h"
31
32#import "CDataScanner_Extensions.h"
33
34@interface CDataScanner ()
35@end
36
37#pragma mark -
38
39inline static unichar CharacterAtPointer(void *start, void *end)
40 {
41 #pragma unused(end)
42
43 const u_int8_t theByte = *(u_int8_t *)start;
44 if (theByte & 0x80)
45 {
46 // TODO -- UNICODE!!!! (well in theory nothing todo here)
47 }
48 const unichar theCharacter = theByte;
49 return(theCharacter);
50 }
51
52 static NSCharacterSet *sDoubleCharacters = NULL;
53
54 @implementation CDataScanner
55
56- (id)init
57 {
58 if ((self = [super init]) != NULL)
59 {
60 }
61 return(self);
62 }
63
64- (id)initWithData:(NSData *)inData;
65 {
66 if ((self = [self init]) != NULL)
67 {
68 [self setData:inData];
69 }
70 return(self);
71 }
72
73 + (void)initialize
74 {
75 if (sDoubleCharacters == NULL)
76 {
77 sDoubleCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-+."] retain];
78 }
79 }
80
81- (void)dealloc
82 {
83 [data release];
84 data = NULL;
85 //
86 [super dealloc];
87 }
88
89- (NSUInteger)scanLocation
90 {
91 return(current - start);
92 }
93
94- (NSUInteger)bytesRemaining
95 {
96 return(end - current);
97 }
98
99- (NSData *)data
100 {
101 return(data);
102 }
103
104- (void)setData:(NSData *)inData
105 {
106 if (data != inData)
107 {
108 [data release];
109 data = [inData retain];
110 }
111
112 if (data)
113 {
114 start = (u_int8_t *)data.bytes;
115 end = start + data.length;
116 current = start;
117 length = data.length;
118 }
119 else
120 {
121 start = NULL;
122 end = NULL;
123 current = NULL;
124 length = 0;
125 }
126 }
127
128- (void)setScanLocation:(NSUInteger)inScanLocation
129 {
130 current = start + inScanLocation;
131 }
132
133- (BOOL)isAtEnd
134 {
135 return(self.scanLocation >= length);
136 }
137
138- (unichar)currentCharacter
139 {
140 return(CharacterAtPointer(current, end));
141 }
142
143#pragma mark -
144
145- (unichar)scanCharacter
146 {
147 const unichar theCharacter = CharacterAtPointer(current++, end);
148 return(theCharacter);
149 }
150
151- (BOOL)scanCharacter:(unichar)inCharacter
152 {
153 unichar theCharacter = CharacterAtPointer(current, end);
154 if (theCharacter == inCharacter)
155 {
156 ++current;
157 return(YES);
158 }
159 else
160 return(NO);
161 }
162
163- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue
164 {
165 const size_t theLength = strlen(inString);
166 if ((size_t)(end - current) < theLength)
167 return(NO);
168 if (strncmp((char *)current, inString, theLength) == 0)
169 {
170 current += theLength;
171 if (outValue)
172 *outValue = [NSString stringWithUTF8String:inString];
173 return(YES);
174 }
175 return(NO);
176 }
177
178- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue
179 {
180 if ((size_t)(end - current) < inString.length)
181 return(NO);
182 if (strncmp((char *)current, [inString UTF8String], inString.length) == 0)
183 {
184 current += inString.length;
185 if (outValue)
186 *outValue = inString;
187 return(YES);
188 }
189 return(NO);
190 }
191
192- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
193 {
194 u_int8_t *P;
195 for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P)
196 ;
197
198 if (P == current)
199 {
200 return(NO);
201 }
202
203 if (outValue)
204 {
205 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
206 }
207
208 current = P;
209
210 return(YES);
211 }
212
213- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue
214 {
215 const char *theToken = [inString UTF8String];
216 const char *theResult = strnstr((char *)current, theToken, end - current);
217 if (theResult == NULL)
218 {
219 return(NO);
220 }
221
222 if (outValue)
223 {
224 *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease];
225 }
226
227 current = (u_int8_t *)theResult;
228
229 return(YES);
230 }
231
232- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
233 {
234 u_int8_t *P;
235 for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P)
236 ;
237
238 if (P == current)
239 {
240 return(NO);
241 }
242
243 if (outValue)
244 {
245 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
246 }
247
248 current = P;
249
250 return(YES);
251 }
252
253- (BOOL)scanNumber:(NSNumber **)outValue
254 {
255 NSString *theString = NULL;
256 if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString])
257 {
258 if ([theString rangeOfString:@"."].location != NSNotFound)
259 {
260 if (outValue)
261 {
262 *outValue = [NSDecimalNumber decimalNumberWithString:theString];
263 }
264 return(YES);
265 }
266 else if ([theString rangeOfString:@"-"].location != NSNotFound)
267 {
268 if (outValue != NULL)
269 {
270 *outValue = [NSNumber numberWithLongLong:[theString longLongValue]];
271 }
272 return(YES);
273 }
274 else
275 {
276 if (outValue != NULL)
277 {
278 *outValue = [NSNumber numberWithUnsignedLongLong:strtoull([theString UTF8String], NULL, 0)];
279 }
280 return(YES);
281 }
282
283 }
284 return(NO);
285 }
286
287- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue;
288 {
289 NSString *theString = NULL;
290 if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString])
291 {
292 if (outValue)
293 {
294 *outValue = [NSDecimalNumber decimalNumberWithString:theString];
295 }
296 return(YES);
297 }
298 return(NO);
299 }
300
301- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData;
302 {
303 if (self.bytesRemaining < inLength)
304 {
305 return(NO);
306 }
307
308 if (outData)
309 {
310 *outData = [NSData dataWithBytes:current length:inLength];
311 }
312
313 current += inLength;
314 return(YES);
315 }
316
317
318- (void)skipWhitespace
319 {
320 u_int8_t *P;
321 for (P = current; P < end && (isspace(*P)); ++P)
322 ;
323
324 current = P;
325 }
326
327- (NSString *)remainingString
328 {
329 NSData *theRemainingData = [NSData dataWithBytes:current length:end - current];
330 NSString *theString = [[[NSString alloc] initWithData:theRemainingData encoding:NSUTF8StringEncoding] autorelease];
331 return(theString);
332 }
333
334- (NSData *)remainingData;
335 {
336 NSData *theRemainingData = [NSData dataWithBytes:current length:end - current];
337 return(theRemainingData);
338 }
339
340 @end
diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.h b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h new file mode 100755 index 0000000..cde1dbb --- /dev/null +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h
@@ -0,0 +1,40 @@
1//
2// CDataScanner_Extensions.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/08/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CDataScanner.h"
31
32@interface CDataScanner (CDataScanner_Extensions)
33
34- (BOOL)scanCStyleComment:(NSString **)outComment;
35- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment;
36
37- (NSUInteger)lineOfScanLocation;
38- (NSDictionary *)userInfoForScanLocation;
39
40@end
diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.m b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m new file mode 100755 index 0000000..90dbbda --- /dev/null +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m
@@ -0,0 +1,135 @@
1//
2// CDataScanner_Extensions.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/08/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CDataScanner_Extensions.h"
31
32#define LF 0x000a // Line Feed
33#define FF 0x000c // Form Feed
34#define CR 0x000d // Carriage Return
35#define NEL 0x0085 // Next Line
36#define LS 0x2028 // Line Separator
37#define PS 0x2029 // Paragraph Separator
38
39@implementation CDataScanner (CDataScanner_Extensions)
40
41- (BOOL)scanCStyleComment:(NSString **)outComment
42{
43if ([self scanString:@"/*" intoString:NULL] == YES)
44 {
45 NSString *theComment = NULL;
46 if ([self scanUpToString:@"*/" intoString:&theComment] == NO)
47 [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."];
48
49 if ([theComment rangeOfString:@"/*"].location != NSNotFound)
50 [NSException raise:NSGenericException format:@"C style comments should not be nested."];
51
52 if ([self scanString:@"*/" intoString:NULL] == NO)
53 [NSException raise:NSGenericException format:@"C style comment did not end correctly."];
54
55 if (outComment != NULL)
56 *outComment = theComment;
57
58 return(YES);
59 }
60else
61 {
62 return(NO);
63 }
64}
65
66- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment
67 {
68 if ([self scanString:@"//" intoString:NULL] == YES)
69 {
70 unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, };
71 NSCharacterSet *theLineBreaksCharacterSet = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]];
72
73 NSString *theComment = NULL;
74 [self scanUpToCharactersFromSet:theLineBreaksCharacterSet intoString:&theComment];
75 [self scanCharactersFromSet:theLineBreaksCharacterSet intoString:NULL];
76
77 if (outComment != NULL)
78 *outComment = theComment;
79
80 return(YES);
81 }
82 else
83 {
84 return(NO);
85 }
86 }
87
88- (NSUInteger)lineOfScanLocation
89 {
90 NSUInteger theLine = 0;
91 for (const u_int8_t *C = start; C < current; ++C)
92 {
93 // TODO: JIW What about MS-DOS line endings you bastard! (Also other unicode line endings)
94 if (*C == '\n' || *C == '\r')
95 {
96 ++theLine;
97 }
98 }
99 return(theLine);
100 }
101
102- (NSDictionary *)userInfoForScanLocation
103 {
104 NSUInteger theLine = 0;
105 const u_int8_t *theLineStart = start;
106 for (const u_int8_t *C = start; C < current; ++C)
107 {
108 if (*C == '\n' || *C == '\r')
109 {
110 theLineStart = C - 1;
111 ++theLine;
112 }
113 }
114
115 NSUInteger theCharacter = current - theLineStart;
116
117 NSRange theStartRange = NSIntersectionRange((NSRange){ .location = MAX((NSInteger)self.scanLocation - 20, 0), .length = 20 + (NSInteger)self.scanLocation - 20 }, (NSRange){ .location = 0, .length = self.data.length });
118 NSRange theEndRange = NSIntersectionRange((NSRange){ .location = self.scanLocation, .length = 20 }, (NSRange){ .location = 0, .length = self.data.length });
119
120
121 NSString *theSnippet = [NSString stringWithFormat:@"%@!HERE>!%@",
122 [[[NSString alloc] initWithData:[self.data subdataWithRange:theStartRange] encoding:NSUTF8StringEncoding] autorelease],
123 [[[NSString alloc] initWithData:[self.data subdataWithRange:theEndRange] encoding:NSUTF8StringEncoding] autorelease]
124 ];
125
126 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
127 [NSNumber numberWithUnsignedInteger:theLine], @"line",
128 [NSNumber numberWithUnsignedInteger:theCharacter], @"character",
129 [NSNumber numberWithUnsignedInteger:self.scanLocation], @"location",
130 theSnippet, @"snippet",
131 NULL];
132 return(theUserInfo);
133 }
134
135@end
diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h new file mode 100755 index 0000000..6e611d0 --- /dev/null +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h
@@ -0,0 +1,37 @@
1//
2// NSDictionary_JSONExtensions.h
3// TouchCode
4//
5// Created by Jonathan Wight on 04/17/08.
6// Copyright 2008 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import <Foundation/Foundation.h>
31
32@interface NSDictionary (NSDictionary_JSONExtensions)
33
34+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError;
35+ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError;
36
37@end
diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m new file mode 100755 index 0000000..c0bb43c --- /dev/null +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m
@@ -0,0 +1,47 @@
1//
2// NSDictionary_JSONExtensions.m
3// TouchCode
4//
5// Created by Jonathan Wight on 04/17/08.
6// Copyright 2008 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "NSDictionary_JSONExtensions.h"
31
32#import "CJSONDeserializer.h"
33
34@implementation NSDictionary (NSDictionary_JSONExtensions)
35
36+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError
37 {
38 return([[CJSONDeserializer deserializer] deserialize:inData error:outError]);
39 }
40
41+ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError;
42 {
43 NSData *theData = [inJSON dataUsingEncoding:NSUTF8StringEncoding];
44 return([self dictionaryWithJSONData:theData error:outError]);
45 }
46
47@end
diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.h b/libs/TouchJSON/JSON/CJSONDeserializer.h new file mode 100755 index 0000000..0c3ed02 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONDeserializer.h
@@ -0,0 +1,63 @@
1//
2// CJSONDeserializer.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/15/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import <Foundation/Foundation.h>
31
32#import "CJSONScanner.h"
33
34extern NSString *const kJSONDeserializerErrorDomain /* = @"CJSONDeserializerErrorDomain" */;
35
36enum {
37 kJSONDeserializationOptions_MutableContainers = kJSONScannerOptions_MutableContainers,
38 kJSONDeserializationOptions_MutableLeaves = kJSONScannerOptions_MutableLeaves,
39};
40typedef NSUInteger EJSONDeserializationOptions;
41
42@class CJSONScanner;
43
44@interface CJSONDeserializer : NSObject {
45 CJSONScanner *scanner;
46 EJSONDeserializationOptions options;
47}
48
49@property (readwrite, nonatomic, retain) CJSONScanner *scanner;
50/// Object to return instead when a null encountered in the JSON. Defaults to NSNull. Setting to null causes the scanner to skip null values.
51@property (readwrite, nonatomic, retain) id nullObject;
52/// JSON must be encoded in Unicode (UTF-8, UTF-16 or UTF-32). Use this if you expect to get the JSON in another encoding.
53@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding;
54@property (readwrite, nonatomic, assign) EJSONDeserializationOptions options;
55
56+ (id)deserializer;
57
58- (id)deserialize:(NSData *)inData error:(NSError **)outError;
59
60- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError;
61- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError;
62
63@end
diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.m b/libs/TouchJSON/JSON/CJSONDeserializer.m new file mode 100755 index 0000000..27a2d03 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONDeserializer.m
@@ -0,0 +1,161 @@
1//
2// CJSONDeserializer.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/15/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CJSONDeserializer.h"
31
32#import "CJSONScanner.h"
33#import "CDataScanner.h"
34
35NSString *const kJSONDeserializerErrorDomain = @"CJSONDeserializerErrorDomain";
36
37@interface CJSONDeserializer ()
38@end
39
40@implementation CJSONDeserializer
41
42@synthesize scanner;
43@synthesize options;
44
45+ (id)deserializer
46 {
47 return([[[self alloc] init] autorelease]);
48 }
49
50- (id)init
51 {
52 if ((self = [super init]) != NULL)
53 {
54 }
55 return(self);
56 }
57
58- (void)dealloc
59 {
60 [scanner release];
61 scanner = NULL;
62 //
63 [super dealloc];
64 }
65
66#pragma mark -
67
68- (CJSONScanner *)scanner
69 {
70 if (scanner == NULL)
71 {
72 scanner = [[CJSONScanner alloc] init];
73 }
74 return(scanner);
75 }
76
77- (id)nullObject
78 {
79 return(self.scanner.nullObject);
80 }
81
82- (void)setNullObject:(id)inNullObject
83 {
84 self.scanner.nullObject = inNullObject;
85 }
86
87#pragma mark -
88
89- (NSStringEncoding)allowedEncoding
90 {
91 return(self.scanner.allowedEncoding);
92 }
93
94- (void)setAllowedEncoding:(NSStringEncoding)inAllowedEncoding
95 {
96 self.scanner.allowedEncoding = inAllowedEncoding;
97 }
98
99#pragma mark -
100
101- (id)deserialize:(NSData *)inData error:(NSError **)outError
102 {
103 if (inData == NULL || [inData length] == 0)
104 {
105 if (outError)
106 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
107
108 return(NULL);
109 }
110 if ([self.scanner setData:inData error:outError] == NO)
111 {
112 return(NULL);
113 }
114 id theObject = NULL;
115 if ([self.scanner scanJSONObject:&theObject error:outError] == YES)
116 return(theObject);
117 else
118 return(NULL);
119 }
120
121- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError
122 {
123 if (inData == NULL || [inData length] == 0)
124 {
125 if (outError)
126 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
127
128 return(NULL);
129 }
130 if ([self.scanner setData:inData error:outError] == NO)
131 {
132 return(NULL);
133 }
134 NSDictionary *theDictionary = NULL;
135 if ([self.scanner scanJSONDictionary:&theDictionary error:outError] == YES)
136 return(theDictionary);
137 else
138 return(NULL);
139 }
140
141- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError
142 {
143 if (inData == NULL || [inData length] == 0)
144 {
145 if (outError)
146 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
147
148 return(NULL);
149 }
150 if ([self.scanner setData:inData error:outError] == NO)
151 {
152 return(NULL);
153 }
154 NSArray *theArray = NULL;
155 if ([self.scanner scanJSONArray:&theArray error:outError] == YES)
156 return(theArray);
157 else
158 return(NULL);
159 }
160
161@end
diff --git a/libs/TouchJSON/JSON/CJSONScanner.h b/libs/TouchJSON/JSON/CJSONScanner.h new file mode 100755 index 0000000..d410893 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONScanner.h
@@ -0,0 +1,95 @@
1//
2// CJSONScanner.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/07/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CDataScanner.h"
31
32enum {
33 kJSONScannerOptions_MutableContainers = 0x1,
34 kJSONScannerOptions_MutableLeaves = 0x2,
35};
36typedef NSUInteger EJSONScannerOptions;
37
38/// CDataScanner subclass that understands JSON syntax natively. You should generally use CJSONDeserializer instead of this class. (TODO - this could have been a category?)
39@interface CJSONScanner : CDataScanner {
40 BOOL strictEscapeCodes;
41 id nullObject;
42 NSStringEncoding allowedEncoding;
43 EJSONScannerOptions options;
44}
45
46@property (readwrite, nonatomic, assign) BOOL strictEscapeCodes;
47@property (readwrite, nonatomic, retain) id nullObject;
48@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding;
49@property (readwrite, nonatomic, assign) EJSONScannerOptions options;
50
51- (BOOL)setData:(NSData *)inData error:(NSError **)outError;
52
53- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError;
54- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError;
55- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError;
56- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError;
57- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError;
58
59@end
60
61extern NSString *const kJSONScannerErrorDomain /* = @"kJSONScannerErrorDomain" */;
62
63typedef enum {
64
65 // Fundamental scanning errors
66 kJSONScannerErrorCode_NothingToScan = -11,
67 kJSONScannerErrorCode_CouldNotDecodeData = -12,
68 kJSONScannerErrorCode_CouldNotSerializeData = -13,
69 kJSONScannerErrorCode_CouldNotSerializeObject = -14,
70 kJSONScannerErrorCode_CouldNotScanObject = -15,
71
72 // Dictionary scanning
73 kJSONScannerErrorCode_DictionaryStartCharacterMissing = -101,
74 kJSONScannerErrorCode_DictionaryKeyScanFailed = -102,
75 kJSONScannerErrorCode_DictionaryKeyNotTerminated = -103,
76 kJSONScannerErrorCode_DictionaryValueScanFailed = -104,
77 kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter = -105,
78 kJSONScannerErrorCode_DictionaryNotTerminated = -106,
79
80 // Array scanning
81 kJSONScannerErrorCode_ArrayStartCharacterMissing = -201,
82 kJSONScannerErrorCode_ArrayValueScanFailed = -202,
83 kJSONScannerErrorCode_ArrayValueIsNull = -203,
84 kJSONScannerErrorCode_ArrayNotTerminated = -204,
85
86 // String scanning
87 kJSONScannerErrorCode_StringNotStartedWithBackslash = -301,
88 kJSONScannerErrorCode_StringUnicodeNotDecoded = -302,
89 kJSONScannerErrorCode_StringUnknownEscapeCode = -303,
90 kJSONScannerErrorCode_StringNotTerminated = -304,
91
92 // Number scanning
93 kJSONScannerErrorCode_NumberNotScannable = -401
94
95} EJSONScannerErrorCode;
diff --git a/libs/TouchJSON/JSON/CJSONScanner.m b/libs/TouchJSON/JSON/CJSONScanner.m new file mode 100755 index 0000000..c5ffeb4 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONScanner.m
@@ -0,0 +1,676 @@
1//
2// CJSONScanner.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/07/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CJSONScanner.h"
31
32#import "CDataScanner_Extensions.h"
33
34#if !defined(TREAT_COMMENTS_AS_WHITESPACE)
35#define TREAT_COMMENTS_AS_WHITESPACE 0
36#endif // !defined(TREAT_COMMENTS_AS_WHITESPACE)
37
38NSString *const kJSONScannerErrorDomain = @"kJSONScannerErrorDomain";
39
40inline static int HexToInt(char inCharacter)
41 {
42 int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, };
43 if (inCharacter >= '0' && inCharacter <= 'f')
44 return(theValues[inCharacter - '0']);
45 else
46 return(-1);
47 }
48
49@interface CJSONScanner ()
50- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue;
51@end
52
53#pragma mark -
54
55@implementation CJSONScanner
56
57@synthesize strictEscapeCodes;
58@synthesize nullObject;
59@synthesize allowedEncoding;
60@synthesize options;
61
62- (id)init
63 {
64 if ((self = [super init]) != NULL)
65 {
66 strictEscapeCodes = NO;
67 nullObject = [[NSNull null] retain];
68 }
69 return(self);
70 }
71
72- (void)dealloc
73 {
74 [nullObject release];
75 nullObject = NULL;
76 //
77 [super dealloc];
78 }
79
80#pragma mark -
81
82- (BOOL)setData:(NSData *)inData error:(NSError **)outError;
83 {
84 NSData *theData = inData;
85 if (theData && theData.length >= 4)
86 {
87 // This code is lame, but it works. Because the first character of any JSON string will always be a (ascii) control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt
88 const char *theChars = theData.bytes;
89 NSStringEncoding theEncoding = NSUTF8StringEncoding;
90 if (theChars[0] != 0 && theChars[1] == 0)
91 {
92 if (theChars[2] != 0 && theChars[3] == 0)
93 theEncoding = NSUTF16LittleEndianStringEncoding;
94 else if (theChars[2] == 0 && theChars[3] == 0)
95 theEncoding = NSUTF32LittleEndianStringEncoding;
96 }
97 else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0)
98 {
99 if (theChars[1] == 0)
100 theEncoding = NSUTF32BigEndianStringEncoding;
101 else if (theChars[1] != 0)
102 theEncoding = NSUTF16BigEndianStringEncoding;
103 }
104
105 NSString *theString = [[NSString alloc] initWithData:theData encoding:theEncoding];
106 if (theString == NULL && self.allowedEncoding != 0)
107 {
108 theString = [[NSString alloc] initWithData:theData encoding:self.allowedEncoding];
109 }
110 theData = [theString dataUsingEncoding:NSUTF8StringEncoding];
111 [theString release];
112 }
113
114 if (theData)
115 {
116 [super setData:theData];
117 return(YES);
118 }
119 else
120 {
121 if (outError)
122 {
123 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
124 @"Could not scan data. Data wasn't encoded properly?", NSLocalizedDescriptionKey,
125 NULL];
126 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
127 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotDecodeData userInfo:theUserInfo];
128 }
129 return(NO);
130 }
131 }
132
133- (void)setData:(NSData *)inData
134 {
135 [self setData:inData error:NULL];
136 }
137
138#pragma mark -
139
140- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError
141 {
142 BOOL theResult = YES;
143
144 [self skipWhitespace];
145
146 id theObject = NULL;
147
148 const unichar C = [self currentCharacter];
149 switch (C)
150 {
151 case 't':
152 if ([self scanUTF8String:"true" intoString:NULL])
153 {
154 theObject = [NSNumber numberWithBool:YES];
155 }
156 break;
157 case 'f':
158 if ([self scanUTF8String:"false" intoString:NULL])
159 {
160 theObject = [NSNumber numberWithBool:NO];
161 }
162 break;
163 case 'n':
164 if ([self scanUTF8String:"null" intoString:NULL])
165 {
166 theObject = self.nullObject;
167 }
168 break;
169 case '\"':
170 case '\'':
171 theResult = [self scanJSONStringConstant:&theObject error:outError];
172 break;
173 case '0':
174 case '1':
175 case '2':
176 case '3':
177 case '4':
178 case '5':
179 case '6':
180 case '7':
181 case '8':
182 case '9':
183 case '-':
184 theResult = [self scanJSONNumberConstant:&theObject error:outError];
185 break;
186 case '{':
187 theResult = [self scanJSONDictionary:&theObject error:outError];
188 break;
189 case '[':
190 theResult = [self scanJSONArray:&theObject error:outError];
191 break;
192 default:
193 theResult = NO;
194 if (outError)
195 {
196 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
197 @"Could not scan object. Character not a valid JSON character.", NSLocalizedDescriptionKey,
198 NULL];
199 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
200 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotScanObject userInfo:theUserInfo];
201 }
202 break;
203 }
204
205 if (outObject != NULL)
206 *outObject = theObject;
207
208 return(theResult);
209 }
210
211- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError
212 {
213 NSUInteger theScanLocation = [self scanLocation];
214
215 [self skipWhitespace];
216
217 if ([self scanCharacter:'{'] == NO)
218 {
219 if (outError)
220 {
221 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
222 @"Could not scan dictionary. Dictionary that does not start with '{' character.", NSLocalizedDescriptionKey,
223 NULL];
224 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
225 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryStartCharacterMissing userInfo:theUserInfo];
226 }
227 return(NO);
228 }
229
230 NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init];
231
232 while ([self currentCharacter] != '}')
233 {
234 [self skipWhitespace];
235
236 if ([self currentCharacter] == '}')
237 break;
238
239 NSString *theKey = NULL;
240 if ([self scanJSONStringConstant:&theKey error:outError] == NO)
241 {
242 [self setScanLocation:theScanLocation];
243 if (outError)
244 {
245 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
246 @"Could not scan dictionary. Failed to scan a key.", NSLocalizedDescriptionKey,
247 NULL];
248 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
249 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyScanFailed userInfo:theUserInfo];
250 }
251 [theDictionary release];
252 return(NO);
253 }
254
255 [self skipWhitespace];
256
257 if ([self scanCharacter:':'] == NO)
258 {
259 [self setScanLocation:theScanLocation];
260 if (outError)
261 {
262 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
263 @"Could not scan dictionary. Key was not terminated with a ':' character.", NSLocalizedDescriptionKey,
264 NULL];
265 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
266 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyNotTerminated userInfo:theUserInfo];
267 }
268 [theDictionary release];
269 return(NO);
270 }
271
272 id theValue = NULL;
273 if ([self scanJSONObject:&theValue error:outError] == NO)
274 {
275 [self setScanLocation:theScanLocation];
276 if (outError)
277 {
278 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
279 @"Could not scan dictionary. Failed to scan a value.", NSLocalizedDescriptionKey,
280 NULL];
281
282 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
283 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryValueScanFailed userInfo:theUserInfo];
284 }
285 [theDictionary release];
286 return(NO);
287 }
288
289 if (theValue == NULL && self.nullObject == NULL)
290 {
291 // If the value is a null and nullObject is also null then we're skipping this key/value pair.
292 }
293 else
294 {
295 [theDictionary setValue:theValue forKey:theKey];
296 }
297
298 [self skipWhitespace];
299 if ([self scanCharacter:','] == NO)
300 {
301 if ([self currentCharacter] != '}')
302 {
303 [self setScanLocation:theScanLocation];
304 if (outError)
305 {
306 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
307 @"Could not scan dictionary. Key value pairs not delimited with a ',' character.", NSLocalizedDescriptionKey,
308 NULL];
309 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
310 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter userInfo:theUserInfo];
311 }
312 [theDictionary release];
313 return(NO);
314 }
315 break;
316 }
317 else
318 {
319 [self skipWhitespace];
320 if ([self currentCharacter] == '}')
321 break;
322 }
323 }
324
325 if ([self scanCharacter:'}'] == NO)
326 {
327 [self setScanLocation:theScanLocation];
328 if (outError)
329 {
330 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
331 @"Could not scan dictionary. Dictionary not terminated by a '}' character.", NSLocalizedDescriptionKey,
332 NULL];
333 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
334 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryNotTerminated userInfo:theUserInfo];
335 }
336 [theDictionary release];
337 return(NO);
338 }
339
340 if (outDictionary != NULL)
341 {
342 if (self.options & kJSONScannerOptions_MutableContainers)
343 {
344 *outDictionary = [theDictionary autorelease];
345 }
346 else
347 {
348 *outDictionary = [[theDictionary copy] autorelease];
349 [theDictionary release];
350 }
351 }
352 else
353 {
354 [theDictionary release];
355 }
356
357 return(YES);
358 }
359
360- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError
361 {
362 NSUInteger theScanLocation = [self scanLocation];
363
364 [self skipWhitespace];
365
366 if ([self scanCharacter:'['] == NO)
367 {
368 if (outError)
369 {
370 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
371 @"Could not scan array. Array not started by a '[' character.", NSLocalizedDescriptionKey,
372 NULL];
373 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
374 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayStartCharacterMissing userInfo:theUserInfo];
375 }
376 return(NO);
377 }
378
379 NSMutableArray *theArray = [[NSMutableArray alloc] init];
380
381 [self skipWhitespace];
382 while ([self currentCharacter] != ']')
383 {
384 NSString *theValue = NULL;
385 if ([self scanJSONObject:&theValue error:outError] == NO)
386 {
387 [self setScanLocation:theScanLocation];
388 if (outError)
389 {
390 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
391 @"Could not scan array. Could not scan a value.", NSLocalizedDescriptionKey,
392 NULL];
393 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
394 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueScanFailed userInfo:theUserInfo];
395 }
396 [theArray release];
397 return(NO);
398 }
399
400 if (theValue == NULL)
401 {
402 if (self.nullObject != NULL)
403 {
404 if (outError)
405 {
406 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
407 @"Could not scan array. Value is NULL.", NSLocalizedDescriptionKey,
408 NULL];
409 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
410 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueIsNull userInfo:theUserInfo];
411 }
412 [theArray release];
413 return(NO);
414 }
415 }
416 else
417 {
418 [theArray addObject:theValue];
419 }
420
421 [self skipWhitespace];
422 if ([self scanCharacter:','] == NO)
423 {
424 [self skipWhitespace];
425 if ([self currentCharacter] != ']')
426 {
427 [self setScanLocation:theScanLocation];
428 if (outError)
429 {
430 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
431 @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey,
432 NULL];
433 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
434 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo];
435 }
436 [theArray release];
437 return(NO);
438 }
439
440 break;
441 }
442 [self skipWhitespace];
443 }
444
445 [self skipWhitespace];
446
447 if ([self scanCharacter:']'] == NO)
448 {
449 [self setScanLocation:theScanLocation];
450 if (outError)
451 {
452 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
453 @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey,
454 NULL];
455 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
456 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo];
457 }
458 [theArray release];
459 return(NO);
460 }
461
462 if (outArray != NULL)
463 {
464 if (self.options & kJSONScannerOptions_MutableContainers)
465 {
466 *outArray = [theArray autorelease];
467 }
468 else
469 {
470 *outArray = [[theArray copy] autorelease];
471 [theArray release];
472 }
473 }
474 else
475 {
476 [theArray release];
477 }
478 return(YES);
479 }
480
481- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError
482 {
483 NSUInteger theScanLocation = [self scanLocation];
484
485 [self skipWhitespace];
486
487 NSMutableString *theString = [[NSMutableString alloc] init];
488
489 if ([self scanCharacter:'"'] == NO)
490 {
491 [self setScanLocation:theScanLocation];
492 if (outError)
493 {
494 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
495 @"Could not scan string constant. String not started by a '\"' character.", NSLocalizedDescriptionKey,
496 NULL];
497 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
498 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotStartedWithBackslash userInfo:theUserInfo];
499 }
500 [theString release];
501 return(NO);
502 }
503
504 while ([self scanCharacter:'"'] == NO)
505 {
506 NSString *theStringChunk = NULL;
507 if ([self scanNotQuoteCharactersIntoString:&theStringChunk])
508 {
509 CFStringAppend((CFMutableStringRef)theString, (CFStringRef)theStringChunk);
510 }
511 else if ([self scanCharacter:'\\'] == YES)
512 {
513 unichar theCharacter = [self scanCharacter];
514 switch (theCharacter)
515 {
516 case '"':
517 case '\\':
518 case '/':
519 break;
520 case 'b':
521 theCharacter = '\b';
522 break;
523 case 'f':
524 theCharacter = '\f';
525 break;
526 case 'n':
527 theCharacter = '\n';
528 break;
529 case 'r':
530 theCharacter = '\r';
531 break;
532 case 't':
533 theCharacter = '\t';
534 break;
535 case 'u':
536 {
537 theCharacter = 0;
538
539 int theShift;
540 for (theShift = 12; theShift >= 0; theShift -= 4)
541 {
542 const int theDigit = HexToInt([self scanCharacter]);
543 if (theDigit == -1)
544 {
545 [self setScanLocation:theScanLocation];
546 if (outError)
547 {
548 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
549 @"Could not scan string constant. Unicode character could not be decoded.", NSLocalizedDescriptionKey,
550 NULL];
551 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
552 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnicodeNotDecoded userInfo:theUserInfo];
553 }
554 [theString release];
555 return(NO);
556 }
557 theCharacter |= (theDigit << theShift);
558 }
559 }
560 break;
561 default:
562 {
563 if (strictEscapeCodes == YES)
564 {
565 [self setScanLocation:theScanLocation];
566 if (outError)
567 {
568 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
569 @"Could not scan string constant. Unknown escape code.", NSLocalizedDescriptionKey,
570 NULL];
571 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
572 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnknownEscapeCode userInfo:theUserInfo];
573 }
574 [theString release];
575 return(NO);
576 }
577 }
578 break;
579 }
580 CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1);
581 }
582 else
583 {
584 if (outError)
585 {
586 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
587 @"Could not scan string constant. No terminating double quote character.", NSLocalizedDescriptionKey,
588 NULL];
589 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
590 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotTerminated userInfo:theUserInfo];
591 }
592 [theString release];
593 return(NO);
594 }
595 }
596
597 if (outStringConstant != NULL)
598 {
599 if (self.options & kJSONScannerOptions_MutableLeaves)
600 {
601 *outStringConstant = [theString autorelease];
602 }
603 else
604 {
605 *outStringConstant = [[theString copy] autorelease];
606 [theString release];
607 }
608 }
609 else
610 {
611 [theString release];
612 }
613
614 return(YES);
615 }
616
617- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError
618 {
619 NSNumber *theNumber = NULL;
620
621 [self skipWhitespace];
622
623 if ([self scanNumber:&theNumber] == YES)
624 {
625 if (outNumberConstant != NULL)
626 *outNumberConstant = theNumber;
627 return(YES);
628 }
629 else
630 {
631 if (outError)
632 {
633 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
634 @"Could not scan number constant.", NSLocalizedDescriptionKey,
635 NULL];
636 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
637 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_NumberNotScannable userInfo:theUserInfo];
638 }
639 return(NO);
640 }
641 }
642
643#if TREAT_COMMENTS_AS_WHITESPACE
644- (void)skipWhitespace
645 {
646 [super skipWhitespace];
647 [self scanCStyleComment:NULL];
648 [self scanCPlusPlusStyleComment:NULL];
649 [super skipWhitespace];
650 }
651#endif // TREAT_COMMENTS_AS_WHITESPACE
652
653#pragma mark -
654
655- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue
656 {
657 u_int8_t *P;
658 for (P = current; P < end && *P != '\"' && *P != '\\'; ++P)
659 ;
660
661 if (P == current)
662 {
663 return(NO);
664 }
665
666 if (outValue)
667 {
668 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
669 }
670
671 current = P;
672
673 return(YES);
674 }
675
676@end
diff --git a/libs/TouchJSON/JSON/CJSONSerializer.h b/libs/TouchJSON/JSON/CJSONSerializer.h new file mode 100755 index 0000000..748a85c --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONSerializer.h
@@ -0,0 +1,53 @@
1//
2// CJSONSerializer.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/07/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import <Foundation/Foundation.h>
31
32@interface CJSONSerializer : NSObject {
33}
34
35+ (id)serializer;
36
37- (BOOL)isValidJSONObject:(id)inObject;
38
39/// Take any JSON compatible object (generally NSNull, NSNumber, NSString, NSArray and NSDictionary) and produce an NSData containing the serialized JSON.
40- (NSData *)serializeObject:(id)inObject error:(NSError **)outError;
41
42- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError;
43- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError;
44- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError;
45- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError;
46- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError;
47
48@end
49
50typedef enum {
51 CJSONSerializerErrorCouldNotSerializeDataType = -1,
52 CJSONSerializerErrorCouldNotSerializeObject = -1
53} CJSONSerializerError;
diff --git a/libs/TouchJSON/JSON/CJSONSerializer.m b/libs/TouchJSON/JSON/CJSONSerializer.m new file mode 100755 index 0000000..952b3c2 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONSerializer.m
@@ -0,0 +1,342 @@
1//
2// CJSONSerializer.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/07/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CJSONSerializer.h"
31
32#import "JSONRepresentation.h"
33
34static NSData *kNULL = NULL;
35static NSData *kFalse = NULL;
36static NSData *kTrue = NULL;
37
38@implementation CJSONSerializer
39
40+ (void)initialize
41 {
42 NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
43
44 if (self == [CJSONSerializer class])
45 {
46 if (kNULL == NULL)
47 kNULL = [[NSData alloc] initWithBytesNoCopy:(void *)"null" length:4 freeWhenDone:NO];
48 if (kFalse == NULL)
49 kFalse = [[NSData alloc] initWithBytesNoCopy:(void *)"false" length:5 freeWhenDone:NO];
50 if (kTrue == NULL)
51 kTrue = [[NSData alloc] initWithBytesNoCopy:(void *)"true" length:4 freeWhenDone:NO];
52
53 [thePool release];
54 }
55 }
56
57+ (id)serializer
58 {
59 return([[[self alloc] init] autorelease]);
60 }
61
62- (BOOL)isValidJSONObject:(id)inObject
63 {
64 if ([inObject isKindOfClass:[NSNull class]])
65 {
66 return(YES);
67 }
68 else if ([inObject isKindOfClass:[NSNumber class]])
69 {
70 return(YES);
71 }
72 else if ([inObject isKindOfClass:[NSString class]])
73 {
74 return(YES);
75 }
76 else if ([inObject isKindOfClass:[NSArray class]])
77 {
78 return(YES);
79 }
80 else if ([inObject isKindOfClass:[NSDictionary class]])
81 {
82 return(YES);
83 }
84 else if ([inObject isKindOfClass:[NSData class]])
85 {
86 return(YES);
87 }
88 else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)])
89 {
90 return(YES);
91 }
92 else
93 {
94 return(NO);
95 }
96 }
97
98- (NSData *)serializeObject:(id)inObject error:(NSError **)outError
99 {
100 NSData *theResult = NULL;
101
102 if ([inObject isKindOfClass:[NSNull class]])
103 {
104 theResult = [self serializeNull:inObject error:outError];
105 }
106 else if ([inObject isKindOfClass:[NSNumber class]])
107 {
108 theResult = [self serializeNumber:inObject error:outError];
109 }
110 else if ([inObject isKindOfClass:[NSString class]])
111 {
112 theResult = [self serializeString:inObject error:outError];
113 }
114 else if ([inObject isKindOfClass:[NSArray class]])
115 {
116 theResult = [self serializeArray:inObject error:outError];
117 }
118 else if ([inObject isKindOfClass:[NSDictionary class]])
119 {
120 theResult = [self serializeDictionary:inObject error:outError];
121 }
122 else if ([inObject isKindOfClass:[NSData class]])
123 {
124 NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease];
125 theResult = [self serializeString:theString error:outError];
126 }
127 else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)])
128 {
129 theResult = [inObject JSONDataRepresentation];
130 }
131 else
132 {
133 if (outError)
134 {
135 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
136 [NSString stringWithFormat:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])], NSLocalizedDescriptionKey,
137 NULL];
138 *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeDataType userInfo:theUserInfo];
139 }
140 return(NULL);
141 }
142 if (theResult == NULL)
143 {
144 if (outError)
145 {
146 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
147 [NSString stringWithFormat:@"Could not serialize object '%@'", inObject], NSLocalizedDescriptionKey,
148 NULL];
149 *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeObject userInfo:theUserInfo];
150 }
151 return(NULL);
152 }
153 return(theResult);
154 }
155
156- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError
157 {
158 #pragma unused (inNull, outError)
159 return(kNULL);
160 }
161
162- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError
163 {
164 #pragma unused (outError)
165 NSData *theResult = NULL;
166 switch (CFNumberGetType((CFNumberRef)inNumber))
167 {
168 case kCFNumberCharType:
169 {
170 int theValue = [inNumber intValue];
171 if (theValue == 0)
172 theResult = kFalse;
173 else if (theValue == 1)
174 theResult = kTrue;
175 else
176 theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
177 }
178 break;
179 case kCFNumberFloat32Type:
180 case kCFNumberFloat64Type:
181 case kCFNumberFloatType:
182 case kCFNumberDoubleType:
183 case kCFNumberSInt8Type:
184 case kCFNumberSInt16Type:
185 case kCFNumberSInt32Type:
186 case kCFNumberSInt64Type:
187 case kCFNumberShortType:
188 case kCFNumberIntType:
189 case kCFNumberLongType:
190 case kCFNumberLongLongType:
191 case kCFNumberCFIndexType:
192 default:
193 theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
194 break;
195 }
196 return(theResult);
197 }
198
199- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError
200 {
201 #pragma unused (outError)
202
203 const char *theUTF8String = [inString UTF8String];
204
205 NSMutableData *theData = [NSMutableData dataWithLength:strlen(theUTF8String) * 2 + 2];
206
207 char *theOutputStart = [theData mutableBytes];
208 char *OUT = theOutputStart;
209
210 *OUT++ = '"';
211
212 for (const char *IN = theUTF8String; IN && *IN != '\0'; ++IN)
213 {
214 switch (*IN)
215 {
216 case '\\':
217 {
218 *OUT++ = '\\';
219 *OUT++ = '\\';
220 }
221 break;
222 case '\"':
223 {
224 *OUT++ = '\\';
225 *OUT++ = '\"';
226 }
227 break;
228 case '/':
229 {
230 *OUT++ = '\\';
231 *OUT++ = '/';
232 }
233 break;
234 case '\b':
235 {
236 *OUT++ = '\\';
237 *OUT++ = 'b';
238 }
239 break;
240 case '\f':
241 {
242 *OUT++ = '\\';
243 *OUT++ = 'f';
244 }
245 break;
246 case '\n':
247 {
248 *OUT++ = '\\';
249 *OUT++ = 'n';
250 }
251 break;
252 case '\r':
253 {
254 *OUT++ = '\\';
255 *OUT++ = 'r';
256 }
257 break;
258 case '\t':
259 {
260 *OUT++ = '\\';
261 *OUT++ = 't';
262 }
263 break;
264 default:
265 {
266 *OUT++ = *IN;
267 }
268 break;
269 }
270 }
271
272 *OUT++ = '"';
273
274 theData.length = OUT - theOutputStart;
275 return(theData);
276 }
277
278- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError
279 {
280 NSMutableData *theData = [NSMutableData data];
281
282 [theData appendBytes:"[" length:1];
283
284 NSEnumerator *theEnumerator = [inArray objectEnumerator];
285 id theValue = NULL;
286 NSUInteger i = 0;
287 while ((theValue = [theEnumerator nextObject]) != NULL)
288 {
289 NSData *theValueData = [self serializeObject:theValue error:outError];
290 if (theValueData == NULL)
291 {
292 return(NULL);
293 }
294 [theData appendData:theValueData];
295 if (++i < [inArray count])
296 [theData appendBytes:"," length:1];
297 }
298
299 [theData appendBytes:"]" length:1];
300
301 return(theData);
302 }
303
304- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError
305 {
306 NSMutableData *theData = [NSMutableData data];
307
308 [theData appendBytes:"{" length:1];
309
310 NSArray *theKeys = [inDictionary allKeys];
311 NSEnumerator *theEnumerator = [theKeys objectEnumerator];
312 NSString *theKey = NULL;
313 while ((theKey = [theEnumerator nextObject]) != NULL)
314 {
315 id theValue = [inDictionary objectForKey:theKey];
316
317 NSData *theKeyData = [self serializeString:theKey error:outError];
318 if (theKeyData == NULL)
319 {
320 return(NULL);
321 }
322 NSData *theValueData = [self serializeObject:theValue error:outError];
323 if (theValueData == NULL)
324 {
325 return(NULL);
326 }
327
328
329 [theData appendData:theKeyData];
330 [theData appendBytes:":" length:1];
331 [theData appendData:theValueData];
332
333 if (theKey != [theKeys lastObject])
334 [theData appendData:[@"," dataUsingEncoding:NSASCIIStringEncoding]];
335 }
336
337 [theData appendBytes:"}" length:1];
338
339 return(theData);
340 }
341
342@end
diff --git a/libs/TouchJSON/JSON/JSONRepresentation.h b/libs/TouchJSON/JSON/JSONRepresentation.h new file mode 100755 index 0000000..a83d76f --- /dev/null +++ b/libs/TouchJSON/JSON/JSONRepresentation.h
@@ -0,0 +1,18 @@
1//
2// JSONRepresentation.h
3// TouchJSON
4//
5// Created by Jonathan Wight on 10/15/10.
6// Copyright 2010 toxicsoftware.com. All rights reserved.
7//
8
9#import <Foundation/Foundation.h>
10
11@protocol JSONRepresentation
12
13@optional
14- (id)initWithJSONDataRepresentation:(NSData *)inJSONData;
15
16- (NSData *)JSONDataRepresentation;
17
18@end
diff --git a/libs/cocos2d/CCAction.h b/libs/cocos2d/CCAction.h new file mode 100755 index 0000000..51bad8e --- /dev/null +++ b/libs/cocos2d/CCAction.h
@@ -0,0 +1,195 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#include <sys/time.h>
29#import <Foundation/Foundation.h>
30
31#import "ccTypes.h"
32
33enum {
34 //! Default tag
35 kCCActionTagInvalid = -1,
36};
37
38/** Base class for CCAction objects.
39 */
40@interface CCAction : NSObject <NSCopying>
41{
42 id originalTarget_;
43 id target_;
44 NSInteger tag_;
45}
46
47/** The "target". The action will modify the target properties.
48 The target will be set with the 'startWithTarget' method.
49 When the 'stop' method is called, target will be set to nil.
50 The target is 'assigned', it is not 'retained'.
51 */
52@property (nonatomic,readonly,assign) id target;
53
54/** The original target, since target can be nil.
55 Is the target that were used to run the action. Unless you are doing something complex, like CCActionManager, you should NOT call this method.
56 @since v0.8.2
57*/
58@property (nonatomic,readonly,assign) id originalTarget;
59
60
61/** The action tag. An identifier of the action */
62@property (nonatomic,readwrite,assign) NSInteger tag;
63
64/** Allocates and initializes the action */
65+(id) action;
66
67/** Initializes the action */
68-(id) init;
69
70-(id) copyWithZone: (NSZone*) zone;
71
72//! return YES if the action has finished
73-(BOOL) isDone;
74//! called before the action start. It will also set the target.
75-(void) startWithTarget:(id)target;
76//! called after the action has finished. It will set the 'target' to nil.
77//! IMPORTANT: You should never call "[action stop]" manually. Instead, use: "[target stopAction:action];"
78-(void) stop;
79//! called every frame with it's delta time. DON'T override unless you know what you are doing.
80-(void) step: (ccTime) dt;
81//! called once per frame. time a value between 0 and 1
82//! For example:
83//! * 0 means that the action just started
84//! * 0.5 means that the action is in the middle
85//! * 1 means that the action is over
86-(void) update: (ccTime) time;
87
88@end
89
90/** Base class actions that do have a finite time duration.
91 Possible actions:
92 - An action with a duration of 0 seconds
93 - An action with a duration of 35.5 seconds
94 Infitite time actions are valid
95 */
96@interface CCFiniteTimeAction : CCAction <NSCopying>
97{
98 //! duration in seconds
99 ccTime duration_;
100}
101//! duration in seconds of the action
102@property (nonatomic,readwrite) ccTime duration;
103
104/** returns a reversed action */
105- (CCFiniteTimeAction*) reverse;
106@end
107
108
109@class CCActionInterval;
110/** Repeats an action for ever.
111 To repeat the an action for a limited number of times use the Repeat action.
112 @warning This action can't be Sequenceable because it is not an IntervalAction
113 */
114@interface CCRepeatForever : CCAction <NSCopying>
115{
116 CCActionInterval *innerAction_;
117}
118/** Inner action */
119@property (nonatomic, readwrite, retain) CCActionInterval *innerAction;
120
121/** creates the action */
122+(id) actionWithAction: (CCActionInterval*) action;
123/** initializes the action */
124-(id) initWithAction: (CCActionInterval*) action;
125@end
126
127/** Changes the speed of an action, making it take longer (speed>1)
128 or less (speed<1) time.
129 Useful to simulate 'slow motion' or 'fast forward' effect.
130 @warning This action can't be Sequenceable because it is not an CCIntervalAction
131 */
132@interface CCSpeed : CCAction <NSCopying>
133{
134 CCActionInterval *innerAction_;
135 float speed_;
136}
137/** alter the speed of the inner function in runtime */
138@property (nonatomic,readwrite) float speed;
139/** Inner action of CCSpeed */
140@property (nonatomic, readwrite, retain) CCActionInterval *innerAction;
141
142/** creates the action */
143+(id) actionWithAction: (CCActionInterval*) action speed:(float)rate;
144/** initializes the action */
145-(id) initWithAction: (CCActionInterval*) action speed:(float)rate;
146@end
147
148@class CCNode;
149/** CCFollow is an action that "follows" a node.
150
151 Eg:
152 [layer runAction: [CCFollow actionWithTarget:hero]];
153
154 Instead of using CCCamera as a "follower", use this action instead.
155 @since v0.99.2
156 */
157@interface CCFollow : CCAction <NSCopying>
158{
159 /* node to follow */
160 CCNode *followedNode_;
161
162 /* whether camera should be limited to certain area */
163 BOOL boundarySet;
164
165 /* if screensize is bigger than the boundary - update not needed */
166 BOOL boundaryFullyCovered;
167
168 /* fast access to the screen dimensions */
169 CGPoint halfScreenSize;
170 CGPoint fullScreenSize;
171
172 /* world boundaries */
173 float leftBoundary;
174 float rightBoundary;
175 float topBoundary;
176 float bottomBoundary;
177}
178
179/** alter behavior - turn on/off boundary */
180@property (nonatomic,readwrite) BOOL boundarySet;
181
182/** creates the action with no boundary set */
183+(id) actionWithTarget:(CCNode *)followedNode;
184
185/** creates the action with a set boundary */
186+(id) actionWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect;
187
188/** initializes the action */
189-(id) initWithTarget:(CCNode *)followedNode;
190
191/** initializes the action with a set boundary */
192-(id) initWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect;
193
194@end
195
diff --git a/libs/cocos2d/CCAction.m b/libs/cocos2d/CCAction.m new file mode 100755 index 0000000..27db20b --- /dev/null +++ b/libs/cocos2d/CCAction.m
@@ -0,0 +1,360 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import <Availability.h>
30#import "CCDirector.h"
31#import "ccMacros.h"
32#import "CCAction.h"
33#import "CCActionInterval.h"
34#import "Support/CGPointExtension.h"
35
36//
37// Action Base Class
38//
39#pragma mark -
40#pragma mark Action
41@implementation CCAction
42
43@synthesize tag = tag_, target = target_, originalTarget = originalTarget_;
44
45+(id) action
46{
47 return [[[self alloc] init] autorelease];
48}
49
50-(id) init
51{
52 if( (self=[super init]) ) {
53 originalTarget_ = target_ = nil;
54 tag_ = kCCActionTagInvalid;
55 }
56 return self;
57}
58
59-(void) dealloc
60{
61 CCLOGINFO(@"cocos2d: deallocing %@", self);
62 [super dealloc];
63}
64
65-(NSString*) description
66{
67 return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_];
68}
69
70-(id) copyWithZone: (NSZone*) zone
71{
72 CCAction *copy = [[[self class] allocWithZone: zone] init];
73 copy.tag = tag_;
74 return copy;
75}
76
77-(void) startWithTarget:(id)aTarget
78{
79 originalTarget_ = target_ = aTarget;
80}
81
82-(void) stop
83{
84 target_ = nil;
85}
86
87-(BOOL) isDone
88{
89 return YES;
90}
91
92-(void) step: (ccTime) dt
93{
94 NSLog(@"[Action step]. override me");
95}
96
97-(void) update: (ccTime) time
98{
99 NSLog(@"[Action update]. override me");
100}
101@end
102
103//
104// FiniteTimeAction
105//
106#pragma mark -
107#pragma mark FiniteTimeAction
108@implementation CCFiniteTimeAction
109@synthesize duration = duration_;
110
111- (CCFiniteTimeAction*) reverse
112{
113 CCLOG(@"cocos2d: FiniteTimeAction#reverse: Implement me");
114 return nil;
115}
116@end
117
118
119//
120// RepeatForever
121//
122#pragma mark -
123#pragma mark RepeatForever
124@implementation CCRepeatForever
125@synthesize innerAction=innerAction_;
126+(id) actionWithAction: (CCActionInterval*) action
127{
128 return [[[self alloc] initWithAction: action] autorelease];
129}
130
131-(id) initWithAction: (CCActionInterval*) action
132{
133 if( (self=[super init]) )
134 self.innerAction = action;
135
136 return self;
137}
138
139-(id) copyWithZone: (NSZone*) zone
140{
141 CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[innerAction_ copy] autorelease] ];
142 return copy;
143}
144
145-(void) dealloc
146{
147 [innerAction_ release];
148 [super dealloc];
149}
150
151-(void) startWithTarget:(id)aTarget
152{
153 [super startWithTarget:aTarget];
154 [innerAction_ startWithTarget:target_];
155}
156
157-(void) step:(ccTime) dt
158{
159 [innerAction_ step: dt];
160 if( [innerAction_ isDone] ) {
161 ccTime diff = dt + innerAction_.duration - innerAction_.elapsed;
162 [innerAction_ startWithTarget:target_];
163
164 // to prevent jerk. issue #390
165 [innerAction_ step: diff];
166 }
167}
168
169
170-(BOOL) isDone
171{
172 return NO;
173}
174
175- (CCActionInterval *) reverse
176{
177 return [CCRepeatForever actionWithAction:[innerAction_ reverse]];
178}
179@end
180
181//
182// Speed
183//
184#pragma mark -
185#pragma mark Speed
186@implementation CCSpeed
187@synthesize speed=speed_;
188@synthesize innerAction=innerAction_;
189
190+(id) actionWithAction: (CCActionInterval*) action speed:(float)r
191{
192 return [[[self alloc] initWithAction: action speed:r] autorelease];
193}
194
195-(id) initWithAction: (CCActionInterval*) action speed:(float)r
196{
197 if( (self=[super init]) ) {
198 self.innerAction = action;
199 speed_ = r;
200 }
201 return self;
202}
203
204-(id) copyWithZone: (NSZone*) zone
205{
206 CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[innerAction_ copy] autorelease] speed:speed_];
207 return copy;
208}
209
210-(void) dealloc
211{
212 [innerAction_ release];
213 [super dealloc];
214}
215
216-(void) startWithTarget:(id)aTarget
217{
218 [super startWithTarget:aTarget];
219 [innerAction_ startWithTarget:target_];
220}
221
222-(void) stop
223{
224 [innerAction_ stop];
225 [super stop];
226}
227
228-(void) step:(ccTime) dt
229{
230 [innerAction_ step: dt * speed_];
231}
232
233-(BOOL) isDone
234{
235 return [innerAction_ isDone];
236}
237
238- (CCActionInterval *) reverse
239{
240 return [CCSpeed actionWithAction:[innerAction_ reverse] speed:speed_];
241}
242@end
243
244//
245// Follow
246//
247#pragma mark -
248#pragma mark Follow
249@implementation CCFollow
250
251@synthesize boundarySet;
252
253+(id) actionWithTarget:(CCNode *) fNode
254{
255 return [[[self alloc] initWithTarget:fNode] autorelease];
256}
257
258+(id) actionWithTarget:(CCNode *) fNode worldBoundary:(CGRect)rect
259{
260 return [[[self alloc] initWithTarget:fNode worldBoundary:rect] autorelease];
261}
262
263-(id) initWithTarget:(CCNode *)fNode
264{
265 if( (self=[super init]) ) {
266
267 followedNode_ = [fNode retain];
268 boundarySet = FALSE;
269 boundaryFullyCovered = FALSE;
270
271 CGSize s = [[CCDirector sharedDirector] winSize];
272 fullScreenSize = CGPointMake(s.width, s.height);
273 halfScreenSize = ccpMult(fullScreenSize, .5f);
274 }
275
276 return self;
277}
278
279-(id) initWithTarget:(CCNode *)fNode worldBoundary:(CGRect)rect
280{
281 if( (self=[super init]) ) {
282
283 followedNode_ = [fNode retain];
284 boundarySet = TRUE;
285 boundaryFullyCovered = FALSE;
286
287 CGSize winSize = [[CCDirector sharedDirector] winSize];
288 fullScreenSize = CGPointMake(winSize.width, winSize.height);
289 halfScreenSize = ccpMult(fullScreenSize, .5f);
290
291 leftBoundary = -((rect.origin.x+rect.size.width) - fullScreenSize.x);
292 rightBoundary = -rect.origin.x ;
293 topBoundary = -rect.origin.y;
294 bottomBoundary = -((rect.origin.y+rect.size.height) - fullScreenSize.y);
295
296 if(rightBoundary < leftBoundary)
297 {
298 // screen width is larger than world's boundary width
299 //set both in the middle of the world
300 rightBoundary = leftBoundary = (leftBoundary + rightBoundary) / 2;
301 }
302 if(topBoundary < bottomBoundary)
303 {
304 // screen width is larger than world's boundary width
305 //set both in the middle of the world
306 topBoundary = bottomBoundary = (topBoundary + bottomBoundary) / 2;
307 }
308
309 if( (topBoundary == bottomBoundary) && (leftBoundary == rightBoundary) )
310 boundaryFullyCovered = TRUE;
311 }
312
313 return self;
314}
315
316-(id) copyWithZone: (NSZone*) zone
317{
318 CCAction *copy = [[[self class] allocWithZone: zone] init];
319 copy.tag = tag_;
320 return copy;
321}
322
323-(void) step:(ccTime) dt
324{
325 if(boundarySet)
326 {
327 // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
328 if(boundaryFullyCovered)
329 return;
330
331 CGPoint tempPos = ccpSub( halfScreenSize, followedNode_.position);
332 [target_ setPosition:ccp(clampf(tempPos.x,leftBoundary,rightBoundary), clampf(tempPos.y,bottomBoundary,topBoundary))];
333 }
334 else
335 [target_ setPosition:ccpSub( halfScreenSize, followedNode_.position )];
336
337#undef CLAMP
338}
339
340
341-(BOOL) isDone
342{
343 return !followedNode_.isRunning;
344}
345
346-(void) stop
347{
348 target_ = nil;
349 [super stop];
350}
351
352-(void) dealloc
353{
354 [followedNode_ release];
355 [super dealloc];
356}
357
358@end
359
360
diff --git a/libs/cocos2d/CCActionCamera.h b/libs/cocos2d/CCActionCamera.h new file mode 100755 index 0000000..1ea83a7 --- /dev/null +++ b/libs/cocos2d/CCActionCamera.h
@@ -0,0 +1,73 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCActionInterval.h"
28
29@class CCCamera;
30
31/** Base class for CCCamera actions
32 */
33@interface CCActionCamera : CCActionInterval <NSCopying>
34{
35 float centerXOrig_;
36 float centerYOrig_;
37 float centerZOrig_;
38
39 float eyeXOrig_;
40 float eyeYOrig_;
41 float eyeZOrig_;
42
43 float upXOrig_;
44 float upYOrig_;
45 float upZOrig_;
46}
47@end
48
49/** CCOrbitCamera action
50 Orbits the camera around the center of the screen using spherical coordinates
51 */
52@interface CCOrbitCamera : CCActionCamera <NSCopying>
53{
54 float radius_;
55 float deltaRadius_;
56 float angleZ_;
57 float deltaAngleZ_;
58 float angleX_;
59 float deltaAngleX_;
60
61 float radZ_;
62 float radDeltaZ_;
63 float radX_;
64 float radDeltaX_;
65
66}
67/** creates a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */
68+(id) actionWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx;
69/** initializes a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */
70-(id) initWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx;
71/** positions the camera according to spherical coordinates */
72-(void) sphericalRadius:(float*) r zenith:(float*) zenith azimuth:(float*) azimuth;
73@end
diff --git a/libs/cocos2d/CCActionCamera.m b/libs/cocos2d/CCActionCamera.m new file mode 100755 index 0000000..4dafc4e --- /dev/null +++ b/libs/cocos2d/CCActionCamera.m
@@ -0,0 +1,147 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import "CCActionCamera.h"
30#import "CCNode.h"
31#import "CCCamera.h"
32#import "ccMacros.h"
33
34//
35// CameraAction
36//
37@implementation CCActionCamera
38-(void) startWithTarget:(id)aTarget
39{
40 [super startWithTarget:aTarget];
41 CCCamera *camera = [target_ camera];
42 [camera centerX:&centerXOrig_ centerY:&centerYOrig_ centerZ:&centerZOrig_];
43 [camera eyeX:&eyeXOrig_ eyeY:&eyeYOrig_ eyeZ:&eyeZOrig_];
44 [camera upX:&upXOrig_ upY:&upYOrig_ upZ: &upZOrig_];
45}
46
47-(id) reverse
48{
49 return [CCReverseTime actionWithAction:self];
50}
51@end
52
53@implementation CCOrbitCamera
54+(id) actionWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx
55{
56 return [[[self alloc] initWithDuration:t radius:r deltaRadius:dr angleZ:z deltaAngleZ:dz angleX:x deltaAngleX:dx] autorelease];
57}
58
59-(id) copyWithZone: (NSZone*) zone
60{
61 return [[[self class] allocWithZone: zone] initWithDuration:duration_ radius:radius_ deltaRadius:deltaRadius_ angleZ:angleZ_ deltaAngleZ:deltaAngleZ_ angleX:angleX_ deltaAngleX:deltaAngleX_];
62}
63
64
65-(id) initWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx
66{
67 if((self=[super initWithDuration:t]) ) {
68
69 radius_ = r;
70 deltaRadius_ = dr;
71 angleZ_ = z;
72 deltaAngleZ_ = dz;
73 angleX_ = x;
74 deltaAngleX_ = dx;
75
76 radDeltaZ_ = (CGFloat)CC_DEGREES_TO_RADIANS(dz);
77 radDeltaX_ = (CGFloat)CC_DEGREES_TO_RADIANS(dx);
78 }
79
80 return self;
81}
82
83-(void) startWithTarget:(id)aTarget
84{
85 [super startWithTarget:aTarget];
86 float r, zenith, azimuth;
87
88 [self sphericalRadius: &r zenith:&zenith azimuth:&azimuth];
89
90#if 0 // isnan() is not supported on the simulator, and isnan() always returns false.
91 if( isnan(radius_) )
92 radius_ = r;
93
94 if( isnan( angleZ_) )
95 angleZ_ = (CGFloat)CC_RADIANS_TO_DEGREES(zenith);
96
97 if( isnan( angleX_ ) )
98 angleX_ = (CGFloat)CC_RADIANS_TO_DEGREES(azimuth);
99#endif
100
101 radZ_ = (CGFloat)CC_DEGREES_TO_RADIANS(angleZ_);
102 radX_ = (CGFloat)CC_DEGREES_TO_RADIANS(angleX_);
103}
104
105-(void) update: (ccTime) dt
106{
107 float r = (radius_ + deltaRadius_ * dt) *[CCCamera getZEye];
108 float za = radZ_ + radDeltaZ_ * dt;
109 float xa = radX_ + radDeltaX_ * dt;
110
111 float i = sinf(za) * cosf(xa) * r + centerXOrig_;
112 float j = sinf(za) * sinf(xa) * r + centerYOrig_;
113 float k = cosf(za) * r + centerZOrig_;
114
115 [[target_ camera] setEyeX:i eyeY:j eyeZ:k];
116}
117
118-(void) sphericalRadius:(float*) newRadius zenith:(float*) zenith azimuth:(float*) azimuth
119{
120 float ex, ey, ez, cx, cy, cz, x, y, z;
121 float r; // radius
122 float s;
123
124 CCCamera *camera = [target_ camera];
125 [camera eyeX:&ex eyeY:&ey eyeZ:&ez];
126 [camera centerX:&cx centerY:&cy centerZ:&cz];
127
128 x = ex-cx;
129 y = ey-cy;
130 z = ez-cz;
131
132 r = sqrtf( x*x + y*y + z*z);
133 s = sqrtf( x*x + y*y);
134 if(s==0.0f)
135 s = FLT_EPSILON;
136 if(r==0.0f)
137 r = FLT_EPSILON;
138
139 *zenith = acosf( z/r);
140 if( x < 0 )
141 *azimuth = (float)M_PI - asinf(y/s);
142 else
143 *azimuth = asinf(y/s);
144
145 *newRadius = r / [CCCamera getZEye];
146}
147@end
diff --git a/libs/cocos2d/CCActionEase.h b/libs/cocos2d/CCActionEase.h new file mode 100755 index 0000000..fced701 --- /dev/null +++ b/libs/cocos2d/CCActionEase.h
@@ -0,0 +1,159 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionInterval.h"
28
29/** Base class for Easing actions
30 */
31@interface CCActionEase : CCActionInterval <NSCopying>
32{
33 CCActionInterval * other;
34}
35/** creates the action */
36+(id) actionWithAction: (CCActionInterval*) action;
37/** initializes the action */
38-(id) initWithAction: (CCActionInterval*) action;
39@end
40
41/** Base class for Easing actions with rate parameters
42 */
43@interface CCEaseRateAction : CCActionEase <NSCopying>
44{
45 float rate;
46}
47/** rate value for the actions */
48@property (nonatomic,readwrite,assign) float rate;
49/** Creates the action with the inner action and the rate parameter */
50+(id) actionWithAction: (CCActionInterval*) action rate:(float)rate;
51/** Initializes the action with the inner action and the rate parameter */
52-(id) initWithAction: (CCActionInterval*) action rate:(float)rate;
53@end
54
55/** CCEaseIn action with a rate
56 */
57@interface CCEaseIn : CCEaseRateAction <NSCopying> {} @end
58
59/** CCEaseOut action with a rate
60 */
61@interface CCEaseOut : CCEaseRateAction <NSCopying> {} @end
62
63/** CCEaseInOut action with a rate
64 */
65@interface CCEaseInOut : CCEaseRateAction <NSCopying> {} @end
66
67/** CCEase Exponential In
68 */
69@interface CCEaseExponentialIn : CCActionEase <NSCopying> {} @end
70/** Ease Exponential Out
71 */
72@interface CCEaseExponentialOut : CCActionEase <NSCopying> {} @end
73/** Ease Exponential InOut
74 */
75@interface CCEaseExponentialInOut : CCActionEase <NSCopying> {} @end
76/** Ease Sine In
77 */
78@interface CCEaseSineIn : CCActionEase <NSCopying> {} @end
79/** Ease Sine Out
80 */
81@interface CCEaseSineOut : CCActionEase <NSCopying> {} @end
82/** Ease Sine InOut
83 */
84@interface CCEaseSineInOut : CCActionEase <NSCopying> {} @end
85
86/** Ease Elastic abstract class
87 @since v0.8.2
88 */
89@interface CCEaseElastic : CCActionEase <NSCopying>
90{
91 float period_;
92}
93
94/** period of the wave in radians. default is 0.3 */
95@property (nonatomic,readwrite) float period;
96
97/** Creates the action with the inner action and the period in radians (default is 0.3) */
98+(id) actionWithAction: (CCActionInterval*) action period:(float)period;
99/** Initializes the action with the inner action and the period in radians (default is 0.3) */
100-(id) initWithAction: (CCActionInterval*) action period:(float)period;
101@end
102
103/** Ease Elastic In action.
104 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
105 @since v0.8.2
106 */
107@interface CCEaseElasticIn : CCEaseElastic <NSCopying> {} @end
108/** Ease Elastic Out action.
109 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
110 @since v0.8.2
111 */
112@interface CCEaseElasticOut : CCEaseElastic <NSCopying> {} @end
113/** Ease Elastic InOut action.
114 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
115 @since v0.8.2
116 */
117@interface CCEaseElasticInOut : CCEaseElastic <NSCopying> {} @end
118
119/** CCEaseBounce abstract class.
120 @since v0.8.2
121*/
122@interface CCEaseBounce : CCActionEase <NSCopying> {} @end
123
124/** CCEaseBounceIn action.
125 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
126 @since v0.8.2
127*/
128@interface CCEaseBounceIn : CCEaseBounce <NSCopying> {} @end
129
130/** EaseBounceOut action.
131 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
132 @since v0.8.2
133 */
134@interface CCEaseBounceOut : CCEaseBounce <NSCopying> {} @end
135
136/** CCEaseBounceInOut action.
137 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
138 @since v0.8.2
139 */
140@interface CCEaseBounceInOut : CCEaseBounce <NSCopying> {} @end
141
142/** CCEaseBackIn action.
143 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
144 @since v0.8.2
145 */
146@interface CCEaseBackIn : CCActionEase <NSCopying> {} @end
147
148/** CCEaseBackOut action.
149 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
150 @since v0.8.2
151 */
152@interface CCEaseBackOut : CCActionEase <NSCopying> {} @end
153
154/** CCEaseBackInOut action.
155 @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action.
156 @since v0.8.2
157 */
158@interface CCEaseBackInOut : CCActionEase <NSCopying> {} @end
159
diff --git a/libs/cocos2d/CCActionEase.m b/libs/cocos2d/CCActionEase.m new file mode 100755 index 0000000..f28be11 --- /dev/null +++ b/libs/cocos2d/CCActionEase.m
@@ -0,0 +1,534 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27/*
28 * Elastic, Back and Bounce actions based on code from:
29 * http://github.com/NikhilK/silverlightfx/
30 *
31 * by http://github.com/NikhilK
32 */
33
34#import "CCActionEase.h"
35
36#ifndef M_PI_X_2
37#define M_PI_X_2 (float)M_PI * 2.0f
38#endif
39
40#pragma mark EaseAction
41
42//
43// EaseAction
44//
45@implementation CCActionEase
46
47+(id) actionWithAction: (CCActionInterval*) action
48{
49 return [[[self alloc] initWithAction: action] autorelease ];
50}
51
52-(id) initWithAction: (CCActionInterval*) action
53{
54 NSAssert( action!=nil, @"Ease: arguments must be non-nil");
55
56 if( (self=[super initWithDuration: action.duration]) )
57 other = [action retain];
58
59 return self;
60}
61
62-(id) copyWithZone: (NSZone*) zone
63{
64 CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease]];
65 return copy;
66}
67
68-(void) dealloc
69{
70 [other release];
71 [super dealloc];
72}
73
74-(void) startWithTarget:(id)aTarget
75{
76 [super startWithTarget:aTarget];
77 [other startWithTarget:target_];
78}
79
80-(void) stop
81{
82 [other stop];
83 [super stop];
84}
85
86-(void) update: (ccTime) t
87{
88 [other update: t];
89}
90
91-(CCActionInterval*) reverse
92{
93 return [[self class] actionWithAction: [other reverse]];
94}
95@end
96
97
98#pragma mark -
99#pragma mark EaseRate
100
101//
102// EaseRateAction
103//
104@implementation CCEaseRateAction
105@synthesize rate;
106+(id) actionWithAction: (CCActionInterval*) action rate:(float)aRate
107{
108 return [[[self alloc] initWithAction: action rate:aRate] autorelease ];
109}
110
111-(id) initWithAction: (CCActionInterval*) action rate:(float)aRate
112{
113 if( (self=[super initWithAction:action ]) )
114 self.rate = aRate;
115
116 return self;
117}
118
119-(id) copyWithZone: (NSZone*) zone
120{
121 CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] rate:rate];
122 return copy;
123}
124
125-(void) dealloc
126{
127 [super dealloc];
128}
129
130-(CCActionInterval*) reverse
131{
132 return [[self class] actionWithAction: [other reverse] rate:1/rate];
133}
134@end
135
136//
137// EeseIn
138//
139@implementation CCEaseIn
140-(void) update: (ccTime) t
141{
142 [other update: powf(t,rate)];
143}
144@end
145
146//
147// EaseOut
148//
149@implementation CCEaseOut
150-(void) update: (ccTime) t
151{
152 [other update: powf(t,1/rate)];
153}
154@end
155
156//
157// EaseInOut
158//
159@implementation CCEaseInOut
160-(void) update: (ccTime) t
161{
162 int sign =1;
163 int r = (int) rate;
164 if (r % 2 == 0)
165 sign = -1;
166 t *= 2;
167 if (t < 1)
168 [other update: 0.5f * powf (t, rate)];
169 else
170 [other update: sign*0.5f * (powf (t-2, rate) + sign*2)];
171}
172
173// InOut and OutIn are symmetrical
174-(CCActionInterval*) reverse
175{
176 return [[self class] actionWithAction: [other reverse] rate:rate];
177}
178
179@end
180
181#pragma mark -
182#pragma mark EaseExponential
183
184//
185// EaseExponentialIn
186//
187@implementation CCEaseExponentialIn
188-(void) update: (ccTime) t
189{
190 [other update: (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) - 1 * 0.001f];
191}
192
193- (CCActionInterval*) reverse
194{
195 return [CCEaseExponentialOut actionWithAction: [other reverse]];
196}
197@end
198
199//
200// EaseExponentialOut
201//
202@implementation CCEaseExponentialOut
203-(void) update: (ccTime) t
204{
205 [other update: (t==1) ? 1 : (-powf(2, -10 * t/1) + 1)];
206}
207
208- (CCActionInterval*) reverse
209{
210 return [CCEaseExponentialIn actionWithAction: [other reverse]];
211}
212@end
213
214//
215// EaseExponentialInOut
216//
217@implementation CCEaseExponentialInOut
218-(void) update: (ccTime) t
219{
220 t /= 0.5f;
221 if (t < 1)
222 t = 0.5f * powf(2, 10 * (t - 1));
223 else
224 t = 0.5f * (-powf(2, -10 * (t -1) ) + 2);
225
226 [other update:t];
227}
228@end
229
230
231#pragma mark -
232#pragma mark EaseSin actions
233
234//
235// EaseSineIn
236//
237@implementation CCEaseSineIn
238-(void) update: (ccTime) t
239{
240 [other update:-1*cosf(t * (float)M_PI_2) +1];
241}
242
243- (CCActionInterval*) reverse
244{
245 return [CCEaseSineOut actionWithAction: [other reverse]];
246}
247@end
248
249//
250// EaseSineOut
251//
252@implementation CCEaseSineOut
253-(void) update: (ccTime) t
254{
255 [other update:sinf(t * (float)M_PI_2)];
256}
257
258- (CCActionInterval*) reverse
259{
260 return [CCEaseSineIn actionWithAction: [other reverse]];
261}
262@end
263
264//
265// EaseSineInOut
266//
267@implementation CCEaseSineInOut
268-(void) update: (ccTime) t
269{
270 [other update:-0.5f*(cosf( (float)M_PI*t) - 1)];
271}
272@end
273
274#pragma mark -
275#pragma mark EaseElastic actions
276
277//
278// EaseElastic
279//
280@implementation CCEaseElastic
281
282@synthesize period = period_;
283
284+(id) actionWithAction: (CCActionInterval*) action
285{
286 return [[[self alloc] initWithAction:action period:0.3f] autorelease];
287}
288
289+(id) actionWithAction: (CCActionInterval*) action period:(float)period
290{
291 return [[[self alloc] initWithAction:action period:period] autorelease];
292}
293
294-(id) initWithAction: (CCActionInterval*) action
295{
296 return [self initWithAction:action period:0.3f];
297}
298
299-(id) initWithAction: (CCActionInterval*) action period:(float)period
300{
301 if( (self=[super initWithAction:action]) )
302 period_ = period;
303
304 return self;
305}
306
307-(id) copyWithZone: (NSZone*) zone
308{
309 CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] period:period_];
310 return copy;
311}
312
313-(CCActionInterval*) reverse
314{
315 NSAssert(NO,@"Override me");
316 return nil;
317}
318
319@end
320
321//
322// EaseElasticIn
323//
324
325@implementation CCEaseElasticIn
326-(void) update: (ccTime) t
327{
328 ccTime newT = 0;
329 if (t == 0 || t == 1)
330 newT = t;
331
332 else {
333 float s = period_ / 4;
334 t = t - 1;
335 newT = -powf(2, 10 * t) * sinf( (t-s) *M_PI_X_2 / period_);
336 }
337 [other update:newT];
338}
339
340- (CCActionInterval*) reverse
341{
342 return [CCEaseElasticOut actionWithAction: [other reverse] period:period_];
343}
344
345@end
346
347//
348// EaseElasticOut
349//
350@implementation CCEaseElasticOut
351
352-(void) update: (ccTime) t
353{
354 ccTime newT = 0;
355 if (t == 0 || t == 1) {
356 newT = t;
357
358 } else {
359 float s = period_ / 4;
360 newT = powf(2, -10 * t) * sinf( (t-s) *M_PI_X_2 / period_) + 1;
361 }
362 [other update:newT];
363}
364
365- (CCActionInterval*) reverse
366{
367 return [CCEaseElasticIn actionWithAction: [other reverse] period:period_];
368}
369
370@end
371
372//
373// EaseElasticInOut
374//
375@implementation CCEaseElasticInOut
376-(void) update: (ccTime) t
377{
378 ccTime newT = 0;
379
380 if( t == 0 || t == 1 )
381 newT = t;
382 else {
383 t = t * 2;
384 if(! period_ )
385 period_ = 0.3f * 1.5f;
386 ccTime s = period_ / 4;
387
388 t = t -1;
389 if( t < 0 )
390 newT = -0.5f * powf(2, 10 * t) * sinf((t - s) * M_PI_X_2 / period_);
391 else
392 newT = powf(2, -10 * t) * sinf((t - s) * M_PI_X_2 / period_) * 0.5f + 1;
393 }
394 [other update:newT];
395}
396
397- (CCActionInterval*) reverse
398{
399 return [CCEaseElasticInOut actionWithAction: [other reverse] period:period_];
400}
401
402@end
403
404#pragma mark -
405#pragma mark EaseBounce actions
406
407//
408// EaseBounce
409//
410@implementation CCEaseBounce
411-(ccTime) bounceTime:(ccTime) t
412{
413 if (t < 1 / 2.75) {
414 return 7.5625f * t * t;
415 }
416 else if (t < 2 / 2.75) {
417 t -= 1.5f / 2.75f;
418 return 7.5625f * t * t + 0.75f;
419 }
420 else if (t < 2.5 / 2.75) {
421 t -= 2.25f / 2.75f;
422 return 7.5625f * t * t + 0.9375f;
423 }
424
425 t -= 2.625f / 2.75f;
426 return 7.5625f * t * t + 0.984375f;
427}
428@end
429
430//
431// EaseBounceIn
432//
433
434@implementation CCEaseBounceIn
435
436-(void) update: (ccTime) t
437{
438 ccTime newT = 1 - [self bounceTime:1-t];
439 [other update:newT];
440}
441
442- (CCActionInterval*) reverse
443{
444 return [CCEaseBounceOut actionWithAction: [other reverse]];
445}
446
447@end
448
449@implementation CCEaseBounceOut
450
451-(void) update: (ccTime) t
452{
453 ccTime newT = [self bounceTime:t];
454 [other update:newT];
455}
456
457- (CCActionInterval*) reverse
458{
459 return [CCEaseBounceIn actionWithAction: [other reverse]];
460}
461
462@end
463
464@implementation CCEaseBounceInOut
465
466-(void) update: (ccTime) t
467{
468 ccTime newT = 0;
469 if (t < 0.5) {
470 t = t * 2;
471 newT = (1 - [self bounceTime:1-t] ) * 0.5f;
472 } else
473 newT = [self bounceTime:t * 2 - 1] * 0.5f + 0.5f;
474
475 [other update:newT];
476}
477@end
478
479#pragma mark -
480#pragma mark Ease Back actions
481
482//
483// EaseBackIn
484//
485@implementation CCEaseBackIn
486
487-(void) update: (ccTime) t
488{
489 ccTime overshoot = 1.70158f;
490 [other update: t * t * ((overshoot + 1) * t - overshoot)];
491}
492
493- (CCActionInterval*) reverse
494{
495 return [CCEaseBackOut actionWithAction: [other reverse]];
496}
497@end
498
499//
500// EaseBackOut
501//
502@implementation CCEaseBackOut
503-(void) update: (ccTime) t
504{
505 ccTime overshoot = 1.70158f;
506
507 t = t - 1;
508 [other update: t * t * ((overshoot + 1) * t + overshoot) + 1];
509}
510
511- (CCActionInterval*) reverse
512{
513 return [CCEaseBackIn actionWithAction: [other reverse]];
514}
515@end
516
517//
518// EaseBackInOut
519//
520@implementation CCEaseBackInOut
521
522-(void) update: (ccTime) t
523{
524 ccTime overshoot = 1.70158f * 1.525f;
525
526 t = t * 2;
527 if (t < 1)
528 [other update: (t * t * ((overshoot + 1) * t - overshoot)) / 2];
529 else {
530 t = t - 2;
531 [other update: (t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1];
532 }
533}
534@end
diff --git a/libs/cocos2d/CCActionGrid.h b/libs/cocos2d/CCActionGrid.h new file mode 100755 index 0000000..6b31179 --- /dev/null +++ b/libs/cocos2d/CCActionGrid.h
@@ -0,0 +1,165 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionInterval.h"
28#import "CCActionInstant.h"
29#import "CCGrid.h"
30
31@class CCGridBase;
32
33/** Base class for Grid actions */
34@interface CCGridAction : CCActionInterval
35{
36 ccGridSize gridSize_;
37}
38
39/** size of the grid */
40@property (nonatomic,readwrite) ccGridSize gridSize;
41
42/** creates the action with size and duration */
43+(id) actionWithSize:(ccGridSize)size duration:(ccTime)d;
44/** initializes the action with size and duration */
45-(id) initWithSize:(ccGridSize)gridSize duration:(ccTime)d;
46/** returns the grid */
47-(CCGridBase *)grid;
48
49@end
50
51////////////////////////////////////////////////////////////
52
53/** Base class for CCGrid3D actions.
54 Grid3D actions can modify a non-tiled grid.
55 */
56@interface CCGrid3DAction : CCGridAction
57{
58}
59
60/** returns the vertex than belongs to certain position in the grid */
61-(ccVertex3F)vertex:(ccGridSize)pos;
62/** returns the non-transformed vertex than belongs to certain position in the grid */
63-(ccVertex3F)originalVertex:(ccGridSize)pos;
64/** sets a new vertex to a certain position of the grid */
65-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex;
66
67@end
68
69////////////////////////////////////////////////////////////
70
71/** Base class for CCTiledGrid3D actions */
72@interface CCTiledGrid3DAction : CCGridAction
73{
74}
75
76/** returns the tile that belongs to a certain position of the grid */
77-(ccQuad3)tile:(ccGridSize)pos;
78/** returns the non-transformed tile that belongs to a certain position of the grid */
79-(ccQuad3)originalTile:(ccGridSize)pos;
80/** sets a new tile to a certain position of the grid */
81-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords;
82
83@end
84
85////////////////////////////////////////////////////////////
86
87/** CCAccelDeccelAmplitude action */
88@interface CCAccelDeccelAmplitude : CCActionInterval
89{
90 float rate_;
91 CCActionInterval *other_;
92}
93
94/** amplitude rate */
95@property (nonatomic,readwrite) float rate;
96
97/** creates the action with an inner action that has the amplitude property, and a duration time */
98+(id)actionWithAction:(CCAction*)action duration:(ccTime)d;
99/** initializes the action with an inner action that has the amplitude property, and a duration time */
100-(id)initWithAction:(CCAction*)action duration:(ccTime)d;
101
102@end
103
104////////////////////////////////////////////////////////////
105
106/** CCAccelAmplitude action */
107@interface CCAccelAmplitude : CCActionInterval
108{
109 float rate_;
110 CCActionInterval *other_;
111}
112
113/** amplitude rate */
114@property (nonatomic,readwrite) float rate;
115
116/** creates the action with an inner action that has the amplitude property, and a duration time */
117+(id)actionWithAction:(CCAction*)action duration:(ccTime)d;
118/** initializes the action with an inner action that has the amplitude property, and a duration time */
119-(id)initWithAction:(CCAction*)action duration:(ccTime)d;
120
121@end
122
123////////////////////////////////////////////////////////////
124
125/** CCDeccelAmplitude action */
126@interface CCDeccelAmplitude : CCActionInterval
127{
128 float rate_;
129 CCActionInterval *other_;
130}
131
132/** amplitude rate */
133@property (nonatomic,readwrite) float rate;
134
135/** creates the action with an inner action that has the amplitude property, and a duration time */
136+(id)actionWithAction:(CCAction*)action duration:(ccTime)d;
137/** initializes the action with an inner action that has the amplitude property, and a duration time */
138-(id)initWithAction:(CCAction*)action duration:(ccTime)d;
139
140@end
141
142////////////////////////////////////////////////////////////
143
144/** CCStopGrid action.
145 Don't call this action if another grid action is active.
146 Call if you want to remove the the grid effect. Example:
147 [Sequence actions:[Lens ...], [StopGrid action], nil];
148 */
149@interface CCStopGrid : CCActionInstant
150{
151}
152@end
153
154////////////////////////////////////////////////////////////
155
156/** CCReuseGrid action */
157@interface CCReuseGrid : CCActionInstant
158{
159 int t_;
160}
161/** creates an action with the number of times that the current grid will be reused */
162+(id) actionWithTimes: (int) times;
163/** initializes an action with the number of times that the current grid will be reused */
164-(id) initWithTimes: (int) times;
165@end
diff --git a/libs/cocos2d/CCActionGrid.m b/libs/cocos2d/CCActionGrid.m new file mode 100755 index 0000000..638e27d --- /dev/null +++ b/libs/cocos2d/CCActionGrid.m
@@ -0,0 +1,386 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionGrid.h"
28#import "CCDirector.h"
29
30#pragma mark -
31#pragma mark GridAction
32
33@implementation CCGridAction
34
35@synthesize gridSize = gridSize_;
36
37+(id) actionWithSize:(ccGridSize)size duration:(ccTime)d
38{
39 return [[[self alloc] initWithSize:size duration:d ] autorelease];
40}
41
42-(id) initWithSize:(ccGridSize)gSize duration:(ccTime)d
43{
44 if ( (self = [super initWithDuration:d]) )
45 {
46 gridSize_ = gSize;
47 }
48
49 return self;
50}
51
52-(void)startWithTarget:(id)aTarget
53{
54 [super startWithTarget:aTarget];
55
56 CCGridBase *newgrid = [self grid];
57
58 CCNode *t = (CCNode*) target_;
59 CCGridBase *targetGrid = [t grid];
60
61 if ( targetGrid && targetGrid.reuseGrid > 0 )
62 {
63 if ( targetGrid.active && targetGrid.gridSize.x == gridSize_.x && targetGrid.gridSize.y == gridSize_.y && [targetGrid isKindOfClass:[newgrid class]] )
64 [targetGrid reuse];
65 else
66 [NSException raise:@"GridBase" format:@"Cannot reuse grid"];
67 }
68 else
69 {
70 if ( targetGrid && targetGrid.active )
71 targetGrid.active = NO;
72
73 t.grid = newgrid;
74 t.grid.active = YES;
75 }
76}
77
78-(CCGridBase *)grid
79{
80 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
81 return nil;
82}
83
84- (CCActionInterval*) reverse
85{
86 return [CCReverseTime actionWithAction:self];
87}
88
89-(id) copyWithZone: (NSZone*) zone
90{
91 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSize:gridSize_ duration:duration_];
92 return copy;
93}
94@end
95
96////////////////////////////////////////////////////////////
97
98#pragma mark -
99#pragma mark Grid3DAction
100
101@implementation CCGrid3DAction
102
103-(CCGridBase *)grid
104{
105 return [CCGrid3D gridWithSize:gridSize_];
106}
107
108-(ccVertex3F)vertex:(ccGridSize)pos
109{
110 CCGrid3D *g = (CCGrid3D *)[target_ grid];
111 return [g vertex:pos];
112}
113
114-(ccVertex3F)originalVertex:(ccGridSize)pos
115{
116 CCGrid3D *g = (CCGrid3D *)[target_ grid];
117 return [g originalVertex:pos];
118}
119
120-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex
121{
122 CCGrid3D *g = (CCGrid3D *)[target_ grid];
123 [g setVertex:pos vertex:vertex];
124}
125@end
126
127////////////////////////////////////////////////////////////
128
129#pragma mark -
130#pragma mark TiledGrid3DAction
131
132@implementation CCTiledGrid3DAction
133
134-(CCGridBase *)grid
135{
136 return [CCTiledGrid3D gridWithSize:gridSize_];
137}
138
139-(ccQuad3)tile:(ccGridSize)pos
140{
141 CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid];
142 return [g tile:pos];
143}
144
145-(ccQuad3)originalTile:(ccGridSize)pos
146{
147 CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid];
148 return [g originalTile:pos];
149}
150
151-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords
152{
153 CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid];
154 [g setTile:pos coords:coords];
155}
156
157@end
158
159////////////////////////////////////////////////////////////
160
161@interface CCActionInterval (Amplitude)
162-(void)setAmplitudeRate:(CGFloat)amp;
163-(CGFloat)getAmplitudeRate;
164@end
165
166@implementation CCActionInterval (Amplitude)
167-(void)setAmplitudeRate:(CGFloat)amp
168{
169 [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"];
170}
171
172-(CGFloat)getAmplitudeRate
173{
174 [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"];
175 return 0;
176}
177@end
178
179////////////////////////////////////////////////////////////
180
181#pragma mark -
182#pragma mark AccelDeccelAmplitude
183
184@implementation CCAccelDeccelAmplitude
185
186@synthesize rate=rate_;
187
188+(id)actionWithAction:(CCAction*)action duration:(ccTime)d
189{
190 return [[[self alloc] initWithAction:action duration:d ] autorelease];
191}
192
193-(id)initWithAction:(CCAction *)action duration:(ccTime)d
194{
195 if ( (self = [super initWithDuration:d]) )
196 {
197 rate_ = 1.0f;
198 other_ = (CCActionInterval*)[action retain];
199 }
200
201 return self;
202}
203
204-(void)dealloc
205{
206 [other_ release];
207 [super dealloc];
208}
209
210-(void)startWithTarget:(id)aTarget
211{
212 [super startWithTarget:aTarget];
213 [other_ startWithTarget:target_];
214}
215
216-(void) update: (ccTime) time
217{
218 float f = time*2;
219
220 if (f > 1)
221 {
222 f -= 1;
223 f = 1 - f;
224 }
225
226 [other_ setAmplitudeRate:powf(f, rate_)];
227 [other_ update:time];
228}
229
230- (CCActionInterval*) reverse
231{
232 return [CCAccelDeccelAmplitude actionWithAction:[other_ reverse] duration:duration_];
233}
234
235@end
236
237////////////////////////////////////////////////////////////
238
239#pragma mark -
240#pragma mark AccelAmplitude
241
242@implementation CCAccelAmplitude
243
244@synthesize rate=rate_;
245
246+(id)actionWithAction:(CCAction*)action duration:(ccTime)d
247{
248 return [[[self alloc] initWithAction:action duration:d ] autorelease];
249}
250
251-(id)initWithAction:(CCAction *)action duration:(ccTime)d
252{
253 if ( (self = [super initWithDuration:d]) )
254 {
255 rate_ = 1.0f;
256 other_ = (CCActionInterval*)[action retain];
257 }
258
259 return self;
260}
261
262-(void)dealloc
263{
264 [other_ release];
265 [super dealloc];
266}
267
268-(void)startWithTarget:(id)aTarget
269{
270 [super startWithTarget:aTarget];
271 [other_ startWithTarget:target_];
272}
273
274-(void) update: (ccTime) time
275{
276 [other_ setAmplitudeRate:powf(time, rate_)];
277 [other_ update:time];
278}
279
280- (CCActionInterval*) reverse
281{
282 return [CCAccelAmplitude actionWithAction:[other_ reverse] duration:self.duration];
283}
284
285@end
286
287////////////////////////////////////////////////////////////
288
289#pragma mark -
290#pragma mark DeccelAmplitude
291
292@implementation CCDeccelAmplitude
293
294@synthesize rate=rate_;
295
296+(id)actionWithAction:(CCAction*)action duration:(ccTime)d
297{
298 return [[[self alloc] initWithAction:action duration:d ] autorelease];
299}
300
301-(id)initWithAction:(CCAction *)action duration:(ccTime)d
302{
303 if ( (self = [super initWithDuration:d]) )
304 {
305 rate_ = 1.0f;
306 other_ = (CCActionInterval*)[action retain];
307 }
308
309 return self;
310}
311
312-(void)dealloc
313{
314 [other_ release];
315 [super dealloc];
316}
317
318-(void)startWithTarget:(id)aTarget
319{
320 [super startWithTarget:aTarget];
321 [other_ startWithTarget:target_];
322}
323
324-(void) update: (ccTime) time
325{
326 [other_ setAmplitudeRate:powf((1-time), rate_)];
327 [other_ update:time];
328}
329
330- (CCActionInterval*) reverse
331{
332 return [CCDeccelAmplitude actionWithAction:[other_ reverse] duration:self.duration];
333}
334
335@end
336
337////////////////////////////////////////////////////////////
338
339#pragma mark -
340#pragma mark StopGrid
341
342@implementation CCStopGrid
343
344-(void)startWithTarget:(id)aTarget
345{
346 [super startWithTarget:aTarget];
347
348 if ( [[self target] grid] && [[[self target] grid] active] ) {
349 [[[self target] grid] setActive: NO];
350
351// [[self target] setGrid: nil];
352 }
353}
354
355@end
356
357////////////////////////////////////////////////////////////
358
359#pragma mark -
360#pragma mark ReuseGrid
361
362@implementation CCReuseGrid
363
364+(id)actionWithTimes:(int)times
365{
366 return [[[self alloc] initWithTimes:times ] autorelease];
367}
368
369-(id)initWithTimes:(int)times
370{
371 if ( (self = [super init]) )
372 t_ = times;
373
374 return self;
375}
376
377-(void)startWithTarget:(id)aTarget
378{
379 [super startWithTarget:aTarget];
380
381 CCNode *myTarget = (CCNode*) [self target];
382 if ( myTarget.grid && myTarget.grid.active )
383 myTarget.grid.reuseGrid += t_;
384}
385
386@end
diff --git a/libs/cocos2d/CCActionGrid3D.h b/libs/cocos2d/CCActionGrid3D.h new file mode 100755 index 0000000..a8003f4 --- /dev/null +++ b/libs/cocos2d/CCActionGrid3D.h
@@ -0,0 +1,208 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionGrid.h"
28
29/** CCWaves3D action */
30@interface CCWaves3D : CCGrid3DAction
31{
32 int waves;
33 float amplitude;
34 float amplitudeRate;
35}
36
37/** amplitude of the wave */
38@property (nonatomic,readwrite) float amplitude;
39/** amplitude rate of the wave */
40@property (nonatomic,readwrite) float amplitudeRate;
41
42+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
43-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
44
45@end
46
47////////////////////////////////////////////////////////////
48
49/** CCFlipX3D action */
50@interface CCFlipX3D : CCGrid3DAction
51{
52}
53
54/** creates the action with duration */
55+(id) actionWithDuration:(ccTime)d;
56/** initizlies the action with duration */
57-(id) initWithDuration:(ccTime)d;
58
59@end
60
61////////////////////////////////////////////////////////////
62
63/** CCFlipY3D action */
64@interface CCFlipY3D : CCFlipX3D
65{
66}
67
68@end
69
70////////////////////////////////////////////////////////////
71
72/** CCLens3D action */
73@interface CCLens3D : CCGrid3DAction
74{
75 CGPoint position_;
76 CGPoint positionInPixels_;
77 float radius_;
78 float lensEffect_;
79 BOOL dirty_;
80}
81
82/** lens effect. Defaults to 0.7 - 0 means no effect, 1 is very strong effect */
83@property (nonatomic,readwrite) float lensEffect;
84/** lens center position in Points */
85@property (nonatomic,readwrite) CGPoint position;
86
87/** creates the action with center position in Points, radius, a grid size and duration */
88+(id)actionWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d;
89/** initializes the action with center position in Points, radius, a grid size and duration */
90-(id)initWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d;
91
92@end
93
94////////////////////////////////////////////////////////////
95
96/** CCRipple3D action */
97@interface CCRipple3D : CCGrid3DAction
98{
99 CGPoint position_;
100 CGPoint positionInPixels_;
101 float radius_;
102 int waves_;
103 float amplitude_;
104 float amplitudeRate_;
105}
106
107/** center position in Points */
108@property (nonatomic,readwrite) CGPoint position;
109/** amplitude */
110@property (nonatomic,readwrite) float amplitude;
111/** amplitude rate */
112@property (nonatomic,readwrite) float amplitudeRate;
113
114/** creates the action with a position in points, radius, number of waves, amplitude, a grid size and duration */
115+(id)actionWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
116/** initializes the action with a position in points, radius, number of waves, amplitude, a grid size and duration */
117-(id)initWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
118
119@end
120
121////////////////////////////////////////////////////////////
122
123/** CCShaky3D action */
124@interface CCShaky3D : CCGrid3DAction
125{
126 int randrange;
127 BOOL shakeZ;
128}
129
130/** creates the action with a range, shake Z vertices, a grid and duration */
131+(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d;
132/** initializes the action with a range, shake Z vertices, a grid and duration */
133-(id)initWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d;
134
135@end
136
137////////////////////////////////////////////////////////////
138
139/** CCLiquid action */
140@interface CCLiquid : CCGrid3DAction
141{
142 int waves;
143 float amplitude;
144 float amplitudeRate;
145
146}
147
148/** amplitude */
149@property (nonatomic,readwrite) float amplitude;
150/** amplitude rate */
151@property (nonatomic,readwrite) float amplitudeRate;
152
153/** creates the action with amplitude, a grid and duration */
154+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
155/** initializes the action with amplitude, a grid and duration */
156-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
157
158@end
159
160////////////////////////////////////////////////////////////
161
162/** CCWaves action */
163@interface CCWaves : CCGrid3DAction
164{
165 int waves;
166 float amplitude;
167 float amplitudeRate;
168 BOOL vertical;
169 BOOL horizontal;
170}
171
172/** amplitude */
173@property (nonatomic,readwrite) float amplitude;
174/** amplitude rate */
175@property (nonatomic,readwrite) float amplitudeRate;
176
177/** initializes the action with amplitude, horizontal sin, vertical sin, a grid and duration */
178+(id)actionWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d;
179/** creates the action with amplitude, horizontal sin, vertical sin, a grid and duration */
180-(id)initWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d;
181
182@end
183
184////////////////////////////////////////////////////////////
185
186/** CCTwirl action */
187@interface CCTwirl : CCGrid3DAction
188{
189 CGPoint position_;
190 CGPoint positionInPixels_;
191 int twirls_;
192 float amplitude_;
193 float amplitudeRate_;
194}
195
196/** twirl center */
197@property (nonatomic,readwrite) CGPoint position;
198/** amplitude */
199@property (nonatomic,readwrite) float amplitude;
200/** amplitude rate */
201@property (nonatomic,readwrite) float amplitudeRate;
202
203/** creates the action with center position, number of twirls, amplitude, a grid size and duration */
204+(id)actionWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
205/** initializes the action with center position, number of twirls, amplitude, a grid size and duration */
206-(id)initWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
207
208@end
diff --git a/libs/cocos2d/CCActionGrid3D.m b/libs/cocos2d/CCActionGrid3D.m new file mode 100755 index 0000000..1d4a783 --- /dev/null +++ b/libs/cocos2d/CCActionGrid3D.m
@@ -0,0 +1,659 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionGrid3D.h"
28#import "ccMacros.h"
29#import "Support/CGPointExtension.h"
30
31#pragma mark -
32#pragma mark Waves3D
33
34@implementation CCWaves3D
35
36@synthesize amplitude;
37@synthesize amplitudeRate;
38
39+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
40{
41 return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease];
42}
43
44-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
45{
46 if ( (self = [super initWithSize:gSize duration:d]) )
47 {
48 waves = wav;
49 amplitude = amp;
50 amplitudeRate = 1.0f;
51 }
52
53 return self;
54}
55
56-(id) copyWithZone: (NSZone*) zone
57{
58 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_];
59 return copy;
60}
61
62
63-(void)update:(ccTime)time
64{
65 int i, j;
66
67 for( i = 0; i < (gridSize_.x+1); i++ )
68 {
69 for( j = 0; j < (gridSize_.y+1); j++ )
70 {
71 ccVertex3F v = [self originalVertex:ccg(i,j)];
72 v.z += (sinf((CGFloat)M_PI*time*waves*2 + (v.y+v.x) * .01f) * amplitude * amplitudeRate);
73 [self setVertex:ccg(i,j) vertex:v];
74 }
75 }
76}
77@end
78
79////////////////////////////////////////////////////////////
80
81#pragma mark -
82#pragma mark FlipX3D
83
84@implementation CCFlipX3D
85
86+(id) actionWithDuration:(ccTime)d
87{
88 return [[[self alloc] initWithSize:ccg(1,1) duration:d] autorelease];
89}
90
91-(id) initWithDuration:(ccTime)d
92{
93 return [super initWithSize:ccg(1,1) duration:d];
94}
95
96-(id)initWithSize:(ccGridSize)gSize duration:(ccTime)d
97{
98 if ( gSize.x != 1 || gSize.y != 1 )
99 {
100 [NSException raise:@"FlipX3D" format:@"Grid size must be (1,1)"];
101 }
102
103 return [super initWithSize:gSize duration:d];
104}
105
106-(id) copyWithZone: (NSZone*) zone
107{
108 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSize:gridSize_ duration:duration_];
109 return copy;
110}
111
112
113-(void)update:(ccTime)time
114{
115 CGFloat angle = (CGFloat)M_PI * time; // 180 degrees
116 CGFloat mz = sinf( angle );
117 angle = angle / 2.0f; // x calculates degrees from 0 to 90
118 CGFloat mx = cosf( angle );
119
120 ccVertex3F v0, v1, v, diff;
121
122 v0 = [self originalVertex:ccg(1,1)];
123 v1 = [self originalVertex:ccg(0,0)];
124
125 CGFloat x0 = v0.x;
126 CGFloat x1 = v1.x;
127 CGFloat x;
128 ccGridSize a, b, c, d;
129
130 if ( x0 > x1 )
131 {
132 // Normal Grid
133 a = ccg(0,0);
134 b = ccg(0,1);
135 c = ccg(1,0);
136 d = ccg(1,1);
137 x = x0;
138 }
139 else
140 {
141 // Reversed Grid
142 c = ccg(0,0);
143 d = ccg(0,1);
144 a = ccg(1,0);
145 b = ccg(1,1);
146 x = x1;
147 }
148
149 diff.x = ( x - x * mx );
150 diff.z = fabsf( floorf( (x * mz) / 4.0f ) );
151
152// bottom-left
153 v = [self originalVertex:a];
154 v.x = diff.x;
155 v.z += diff.z;
156 [self setVertex:a vertex:v];
157
158// upper-left
159 v = [self originalVertex:b];
160 v.x = diff.x;
161 v.z += diff.z;
162 [self setVertex:b vertex:v];
163
164// bottom-right
165 v = [self originalVertex:c];
166 v.x -= diff.x;
167 v.z -= diff.z;
168 [self setVertex:c vertex:v];
169
170// upper-right
171 v = [self originalVertex:d];
172 v.x -= diff.x;
173 v.z -= diff.z;
174 [self setVertex:d vertex:v];
175}
176
177@end
178
179////////////////////////////////////////////////////////////
180
181#pragma mark -
182#pragma mark FlipY3D
183
184@implementation CCFlipY3D
185
186-(void)update:(ccTime)time
187{
188 CGFloat angle = (CGFloat)M_PI * time; // 180 degrees
189 CGFloat mz = sinf( angle );
190 angle = angle / 2.0f; // x calculates degrees from 0 to 90
191 CGFloat my = cosf( angle );
192
193 ccVertex3F v0, v1, v, diff;
194
195 v0 = [self originalVertex:ccg(1,1)];
196 v1 = [self originalVertex:ccg(0,0)];
197
198 CGFloat y0 = v0.y;
199 CGFloat y1 = v1.y;
200 CGFloat y;
201 ccGridSize a, b, c, d;
202
203 if ( y0 > y1 )
204 {
205 // Normal Grid
206 a = ccg(0,0);
207 b = ccg(0,1);
208 c = ccg(1,0);
209 d = ccg(1,1);
210 y = y0;
211 }
212 else
213 {
214 // Reversed Grid
215 b = ccg(0,0);
216 a = ccg(0,1);
217 d = ccg(1,0);
218 c = ccg(1,1);
219 y = y1;
220 }
221
222 diff.y = y - y * my;
223 diff.z = fabsf( floorf( (y * mz) / 4.0f ) );
224
225 // bottom-left
226 v = [self originalVertex:a];
227 v.y = diff.y;
228 v.z += diff.z;
229 [self setVertex:a vertex:v];
230
231 // upper-left
232 v = [self originalVertex:b];
233 v.y -= diff.y;
234 v.z -= diff.z;
235 [self setVertex:b vertex:v];
236
237 // bottom-right
238 v = [self originalVertex:c];
239 v.y = diff.y;
240 v.z += diff.z;
241 [self setVertex:c vertex:v];
242
243 // upper-right
244 v = [self originalVertex:d];
245 v.y -= diff.y;
246 v.z -= diff.z;
247 [self setVertex:d vertex:v];
248}
249
250@end
251
252////////////////////////////////////////////////////////////
253
254#pragma mark -
255#pragma mark Lens3D
256
257@implementation CCLens3D
258
259@synthesize lensEffect=lensEffect_;
260
261+(id)actionWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d
262{
263 return [[[self alloc] initWithPosition:pos radius:r grid:gridSize duration:d] autorelease];
264}
265
266-(id)initWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gSize duration:(ccTime)d
267{
268 if ( (self = [super initWithSize:gSize duration:d]) )
269 {
270 position_ = ccp(-1,-1);
271 self.position = pos;
272 radius_ = r;
273 lensEffect_ = 0.7f;
274 dirty_ = YES;
275 }
276
277 return self;
278}
279
280-(id) copyWithZone: (NSZone*) zone
281{
282 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_ radius:radius_ grid:gridSize_ duration:duration_];
283 return copy;
284}
285
286-(void) setPosition:(CGPoint)pos
287{
288 if( ! CGPointEqualToPoint(pos, position_) ) {
289 position_ = pos;
290 positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR();
291 positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR();
292
293 dirty_ = YES;
294 }
295}
296
297-(CGPoint) position
298{
299 return position_;
300}
301
302-(void)update:(ccTime)time
303{
304 if ( dirty_ )
305 {
306 int i, j;
307
308 for( i = 0; i < gridSize_.x+1; i++ )
309 {
310 for( j = 0; j < gridSize_.y+1; j++ )
311 {
312 ccVertex3F v = [self originalVertex:ccg(i,j)];
313 CGPoint vect = ccpSub(positionInPixels_, ccp(v.x,v.y));
314 CGFloat r = ccpLength(vect);
315
316 if ( r < radius_ )
317 {
318 r = radius_ - r;
319 CGFloat pre_log = r / radius_;
320 if ( pre_log == 0 ) pre_log = 0.001f;
321 float l = logf(pre_log) * lensEffect_;
322 float new_r = expf( l ) * radius_;
323
324 if ( ccpLength(vect) > 0 )
325 {
326 vect = ccpNormalize(vect);
327 CGPoint new_vect = ccpMult(vect, new_r);
328 v.z += ccpLength(new_vect) * lensEffect_;
329 }
330 }
331
332 [self setVertex:ccg(i,j) vertex:v];
333 }
334 }
335
336 dirty_ = NO;
337 }
338}
339
340@end
341
342////////////////////////////////////////////////////////////
343
344#pragma mark -
345#pragma mark Ripple3D
346
347@implementation CCRipple3D
348
349@synthesize amplitude = amplitude_;
350@synthesize amplitudeRate = amplitudeRate_;
351
352+(id)actionWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
353{
354 return [[[self alloc] initWithPosition:pos radius:r waves:wav amplitude:amp grid:gridSize duration:d] autorelease];
355}
356
357-(id)initWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
358{
359 if ( (self = [super initWithSize:gSize duration:d]) )
360 {
361 self.position = pos;
362 radius_ = r;
363 waves_ = wav;
364 amplitude_ = amp;
365 amplitudeRate_ = 1.0f;
366 }
367
368 return self;
369}
370
371-(CGPoint) position
372{
373 return position_;
374}
375
376-(void) setPosition:(CGPoint)pos
377{
378 position_ = pos;
379 positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR();
380 positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR();
381}
382
383-(id) copyWithZone: (NSZone*) zone
384{
385 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_ radius:radius_ waves:waves_ amplitude:amplitude_ grid:gridSize_ duration:duration_];
386 return copy;
387}
388
389
390-(void)update:(ccTime)time
391{
392 int i, j;
393
394 for( i = 0; i < (gridSize_.x+1); i++ )
395 {
396 for( j = 0; j < (gridSize_.y+1); j++ )
397 {
398 ccVertex3F v = [self originalVertex:ccg(i,j)];
399 CGPoint vect = ccpSub(positionInPixels_, ccp(v.x,v.y));
400 CGFloat r = ccpLength(vect);
401
402 if ( r < radius_ )
403 {
404 r = radius_ - r;
405 CGFloat rate = powf( r / radius_, 2);
406 v.z += (sinf( time*(CGFloat)M_PI*waves_*2 + r * 0.1f) * amplitude_ * amplitudeRate_ * rate );
407 }
408
409 [self setVertex:ccg(i,j) vertex:v];
410 }
411 }
412}
413
414@end
415
416////////////////////////////////////////////////////////////
417
418#pragma mark -
419#pragma mark Shaky3D
420
421@implementation CCShaky3D
422
423+(id)actionWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gridSize duration:(ccTime)d
424{
425 return [[[self alloc] initWithRange:range shakeZ:sz grid:gridSize duration:d] autorelease];
426}
427
428-(id)initWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d
429{
430 if ( (self = [super initWithSize:gSize duration:d]) )
431 {
432 randrange = range;
433 shakeZ = sz;
434 }
435
436 return self;
437}
438
439-(id) copyWithZone: (NSZone*) zone
440{
441 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shakeZ:shakeZ grid:gridSize_ duration:duration_];
442 return copy;
443}
444
445-(void)update:(ccTime)time
446{
447 int i, j;
448
449 for( i = 0; i < (gridSize_.x+1); i++ )
450 {
451 for( j = 0; j < (gridSize_.y+1); j++ )
452 {
453 ccVertex3F v = [self originalVertex:ccg(i,j)];
454 v.x += ( rand() % (randrange*2) ) - randrange;
455 v.y += ( rand() % (randrange*2) ) - randrange;
456 if( shakeZ )
457 v.z += ( rand() % (randrange*2) ) - randrange;
458
459 [self setVertex:ccg(i,j) vertex:v];
460 }
461 }
462}
463
464@end
465
466////////////////////////////////////////////////////////////
467
468#pragma mark -
469#pragma mark Liquid
470
471@implementation CCLiquid
472
473@synthesize amplitude;
474@synthesize amplitudeRate;
475
476+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
477{
478 return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease];
479}
480
481-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
482{
483 if ( (self = [super initWithSize:gSize duration:d]) )
484 {
485 waves = wav;
486 amplitude = amp;
487 amplitudeRate = 1.0f;
488 }
489
490 return self;
491}
492
493-(void)update:(ccTime)time
494{
495 int i, j;
496
497 for( i = 1; i < gridSize_.x; i++ )
498 {
499 for( j = 1; j < gridSize_.y; j++ )
500 {
501 ccVertex3F v = [self originalVertex:ccg(i,j)];
502 v.x = (v.x + (sinf(time*(CGFloat)M_PI*waves*2 + v.x * .01f) * amplitude * amplitudeRate));
503 v.y = (v.y + (sinf(time*(CGFloat)M_PI*waves*2 + v.y * .01f) * amplitude * amplitudeRate));
504 [self setVertex:ccg(i,j) vertex:v];
505 }
506 }
507}
508
509-(id) copyWithZone: (NSZone*) zone
510{
511 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_];
512 return copy;
513}
514
515@end
516
517////////////////////////////////////////////////////////////
518
519#pragma mark -
520#pragma mark Waves
521
522@implementation CCWaves
523
524@synthesize amplitude;
525@synthesize amplitudeRate;
526
527+(id)actionWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d
528{
529 return [[[self alloc] initWithWaves:wav amplitude:amp horizontal:h vertical:v grid:gridSize duration:d] autorelease];
530}
531
532-(id)initWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gSize duration:(ccTime)d
533{
534 if ( (self = [super initWithSize:gSize duration:d]) )
535 {
536 waves = wav;
537 amplitude = amp;
538 amplitudeRate = 1.0f;
539 horizontal = h;
540 vertical = v;
541 }
542
543 return self;
544}
545
546-(void)update:(ccTime)time
547{
548 int i, j;
549
550 for( i = 0; i < (gridSize_.x+1); i++ )
551 {
552 for( j = 0; j < (gridSize_.y+1); j++ )
553 {
554 ccVertex3F v = [self originalVertex:ccg(i,j)];
555
556 if ( vertical )
557 v.x = (v.x + (sinf(time*(CGFloat)M_PI*waves*2 + v.y * .01f) * amplitude * amplitudeRate));
558
559 if ( horizontal )
560 v.y = (v.y + (sinf(time*(CGFloat)M_PI*waves*2 + v.x * .01f) * amplitude * amplitudeRate));
561
562 [self setVertex:ccg(i,j) vertex:v];
563 }
564 }
565}
566
567-(id) copyWithZone: (NSZone*) zone
568{
569 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude horizontal:horizontal vertical:vertical grid:gridSize_ duration:duration_];
570 return copy;
571}
572
573@end
574
575////////////////////////////////////////////////////////////
576
577#pragma mark -
578#pragma mark Twirl
579
580@implementation CCTwirl
581
582@synthesize amplitude = amplitude_;
583@synthesize amplitudeRate = amplitudeRate_;
584
585+(id)actionWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
586{
587 return [[[self alloc] initWithPosition:pos twirls:t amplitude:amp grid:gridSize duration:d] autorelease];
588}
589
590-(id)initWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
591{
592 if ( (self = [super initWithSize:gSize duration:d]) )
593 {
594 self.position = pos;
595 twirls_ = t;
596 amplitude_ = amp;
597 amplitudeRate_ = 1.0f;
598 }
599
600 return self;
601}
602
603-(void) setPosition:(CGPoint)pos
604{
605 position_ = pos;
606 positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR();
607 positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR();
608}
609
610-(CGPoint) position
611{
612 return position_;
613}
614
615-(void)update:(ccTime)time
616{
617 int i, j;
618 CGPoint c = positionInPixels_;
619
620 for( i = 0; i < (gridSize_.x+1); i++ )
621 {
622 for( j = 0; j < (gridSize_.y+1); j++ )
623 {
624 ccVertex3F v = [self originalVertex:ccg(i,j)];
625
626 CGPoint avg = ccp(i-(gridSize_.x/2.0f), j-(gridSize_.y/2.0f));
627 CGFloat r = ccpLength( avg );
628
629 CGFloat amp = 0.1f * amplitude_ * amplitudeRate_;
630 CGFloat a = r * cosf( (CGFloat)M_PI/2.0f + time * (CGFloat)M_PI * twirls_ * 2 ) * amp;
631
632 float cosA = cosf(a);
633 float sinA = sinf(a);
634
635 CGPoint d = {
636 sinA * (v.y-c.y) + cosA * (v.x-c.x),
637 cosA * (v.y-c.y) - sinA * (v.x-c.x)
638 };
639
640 v.x = c.x + d.x;
641 v.y = c.y + d.y;
642
643 [self setVertex:ccg(i,j) vertex:v];
644 }
645 }
646}
647
648-(id) copyWithZone: (NSZone*) zone
649{
650 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_
651 twirls:twirls_
652 amplitude:amplitude_
653 grid:gridSize_
654 duration:duration_];
655 return copy;
656}
657
658
659@end
diff --git a/libs/cocos2d/CCActionInstant.h b/libs/cocos2d/CCActionInstant.h new file mode 100755 index 0000000..5a1bc2d --- /dev/null +++ b/libs/cocos2d/CCActionInstant.h
@@ -0,0 +1,205 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCAction.h"
29
30/** Instant actions are immediate actions. They don't have a duration like
31 the CCIntervalAction actions.
32*/
33@interface CCActionInstant : CCFiniteTimeAction <NSCopying>
34{
35}
36@end
37
38/** Show the node
39 */
40 @interface CCShow : CCActionInstant
41{
42}
43@end
44
45/** Hide the node
46 */
47@interface CCHide : CCActionInstant
48{
49}
50@end
51
52/** Toggles the visibility of a node
53 */
54@interface CCToggleVisibility : CCActionInstant
55{
56}
57@end
58
59/** Flips the sprite horizontally
60 @since v0.99.0
61 */
62@interface CCFlipX : CCActionInstant
63{
64 BOOL flipX;
65}
66+(id) actionWithFlipX:(BOOL)x;
67-(id) initWithFlipX:(BOOL)x;
68@end
69
70/** Flips the sprite vertically
71 @since v0.99.0
72 */
73@interface CCFlipY : CCActionInstant
74{
75 BOOL flipY;
76}
77+(id) actionWithFlipY:(BOOL)y;
78-(id) initWithFlipY:(BOOL)y;
79@end
80
81/** Places the node in a certain position
82 */
83@interface CCPlace : CCActionInstant <NSCopying>
84{
85 CGPoint position;
86}
87/** creates a Place action with a position */
88+(id) actionWithPosition: (CGPoint) pos;
89/** Initializes a Place action with a position */
90-(id) initWithPosition: (CGPoint) pos;
91@end
92
93/** Calls a 'callback'
94 */
95@interface CCCallFunc : CCActionInstant <NSCopying>
96{
97 id targetCallback_;
98 SEL selector_;
99}
100
101/** Target that will be called */
102@property (nonatomic, readwrite, retain) id targetCallback;
103
104/** creates the action with the callback */
105+(id) actionWithTarget: (id) t selector:(SEL) s;
106/** initializes the action with the callback */
107-(id) initWithTarget: (id) t selector:(SEL) s;
108/** exeuctes the callback */
109-(void) execute;
110@end
111
112/** Calls a 'callback' with the node as the first argument.
113 N means Node
114 */
115@interface CCCallFuncN : CCCallFunc
116{
117}
118@end
119
120typedef void (*CC_CALLBACK_ND)(id, SEL, id, void *);
121/** Calls a 'callback' with the node as the first argument and the 2nd argument is data.
122 * ND means: Node and Data. Data is void *, so it could be anything.
123 */
124@interface CCCallFuncND : CCCallFuncN
125{
126 void *data_;
127 CC_CALLBACK_ND callbackMethod_;
128}
129
130/** Invocation object that has the target#selector and the parameters */
131@property (nonatomic,readwrite) CC_CALLBACK_ND callbackMethod;
132
133/** creates the action with the callback and the data to pass as an argument */
134+(id) actionWithTarget: (id) t selector:(SEL) s data:(void*)d;
135/** initializes the action with the callback and the data to pass as an argument */
136-(id) initWithTarget:(id) t selector:(SEL) s data:(void*) d;
137@end
138
139/** Calls a 'callback' with an object as the first argument.
140 O means Object.
141 @since v0.99.5
142 */
143@interface CCCallFuncO : CCCallFunc
144{
145 id object_;
146}
147/** object to be passed as argument */
148@property (nonatomic, readwrite, retain) id object;
149
150/** creates the action with the callback and the object to pass as an argument */
151+(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object;
152/** initializes the action with the callback and the object to pass as an argument */
153-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object;
154
155@end
156
157#pragma mark Blocks Support
158
159#if NS_BLOCKS_AVAILABLE
160
161/** Executes a callback using a block.
162 */
163@interface CCCallBlock : CCActionInstant<NSCopying>
164{
165 void (^block_)();
166}
167
168/** creates the action with the specified block, to be used as a callback.
169 The block will be "copied".
170 */
171+(id) actionWithBlock:(void(^)())block;
172
173/** initialized the action with the specified block, to be used as a callback.
174 The block will be "copied".
175 */
176-(id) initWithBlock:(void(^)())block;
177
178/** executes the callback */
179-(void) execute;
180@end
181
182@class CCNode;
183
184/** Executes a callback using a block with a single CCNode parameter.
185 */
186@interface CCCallBlockN : CCActionInstant<NSCopying>
187{
188 void (^block_)(CCNode *);
189}
190
191/** creates the action with the specified block, to be used as a callback.
192 The block will be "copied".
193 */
194+(id) actionWithBlock:(void(^)(CCNode *node))block;
195
196/** initialized the action with the specified block, to be used as a callback.
197 The block will be "copied".
198 */
199-(id) initWithBlock:(void(^)(CCNode *node))block;
200
201/** executes the callback */
202-(void) execute;
203@end
204
205#endif
diff --git a/libs/cocos2d/CCActionInstant.m b/libs/cocos2d/CCActionInstant.m new file mode 100755 index 0000000..e7f6fad --- /dev/null +++ b/libs/cocos2d/CCActionInstant.m
@@ -0,0 +1,477 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCBlockSupport.h"
29#import "CCActionInstant.h"
30#import "CCNode.h"
31#import "CCSprite.h"
32
33
34//
35// InstantAction
36//
37#pragma mark CCActionInstant
38
39@implementation CCActionInstant
40
41-(id) init
42{
43 if( (self=[super init]) )
44 duration_ = 0;
45
46 return self;
47}
48
49-(id) copyWithZone: (NSZone*) zone
50{
51 CCActionInstant *copy = [[[self class] allocWithZone: zone] init];
52 return copy;
53}
54
55- (BOOL) isDone
56{
57 return YES;
58}
59
60-(void) step: (ccTime) dt
61{
62 [self update: 1];
63}
64
65-(void) update: (ccTime) t
66{
67 // ignore
68}
69
70-(CCFiniteTimeAction*) reverse
71{
72 return [[self copy] autorelease];
73}
74@end
75
76//
77// Show
78//
79#pragma mark CCShow
80
81@implementation CCShow
82-(void) startWithTarget:(id)aTarget
83{
84 [super startWithTarget:aTarget];
85 ((CCNode *)target_).visible = YES;
86}
87
88-(CCFiniteTimeAction*) reverse
89{
90 return [CCHide action];
91}
92@end
93
94//
95// Hide
96//
97#pragma mark CCHide
98
99@implementation CCHide
100-(void) startWithTarget:(id)aTarget
101{
102 [super startWithTarget:aTarget];
103 ((CCNode *)target_).visible = NO;
104}
105
106-(CCFiniteTimeAction*) reverse
107{
108 return [CCShow action];
109}
110@end
111
112//
113// ToggleVisibility
114//
115#pragma mark CCToggleVisibility
116
117@implementation CCToggleVisibility
118-(void) startWithTarget:(id)aTarget
119{
120 [super startWithTarget:aTarget];
121 ((CCNode *)target_).visible = !((CCNode *)target_).visible;
122}
123@end
124
125//
126// FlipX
127//
128#pragma mark CCFlipX
129
130@implementation CCFlipX
131+(id) actionWithFlipX:(BOOL)x
132{
133 return [[[self alloc] initWithFlipX:x] autorelease];
134}
135
136-(id) initWithFlipX:(BOOL)x
137{
138 if(( self=[super init]))
139 flipX = x;
140
141 return self;
142}
143
144-(void) startWithTarget:(id)aTarget
145{
146 [super startWithTarget:aTarget];
147 [(CCSprite*)aTarget setFlipX:flipX];
148}
149
150-(CCFiniteTimeAction*) reverse
151{
152 return [CCFlipX actionWithFlipX:!flipX];
153}
154
155-(id) copyWithZone: (NSZone*) zone
156{
157 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipX:flipX];
158 return copy;
159}
160@end
161
162//
163// FlipY
164//
165#pragma mark CCFlipY
166
167@implementation CCFlipY
168+(id) actionWithFlipY:(BOOL)y
169{
170 return [[[self alloc] initWithFlipY:y] autorelease];
171}
172
173-(id) initWithFlipY:(BOOL)y
174{
175 if(( self=[super init]))
176 flipY = y;
177
178 return self;
179}
180
181-(void) startWithTarget:(id)aTarget
182{
183 [super startWithTarget:aTarget];
184 [(CCSprite*)aTarget setFlipY:flipY];
185}
186
187-(CCFiniteTimeAction*) reverse
188{
189 return [CCFlipY actionWithFlipY:!flipY];
190}
191
192-(id) copyWithZone: (NSZone*) zone
193{
194 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipY:flipY];
195 return copy;
196}
197@end
198
199
200//
201// Place
202//
203#pragma mark CCPlace
204
205@implementation CCPlace
206+(id) actionWithPosition: (CGPoint) pos
207{
208 return [[[self alloc]initWithPosition:pos]autorelease];
209}
210
211-(id) initWithPosition: (CGPoint) pos
212{
213 if( (self=[super init]) )
214 position = pos;
215
216 return self;
217}
218
219-(id) copyWithZone: (NSZone*) zone
220{
221 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithPosition: position];
222 return copy;
223}
224
225-(void) startWithTarget:(id)aTarget
226{
227 [super startWithTarget:aTarget];
228 ((CCNode *)target_).position = position;
229}
230
231@end
232
233//
234// CallFunc
235//
236#pragma mark CCCallFunc
237
238@implementation CCCallFunc
239
240@synthesize targetCallback = targetCallback_;
241
242+(id) actionWithTarget: (id) t selector:(SEL) s
243{
244 return [[[self alloc] initWithTarget: t selector: s] autorelease];
245}
246
247-(id) initWithTarget: (id) t selector:(SEL) s
248{
249 if( (self=[super init]) ) {
250 self.targetCallback = t;
251 selector_ = s;
252 }
253 return self;
254}
255
256-(NSString*) description
257{
258 return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i | target = %@ | selector = %@>",
259 [self class],
260 self,
261 tag_,
262 [targetCallback_ class],
263 NSStringFromSelector(selector_)
264 ];
265}
266
267-(void) dealloc
268{
269 [targetCallback_ release];
270 [super dealloc];
271}
272
273-(id) copyWithZone: (NSZone*) zone
274{
275 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_];
276 return copy;
277}
278
279-(void) startWithTarget:(id)aTarget
280{
281 [super startWithTarget:aTarget];
282 [self execute];
283}
284
285-(void) execute
286{
287 [targetCallback_ performSelector:selector_];
288}
289@end
290
291//
292// CallFuncN
293//
294#pragma mark CCCallFuncN
295
296@implementation CCCallFuncN
297
298-(void) execute
299{
300 [targetCallback_ performSelector:selector_ withObject:target_];
301}
302@end
303
304//
305// CallFuncND
306//
307#pragma mark CCCallFuncND
308
309@implementation CCCallFuncND
310
311@synthesize callbackMethod = callbackMethod_;
312
313+(id) actionWithTarget:(id)t selector:(SEL)s data:(void*)d
314{
315 return [[[self alloc] initWithTarget:t selector:s data:d] autorelease];
316}
317
318-(id) initWithTarget:(id)t selector:(SEL)s data:(void*)d
319{
320 if( (self=[super initWithTarget:t selector:s]) ) {
321 data_ = d;
322
323#if COCOS2D_DEBUG
324 NSMethodSignature * sig = [t methodSignatureForSelector:s]; // added
325 NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void)name:(id)sender data:(void*)data");
326#endif
327 callbackMethod_ = (CC_CALLBACK_ND) [t methodForSelector:s];
328 }
329 return self;
330}
331
332-(id) copyWithZone: (NSZone*) zone
333{
334 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_ data:data_];
335 return copy;
336}
337
338-(void) dealloc
339{
340 // nothing to dealloc really. Everything is dealloc on super (CCCallFuncN)
341 [super dealloc];
342}
343
344-(void) execute
345{
346 callbackMethod_(targetCallback_,selector_,target_, data_);
347}
348@end
349
350@implementation CCCallFuncO
351@synthesize object = object_;
352
353+(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object
354{
355 return [[[self alloc] initWithTarget:t selector:s object:object] autorelease];
356}
357
358-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object
359{
360 if( (self=[super initWithTarget:t selector:s] ) )
361 self.object = object;
362
363 return self;
364}
365
366- (void) dealloc
367{
368 [object_ release];
369 [super dealloc];
370}
371
372-(id) copyWithZone: (NSZone*) zone
373{
374 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_ object:object_];
375 return copy;
376}
377
378
379-(void) execute
380{
381 [targetCallback_ performSelector:selector_ withObject:object_];
382}
383
384@end
385
386
387#pragma mark -
388#pragma mark Blocks
389
390#if NS_BLOCKS_AVAILABLE
391
392#pragma mark CCCallBlock
393
394@implementation CCCallBlock
395
396+(id) actionWithBlock:(void(^)())block
397{
398 return [[[self alloc] initWithBlock:block] autorelease];
399}
400
401-(id) initWithBlock:(void(^)())block
402{
403 if ((self = [super init]))
404 block_ = [block copy];
405
406 return self;
407}
408
409-(id) copyWithZone: (NSZone*) zone
410{
411 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:block_];
412 return copy;
413}
414
415-(void) startWithTarget:(id)aTarget
416{
417 [super startWithTarget:aTarget];
418 [self execute];
419}
420
421-(void) execute
422{
423 block_();
424}
425
426-(void) dealloc
427{
428 [block_ release];
429 [super dealloc];
430}
431
432@end
433
434#pragma mark CCCallBlockN
435
436@implementation CCCallBlockN
437
438+(id) actionWithBlock:(void(^)(CCNode *node))block
439{
440 return [[[self alloc] initWithBlock:block] autorelease];
441}
442
443-(id) initWithBlock:(void(^)(CCNode *node))block
444{
445 if ((self = [super init]))
446 block_ = [block copy];
447
448 return self;
449}
450
451-(id) copyWithZone: (NSZone*) zone
452{
453 CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:block_];
454 return copy;
455}
456
457-(void) startWithTarget:(id)aTarget
458{
459 [super startWithTarget:aTarget];
460 [self execute];
461}
462
463-(void) execute
464{
465 block_(target_);
466}
467
468-(void) dealloc
469{
470 [block_ release];
471 [super dealloc];
472}
473
474@end
475
476
477#endif // NS_BLOCKS_AVAILABLE
diff --git a/libs/cocos2d/CCActionInterval.h b/libs/cocos2d/CCActionInterval.h new file mode 100755 index 0000000..c667963 --- /dev/null +++ b/libs/cocos2d/CCActionInterval.h
@@ -0,0 +1,421 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCNode.h"
29#import "CCAction.h"
30#import "CCProtocols.h"
31
32#include <sys/time.h>
33
34/** An interval action is an action that takes place within a certain period of time.
35It has an start time, and a finish time. The finish time is the parameter
36duration plus the start time.
37
38These CCActionInterval actions have some interesting properties, like:
39 - They can run normally (default)
40 - They can run reversed with the reverse method
41 - They can run with the time altered with the Accelerate, AccelDeccel and Speed actions.
42
43For example, you can simulate a Ping Pong effect running the action normally and
44then running it again in Reverse mode.
45
46Example:
47
48 CCAction * pingPongAction = [CCSequence actions: action, [action reverse], nil];
49*/
50@interface CCActionInterval: CCFiniteTimeAction <NSCopying>
51{
52 ccTime elapsed_;
53 BOOL firstTick_;
54}
55
56/** how many seconds had elapsed since the actions started to run. */
57@property (nonatomic,readonly) ccTime elapsed;
58
59/** creates the action */
60+(id) actionWithDuration: (ccTime) d;
61/** initializes the action */
62-(id) initWithDuration: (ccTime) d;
63/** returns YES if the action has finished */
64-(BOOL) isDone;
65/** returns a reversed action */
66- (CCActionInterval*) reverse;
67@end
68
69/** Runs actions sequentially, one after another
70 */
71@interface CCSequence : CCActionInterval <NSCopying>
72{
73 CCFiniteTimeAction *actions_[2];
74 ccTime split_;
75 int last_;
76}
77/** helper contructor to create an array of sequenceable actions */
78+(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION;
79/** helper contructor to create an array of sequenceable actions given an array */
80+(id) actionsWithArray: (NSArray*) actions;
81/** creates the action */
82+(id) actionOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo;
83/** initializes the action */
84-(id) initOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo;
85@end
86
87
88/** Repeats an action a number of times.
89 * To repeat an action forever use the CCRepeatForever action.
90 */
91@interface CCRepeat : CCActionInterval <NSCopying>
92{
93 NSUInteger times_;
94 NSUInteger total_;
95 CCFiniteTimeAction *innerAction_;
96}
97
98/** Inner action */
99@property (nonatomic,readwrite,retain) CCFiniteTimeAction *innerAction;
100
101/** creates a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT */
102+(id) actionWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times;
103/** initializes a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT */
104-(id) initWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times;
105@end
106
107/** Spawn a new action immediately
108 */
109@interface CCSpawn : CCActionInterval <NSCopying>
110{
111 CCFiniteTimeAction *one_;
112 CCFiniteTimeAction *two_;
113}
114/** helper constructor to create an array of spawned actions */
115+(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION;
116/** helper contructor to create an array of spawned actions given an array */
117+(id) actionsWithArray: (NSArray*) actions;
118/** creates the Spawn action */
119+(id) actionOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two;
120/** initializes the Spawn action with the 2 actions to spawn */
121-(id) initOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two;
122@end
123
124/** Rotates a CCNode object to a certain angle by modifying it's
125 rotation attribute.
126 The direction will be decided by the shortest angle.
127*/
128@interface CCRotateTo : CCActionInterval <NSCopying>
129{
130 float dstAngle_;
131 float startAngle_;
132 float diffAngle_;
133}
134/** creates the action */
135+(id) actionWithDuration:(ccTime)duration angle:(float)angle;
136/** initializes the action */
137-(id) initWithDuration:(ccTime)duration angle:(float)angle;
138@end
139
140/** Rotates a CCNode object clockwise a number of degrees by modiying it's rotation attribute.
141*/
142@interface CCRotateBy : CCActionInterval <NSCopying>
143{
144 float angle_;
145 float startAngle_;
146}
147/** creates the action */
148+(id) actionWithDuration:(ccTime)duration angle:(float)deltaAngle;
149/** initializes the action */
150-(id) initWithDuration:(ccTime)duration angle:(float)deltaAngle;
151@end
152
153/** Moves a CCNode object to the position x,y. x and y are absolute coordinates by modifying it's position attribute.
154*/
155@interface CCMoveTo : CCActionInterval <NSCopying>
156{
157 CGPoint endPosition_;
158 CGPoint startPosition_;
159 CGPoint delta_;
160}
161/** creates the action */
162+(id) actionWithDuration:(ccTime)duration position:(CGPoint)position;
163/** initializes the action */
164-(id) initWithDuration:(ccTime)duration position:(CGPoint)position;
165@end
166
167/** Moves a CCNode object x,y pixels by modifying it's position attribute.
168 x and y are relative to the position of the object.
169 Duration is is seconds.
170*/
171@interface CCMoveBy : CCMoveTo <NSCopying>
172{
173}
174/** creates the action */
175+(id) actionWithDuration: (ccTime)duration position:(CGPoint)deltaPosition;
176/** initializes the action */
177-(id) initWithDuration: (ccTime)duration position:(CGPoint)deltaPosition;
178@end
179
180/** Skews a CCNode object to given angles by modifying it's skewX and skewY attributes
181 @since v1.0
182 */
183@interface CCSkewTo : CCActionInterval <NSCopying>
184{
185 float skewX_;
186 float skewY_;
187 float startSkewX_;
188 float startSkewY_;
189 float endSkewX_;
190 float endSkewY_;
191 float deltaX_;
192 float deltaY_;
193}
194/** creates the action */
195+(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy;
196/** initializes the action */
197-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy;
198@end
199
200/** Skews a CCNode object by skewX and skewY degrees
201 @since v1.0
202 */
203@interface CCSkewBy : CCSkewTo <NSCopying>
204{
205}
206@end
207
208/** Moves a CCNode object simulating a parabolic jump movement by modifying it's position attribute.
209*/
210 @interface CCJumpBy : CCActionInterval <NSCopying>
211{
212 CGPoint startPosition_;
213 CGPoint delta_;
214 ccTime height_;
215 NSUInteger jumps_;
216}
217/** creates the action */
218+(id) actionWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps;
219/** initializes the action */
220-(id) initWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps;
221@end
222
223/** Moves a CCNode object to a parabolic position simulating a jump movement by modifying it's position attribute.
224*/
225 @interface CCJumpTo : CCJumpBy <NSCopying>
226{
227}
228@end
229
230/** bezier configuration structure
231 */
232typedef struct _ccBezierConfig {
233 //! end position of the bezier
234 CGPoint endPosition;
235 //! Bezier control point 1
236 CGPoint controlPoint_1;
237 //! Bezier control point 2
238 CGPoint controlPoint_2;
239} ccBezierConfig;
240
241/** An action that moves the target with a cubic Bezier curve by a certain distance.
242 */
243@interface CCBezierBy : CCActionInterval <NSCopying>
244{
245 ccBezierConfig config_;
246 CGPoint startPosition_;
247}
248
249/** creates the action with a duration and a bezier configuration */
250+(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c;
251
252/** initializes the action with a duration and a bezier configuration */
253-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c;
254@end
255
256/** An action that moves the target with a cubic Bezier curve to a destination point.
257 @since v0.8.2
258 */
259@interface CCBezierTo : CCBezierBy
260{
261}
262@end
263
264/** Scales a CCNode object to a zoom factor by modifying it's scale attribute.
265 @warning This action doesn't support "reverse"
266 */
267@interface CCScaleTo : CCActionInterval <NSCopying>
268{
269 float scaleX_;
270 float scaleY_;
271 float startScaleX_;
272 float startScaleY_;
273 float endScaleX_;
274 float endScaleY_;
275 float deltaX_;
276 float deltaY_;
277}
278/** creates the action with the same scale factor for X and Y */
279+(id) actionWithDuration: (ccTime)duration scale:(float) s;
280/** initializes the action with the same scale factor for X and Y */
281-(id) initWithDuration: (ccTime)duration scale:(float) s;
282/** creates the action with and X factor and a Y factor */
283+(id) actionWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy;
284/** initializes the action with and X factor and a Y factor */
285-(id) initWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy;
286@end
287
288/** Scales a CCNode object a zoom factor by modifying it's scale attribute.
289*/
290@interface CCScaleBy : CCScaleTo <NSCopying>
291{
292}
293@end
294
295/** Blinks a CCNode object by modifying it's visible attribute
296*/
297@interface CCBlink : CCActionInterval <NSCopying>
298{
299 NSUInteger times_;
300}
301/** creates the action */
302+(id) actionWithDuration: (ccTime)duration blinks:(NSUInteger)blinks;
303/** initilizes the action */
304-(id) initWithDuration: (ccTime)duration blinks:(NSUInteger)blinks;
305@end
306
307/** Fades In an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 0 to 255.
308 The "reverse" of this action is FadeOut
309 */
310@interface CCFadeIn : CCActionInterval <NSCopying>
311{
312}
313@end
314
315/** Fades Out an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 255 to 0.
316 The "reverse" of this action is FadeIn
317*/
318@interface CCFadeOut : CCActionInterval <NSCopying>
319{
320}
321@end
322
323/** Fades an object that implements the CCRGBAProtocol protocol. It modifies the opacity from the current value to a custom one.
324 @warning This action doesn't support "reverse"
325 */
326@interface CCFadeTo : CCActionInterval <NSCopying>
327{
328 GLubyte toOpacity_;
329 GLubyte fromOpacity_;
330}
331/** creates an action with duration and opactiy */
332+(id) actionWithDuration:(ccTime)duration opacity:(GLubyte)opactiy;
333/** initializes the action with duration and opacity */
334-(id) initWithDuration:(ccTime)duration opacity:(GLubyte)opacity;
335@end
336
337/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one.
338 @warning This action doesn't support "reverse"
339 @since v0.7.2
340*/
341@interface CCTintTo : CCActionInterval <NSCopying>
342{
343 ccColor3B to_;
344 ccColor3B from_;
345}
346/** creates an action with duration and color */
347+(id) actionWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue;
348/** initializes the action with duration and color */
349-(id) initWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue;
350@end
351
352/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one.
353 @since v0.7.2
354 */
355@interface CCTintBy : CCActionInterval <NSCopying>
356{
357 GLshort deltaR_, deltaG_, deltaB_;
358 GLshort fromR_, fromG_, fromB_;
359}
360/** creates an action with duration and color */
361+(id) actionWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue;
362/** initializes the action with duration and color */
363-(id) initWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue;
364@end
365
366/** Delays the action a certain amount of seconds
367*/
368@interface CCDelayTime : CCActionInterval <NSCopying>
369{
370}
371@end
372
373/** Executes an action in reverse order, from time=duration to time=0
374
375 @warning Use this action carefully. This action is not
376 sequenceable. Use it as the default "reversed" method
377 of your own actions, but using it outside the "reversed"
378 scope is not recommended.
379*/
380@interface CCReverseTime : CCActionInterval <NSCopying>
381{
382 CCFiniteTimeAction * other_;
383}
384/** creates the action */
385+(id) actionWithAction: (CCFiniteTimeAction*) action;
386/** initializes the action */
387-(id) initWithAction: (CCFiniteTimeAction*) action;
388@end
389
390
391@class CCAnimation;
392@class CCTexture2D;
393/** Animates a sprite given the name of an Animation */
394@interface CCAnimate : CCActionInterval <NSCopying>
395{
396 CCAnimation *animation_;
397 id origFrame_;
398 BOOL restoreOriginalFrame_;
399}
400/** animation used for the animage */
401@property (readwrite,nonatomic,retain) CCAnimation * animation;
402
403/** creates the action with an Animation and will restore the original frame when the animation is over */
404+(id) actionWithAnimation:(CCAnimation*) a;
405/** initializes the action with an Animation and will restore the original frame when the animtion is over */
406-(id) initWithAnimation:(CCAnimation*) a;
407/** creates the action with an Animation */
408+(id) actionWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b;
409/** initializes the action with an Animation */
410-(id) initWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b;
411/** creates an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not.
412 The 'delay' parameter of the animation will be overrided by the duration parameter.
413 @since v0.99.0
414 */
415+(id) actionWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b;
416/** initializes an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not.
417 The 'delay' parameter of the animation will be overrided by the duration parameter.
418 @since v0.99.0
419 */
420-(id) initWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b;
421@end
diff --git a/libs/cocos2d/CCActionInterval.m b/libs/cocos2d/CCActionInterval.m new file mode 100755 index 0000000..17bef40 --- /dev/null +++ b/libs/cocos2d/CCActionInterval.m
@@ -0,0 +1,1355 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import "CCActionInterval.h"
30#import "CCSprite.h"
31#import "CCSpriteFrame.h"
32#import "CCAnimation.h"
33#import "CCNode.h"
34#import "Support/CGPointExtension.h"
35
36//
37// IntervalAction
38//
39#pragma mark -
40#pragma mark IntervalAction
41@implementation CCActionInterval
42
43@synthesize elapsed = elapsed_;
44
45-(id) init
46{
47 NSAssert(NO, @"IntervalActionInit: Init not supported. Use InitWithDuration");
48 [self release];
49 return nil;
50}
51
52+(id) actionWithDuration: (ccTime) d
53{
54 return [[[self alloc] initWithDuration:d ] autorelease];
55}
56
57-(id) initWithDuration: (ccTime) d
58{
59 if( (self=[super init]) ) {
60 duration_ = d;
61
62 // prevent division by 0
63 // This comparison could be in step:, but it might decrease the performance
64 // by 3% in heavy based action games.
65 if( duration_ == 0 )
66 duration_ = FLT_EPSILON;
67 elapsed_ = 0;
68 firstTick_ = YES;
69 }
70 return self;
71}
72
73-(id) copyWithZone: (NSZone*) zone
74{
75 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] ];
76 return copy;
77}
78
79- (BOOL) isDone
80{
81 return (elapsed_ >= duration_);
82}
83
84-(void) step: (ccTime) dt
85{
86 if( firstTick_ ) {
87 firstTick_ = NO;
88 elapsed_ = 0;
89 } else
90 elapsed_ += dt;
91
92 [self update: MIN(1, elapsed_/duration_)];
93}
94
95-(void) startWithTarget:(id)aTarget
96{
97 [super startWithTarget:aTarget];
98 elapsed_ = 0.0f;
99 firstTick_ = YES;
100}
101
102- (CCActionInterval*) reverse
103{
104 NSAssert(NO, @"CCIntervalAction: reverse not implemented.");
105 return nil;
106}
107@end
108
109//
110// Sequence
111//
112#pragma mark -
113#pragma mark Sequence
114@implementation CCSequence
115+(id) actions: (CCFiniteTimeAction*) action1, ...
116{
117 va_list params;
118 va_start(params,action1);
119
120 CCFiniteTimeAction *now;
121 CCFiniteTimeAction *prev = action1;
122
123 while( action1 ) {
124 now = va_arg(params,CCFiniteTimeAction*);
125 if ( now )
126 prev = [self actionOne: prev two: now];
127 else
128 break;
129 }
130 va_end(params);
131 return prev;
132}
133
134+(id) actionsWithArray: (NSArray*) actions
135{
136 CCFiniteTimeAction *prev = [actions objectAtIndex:0];
137
138 for (NSUInteger i = 1; i < [actions count]; i++)
139 prev = [self actionOne:prev two:[actions objectAtIndex:i]];
140
141 return prev;
142}
143
144+(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
145{
146 return [[[self alloc] initOne:one two:two ] autorelease];
147}
148
149-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
150{
151 NSAssert( one!=nil && two!=nil, @"Sequence: arguments must be non-nil");
152 NSAssert( one!=actions_[0] && one!=actions_[1], @"Sequence: re-init using the same parameters is not supported");
153 NSAssert( two!=actions_[1] && two!=actions_[0], @"Sequence: re-init using the same parameters is not supported");
154
155 ccTime d = [one duration] + [two duration];
156
157 if( (self=[super initWithDuration: d]) ) {
158
159 // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_
160 [actions_[0] release];
161 [actions_[1] release];
162
163 actions_[0] = [one retain];
164 actions_[1] = [two retain];
165 }
166
167 return self;
168}
169
170-(id) copyWithZone: (NSZone*) zone
171{
172 CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[actions_[0] copy] autorelease] two:[[actions_[1] copy] autorelease] ];
173 return copy;
174}
175
176-(void) dealloc
177{
178 [actions_[0] release];
179 [actions_[1] release];
180 [super dealloc];
181}
182
183-(void) startWithTarget:(id)aTarget
184{
185 [super startWithTarget:aTarget];
186 split_ = [actions_[0] duration] / duration_;
187 last_ = -1;
188}
189
190-(void) stop
191{
192 [actions_[0] stop];
193 [actions_[1] stop];
194 [super stop];
195}
196
197-(void) update: (ccTime) t
198{
199 int found = 0;
200 ccTime new_t = 0.0f;
201
202 if( t >= split_ ) {
203 found = 1;
204 if ( split_ == 1 )
205 new_t = 1;
206 else
207 new_t = (t-split_) / (1 - split_ );
208 } else {
209 found = 0;
210 if( split_ != 0 )
211 new_t = t / split_;
212 else
213 new_t = 1;
214 }
215
216 if (last_ == -1 && found==1) {
217 [actions_[0] startWithTarget:target_];
218 [actions_[0] update:1.0f];
219 [actions_[0] stop];
220 }
221
222 if (last_ != found ) {
223 if( last_ != -1 ) {
224 [actions_[last_] update: 1.0f];
225 [actions_[last_] stop];
226 }
227 [actions_[found] startWithTarget:target_];
228 }
229 [actions_[found] update: new_t];
230 last_ = found;
231}
232
233- (CCActionInterval *) reverse
234{
235 return [[self class] actionOne: [actions_[1] reverse] two: [actions_[0] reverse ] ];
236}
237@end
238
239//
240// Repeat
241//
242#pragma mark -
243#pragma mark CCRepeat
244@implementation CCRepeat
245@synthesize innerAction=innerAction_;
246
247+(id) actionWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times
248{
249 return [[[self alloc] initWithAction:action times:times] autorelease];
250}
251
252-(id) initWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times
253{
254 ccTime d = [action duration] * times;
255
256 if( (self=[super initWithDuration: d ]) ) {
257 times_ = times;
258 self.innerAction = action;
259
260 total_ = 0;
261 }
262 return self;
263}
264
265-(id) copyWithZone: (NSZone*) zone
266{
267 CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[innerAction_ copy] autorelease] times:times_];
268 return copy;
269}
270
271-(void) dealloc
272{
273 [innerAction_ release];
274 [super dealloc];
275}
276
277-(void) startWithTarget:(id)aTarget
278{
279 total_ = 0;
280 [super startWithTarget:aTarget];
281 [innerAction_ startWithTarget:aTarget];
282}
283
284-(void) stop
285{
286 [innerAction_ stop];
287 [super stop];
288}
289
290
291// issue #80. Instead of hooking step:, hook update: since it can be called by any
292// container action like Repeat, Sequence, AccelDeccel, etc..
293-(void) update:(ccTime) dt
294{
295 ccTime t = dt * times_;
296 if( t > total_+1 ) {
297 [innerAction_ update:1.0f];
298 total_++;
299 [innerAction_ stop];
300 [innerAction_ startWithTarget:target_];
301
302 // repeat is over ?
303 if( total_== times_ )
304 // so, set it in the original position
305 [innerAction_ update:0];
306 else {
307 // no ? start next repeat with the right update
308 // to prevent jerk (issue #390)
309 [innerAction_ update: t-total_];
310 }
311
312 } else {
313
314 float r = fmodf(t, 1.0f);
315
316 // fix last repeat position
317 // else it could be 0.
318 if( dt== 1.0f) {
319 r = 1.0f;
320 total_++; // this is the added line
321 }
322 [innerAction_ update: MIN(r,1)];
323 }
324}
325
326-(BOOL) isDone
327{
328 return ( total_ == times_ );
329}
330
331- (CCActionInterval *) reverse
332{
333 return [[self class] actionWithAction:[innerAction_ reverse] times:times_];
334}
335@end
336
337//
338// Spawn
339//
340#pragma mark -
341#pragma mark Spawn
342
343@implementation CCSpawn
344+(id) actions: (CCFiniteTimeAction*) action1, ...
345{
346 va_list params;
347 va_start(params,action1);
348
349 CCFiniteTimeAction *now;
350 CCFiniteTimeAction *prev = action1;
351
352 while( action1 ) {
353 now = va_arg(params,CCFiniteTimeAction*);
354 if ( now )
355 prev = [self actionOne: prev two: now];
356 else
357 break;
358 }
359 va_end(params);
360 return prev;
361}
362
363+(id) actionsWithArray: (NSArray*) actions
364{
365 CCFiniteTimeAction *prev = [actions objectAtIndex:0];
366
367 for (NSUInteger i = 1; i < [actions count]; i++)
368 prev = [self actionOne:prev two:[actions objectAtIndex:i]];
369
370 return prev;
371}
372
373+(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
374{
375 return [[[self alloc] initOne:one two:two ] autorelease];
376}
377
378-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
379{
380 NSAssert( one!=nil && two!=nil, @"Spawn: arguments must be non-nil");
381 NSAssert( one!=one_ && one!=two_, @"Spawn: reinit using same parameters is not supported");
382 NSAssert( two!=two_ && two!=one_, @"Spawn: reinit using same parameters is not supported");
383
384 ccTime d1 = [one duration];
385 ccTime d2 = [two duration];
386
387 if( (self=[super initWithDuration: MAX(d1,d2)] ) ) {
388
389 // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_
390 [one_ release];
391 [two_ release];
392
393 one_ = one;
394 two_ = two;
395
396 if( d1 > d2 )
397 two_ = [CCSequence actionOne:two two:[CCDelayTime actionWithDuration: (d1-d2)] ];
398 else if( d1 < d2)
399 one_ = [CCSequence actionOne:one two: [CCDelayTime actionWithDuration: (d2-d1)] ];
400
401 [one_ retain];
402 [two_ retain];
403 }
404 return self;
405}
406
407-(id) copyWithZone: (NSZone*) zone
408{
409 CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[one_ copy] autorelease] two: [[two_ copy] autorelease] ];
410 return copy;
411}
412
413-(void) dealloc
414{
415 [one_ release];
416 [two_ release];
417 [super dealloc];
418}
419
420-(void) startWithTarget:(id)aTarget
421{
422 [super startWithTarget:aTarget];
423 [one_ startWithTarget:target_];
424 [two_ startWithTarget:target_];
425}
426
427-(void) stop
428{
429 [one_ stop];
430 [two_ stop];
431 [super stop];
432}
433
434-(void) update: (ccTime) t
435{
436 [one_ update:t];
437 [two_ update:t];
438}
439
440- (CCActionInterval *) reverse
441{
442 return [[self class] actionOne: [one_ reverse] two: [two_ reverse ] ];
443}
444@end
445
446//
447// RotateTo
448//
449#pragma mark -
450#pragma mark RotateTo
451
452@implementation CCRotateTo
453+(id) actionWithDuration: (ccTime) t angle:(float) a
454{
455 return [[[self alloc] initWithDuration:t angle:a ] autorelease];
456}
457
458-(id) initWithDuration: (ccTime) t angle:(float) a
459{
460 if( (self=[super initWithDuration: t]) )
461 dstAngle_ = a;
462
463 return self;
464}
465
466-(id) copyWithZone: (NSZone*) zone
467{
468 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angle:dstAngle_];
469 return copy;
470}
471
472-(void) startWithTarget:(CCNode *)aTarget
473{
474 [super startWithTarget:aTarget];
475
476 startAngle_ = [target_ rotation];
477 if (startAngle_ > 0)
478 startAngle_ = fmodf(startAngle_, 360.0f);
479 else
480 startAngle_ = fmodf(startAngle_, -360.0f);
481
482 diffAngle_ =dstAngle_ - startAngle_;
483 if (diffAngle_ > 180)
484 diffAngle_ -= 360;
485 if (diffAngle_ < -180)
486 diffAngle_ += 360;
487}
488-(void) update: (ccTime) t
489{
490 [target_ setRotation: startAngle_ + diffAngle_ * t];
491}
492@end
493
494
495//
496// RotateBy
497//
498#pragma mark -
499#pragma mark RotateBy
500
501@implementation CCRotateBy
502+(id) actionWithDuration: (ccTime) t angle:(float) a
503{
504 return [[[self alloc] initWithDuration:t angle:a ] autorelease];
505}
506
507-(id) initWithDuration: (ccTime) t angle:(float) a
508{
509 if( (self=[super initWithDuration: t]) )
510 angle_ = a;
511
512 return self;
513}
514
515-(id) copyWithZone: (NSZone*) zone
516{
517 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angle: angle_];
518 return copy;
519}
520
521-(void) startWithTarget:(id)aTarget
522{
523 [super startWithTarget:aTarget];
524 startAngle_ = [target_ rotation];
525}
526
527-(void) update: (ccTime) t
528{
529 // XXX: shall I add % 360
530 [target_ setRotation: (startAngle_ +angle_ * t )];
531}
532
533-(CCActionInterval*) reverse
534{
535 return [[self class] actionWithDuration:duration_ angle:-angle_];
536}
537
538@end
539
540//
541// MoveTo
542//
543#pragma mark -
544#pragma mark MoveTo
545
546@implementation CCMoveTo
547+(id) actionWithDuration: (ccTime) t position: (CGPoint) p
548{
549 return [[[self alloc] initWithDuration:t position:p ] autorelease];
550}
551
552-(id) initWithDuration: (ccTime) t position: (CGPoint) p
553{
554 if( (self=[super initWithDuration: t]) )
555 endPosition_ = p;
556
557 return self;
558}
559
560-(id) copyWithZone: (NSZone*) zone
561{
562 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: endPosition_];
563 return copy;
564}
565
566-(void) startWithTarget:(CCNode *)aTarget
567{
568 [super startWithTarget:aTarget];
569 startPosition_ = [(CCNode*)target_ position];
570 delta_ = ccpSub( endPosition_, startPosition_ );
571}
572
573-(void) update: (ccTime) t
574{
575 [target_ setPosition: ccp( (startPosition_.x + delta_.x * t ), (startPosition_.y + delta_.y * t ) )];
576}
577@end
578
579//
580// MoveBy
581//
582#pragma mark -
583#pragma mark MoveBy
584
585@implementation CCMoveBy
586+(id) actionWithDuration: (ccTime) t position: (CGPoint) p
587{
588 return [[[self alloc] initWithDuration:t position:p ] autorelease];
589}
590
591-(id) initWithDuration: (ccTime) t position: (CGPoint) p
592{
593 if( (self=[super initWithDuration: t]) )
594 delta_ = p;
595
596 return self;
597}
598
599-(id) copyWithZone: (NSZone*) zone
600{
601 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta_];
602 return copy;
603}
604
605-(void) startWithTarget:(CCNode *)aTarget
606{
607 CGPoint dTmp = delta_;
608 [super startWithTarget:aTarget];
609 delta_ = dTmp;
610}
611
612-(CCActionInterval*) reverse
613{
614 return [[self class] actionWithDuration:duration_ position:ccp( -delta_.x, -delta_.y)];
615}
616@end
617
618
619//
620// SkewTo
621//
622#pragma mark -
623#pragma mark SkewTo
624
625@implementation CCSkewTo
626+(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
627{
628 return [[[self alloc] initWithDuration: t skewX:sx skewY:sy] autorelease];
629}
630
631-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
632{
633 if( (self=[super initWithDuration:t]) ) {
634 endSkewX_ = sx;
635 endSkewY_ = sy;
636 }
637 return self;
638}
639
640-(id) copyWithZone: (NSZone*) zone
641{
642 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] skewX:endSkewX_ skewY:endSkewY_];
643 return copy;
644}
645
646-(void) startWithTarget:(CCNode *)aTarget
647{
648 [super startWithTarget:aTarget];
649
650 startSkewX_ = [target_ skewX];
651
652 if (startSkewX_ > 0)
653 startSkewX_ = fmodf(startSkewX_, 180.0f);
654 else
655 startSkewX_ = fmodf(startSkewX_, -180.0f);
656
657 deltaX_ = endSkewX_ - startSkewX_;
658
659 if ( deltaX_ > 180 ) {
660 deltaX_ -= 360;
661 }
662 if ( deltaX_ < -180 ) {
663 deltaX_ += 360;
664 }
665
666 startSkewY_ = [target_ skewY];
667
668 if (startSkewY_ > 0)
669 startSkewY_ = fmodf(startSkewY_, 360.0f);
670 else
671 startSkewY_ = fmodf(startSkewY_, -360.0f);
672
673 deltaY_ = endSkewY_ - startSkewY_;
674
675 if ( deltaY_ > 180 ) {
676 deltaY_ -= 360;
677 }
678 if ( deltaY_ < -180 ) {
679 deltaY_ += 360;
680 }
681}
682
683-(void) update: (ccTime) t
684{
685 [target_ setSkewX: (startSkewX_ + deltaX_ * t ) ];
686 [target_ setSkewY: (startSkewY_ + deltaY_ * t ) ];
687}
688
689@end
690
691//
692// CCSkewBy
693//
694@implementation CCSkewBy
695
696-(id) initWithDuration:(ccTime)t skewX:(float)deltaSkewX skewY:(float)deltaSkewY
697{
698 if( (self=[super initWithDuration:t skewX:deltaSkewX skewY:deltaSkewY]) ) {
699 skewX_ = deltaSkewX;
700 skewY_ = deltaSkewY;
701 }
702 return self;
703}
704
705-(void) startWithTarget:(CCNode *)aTarget
706{
707 [super startWithTarget:aTarget];
708 deltaX_ = skewX_;
709 deltaY_ = skewY_;
710 endSkewX_ = startSkewX_ + deltaX_;
711 endSkewY_ = startSkewY_ + deltaY_;
712}
713
714-(CCActionInterval*) reverse
715{
716 return [[self class] actionWithDuration:duration_ skewX:-skewX_ skewY:-skewY_];
717}
718@end
719
720
721//
722// JumpBy
723//
724#pragma mark -
725#pragma mark JumpBy
726
727@implementation CCJumpBy
728+(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j
729{
730 return [[[self alloc] initWithDuration: t position: pos height: h jumps:j] autorelease];
731}
732
733-(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j
734{
735 if( (self=[super initWithDuration:t]) ) {
736 delta_ = pos;
737 height_ = h;
738 jumps_ = j;
739 }
740 return self;
741}
742
743-(id) copyWithZone: (NSZone*) zone
744{
745 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] position:delta_ height:height_ jumps:jumps_];
746 return copy;
747}
748
749-(void) startWithTarget:(id)aTarget
750{
751 [super startWithTarget:aTarget];
752 startPosition_ = [(CCNode*)target_ position];
753}
754
755-(void) update: (ccTime) t
756{
757 // Sin jump. Less realistic
758// ccTime y = height * fabsf( sinf(t * (CGFloat)M_PI * jumps ) );
759// y += delta.y * t;
760// ccTime x = delta.x * t;
761// [target setPosition: ccp( startPosition.x + x, startPosition.y + y )];
762
763 // parabolic jump (since v0.8.2)
764 ccTime frac = fmodf( t * jumps_, 1.0f );
765 ccTime y = height_ * 4 * frac * (1 - frac);
766 y += delta_.y * t;
767 ccTime x = delta_.x * t;
768 [target_ setPosition: ccp( startPosition_.x + x, startPosition_.y + y )];
769
770}
771
772-(CCActionInterval*) reverse
773{
774 return [[self class] actionWithDuration:duration_ position: ccp(-delta_.x,-delta_.y) height:height_ jumps:jumps_];
775}
776@end
777
778//
779// JumpTo
780//
781#pragma mark -
782#pragma mark JumpTo
783
784@implementation CCJumpTo
785-(void) startWithTarget:(CCNode *)aTarget
786{
787 [super startWithTarget:aTarget];
788 delta_ = ccp( delta_.x - startPosition_.x, delta_.y - startPosition_.y );
789}
790@end
791
792
793#pragma mark -
794#pragma mark BezierBy
795
796// Bezier cubic formula:
797// ((1 - t) + t)3 = 1
798// Expands to…
799// (1 - t)3 + 3t(1-t)2 + 3t2(1 - t) + t3 = 1
800static inline float bezierat( float a, float b, float c, float d, ccTime t )
801{
802 return (powf(1-t,3) * a +
803 3*t*(powf(1-t,2))*b +
804 3*powf(t,2)*(1-t)*c +
805 powf(t,3)*d );
806}
807
808//
809// BezierBy
810//
811@implementation CCBezierBy
812+(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c
813{
814 return [[[self alloc] initWithDuration:t bezier:c ] autorelease];
815}
816
817-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c
818{
819 if( (self=[super initWithDuration: t]) ) {
820 config_ = c;
821 }
822 return self;
823}
824
825-(id) copyWithZone: (NSZone*) zone
826{
827 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] bezier:config_];
828 return copy;
829}
830
831-(void) startWithTarget:(id)aTarget
832{
833 [super startWithTarget:aTarget];
834 startPosition_ = [(CCNode*)target_ position];
835}
836
837-(void) update: (ccTime) t
838{
839 float xa = 0;
840 float xb = config_.controlPoint_1.x;
841 float xc = config_.controlPoint_2.x;
842 float xd = config_.endPosition.x;
843
844 float ya = 0;
845 float yb = config_.controlPoint_1.y;
846 float yc = config_.controlPoint_2.y;
847 float yd = config_.endPosition.y;
848
849 float x = bezierat(xa, xb, xc, xd, t);
850 float y = bezierat(ya, yb, yc, yd, t);
851 [target_ setPosition: ccpAdd( startPosition_, ccp(x,y))];
852}
853
854- (CCActionInterval*) reverse
855{
856 ccBezierConfig r;
857
858 r.endPosition = ccpNeg(config_.endPosition);
859 r.controlPoint_1 = ccpAdd(config_.controlPoint_2, ccpNeg(config_.endPosition));
860 r.controlPoint_2 = ccpAdd(config_.controlPoint_1, ccpNeg(config_.endPosition));
861
862 CCBezierBy *action = [[self class] actionWithDuration:[self duration] bezier:r];
863 return action;
864}
865@end
866
867//
868// BezierTo
869//
870#pragma mark -
871#pragma mark BezierTo
872@implementation CCBezierTo
873-(void) startWithTarget:(id)aTarget
874{
875 [super startWithTarget:aTarget];
876 config_.controlPoint_1 = ccpSub(config_.controlPoint_1, startPosition_);
877 config_.controlPoint_2 = ccpSub(config_.controlPoint_2, startPosition_);
878 config_.endPosition = ccpSub(config_.endPosition, startPosition_);
879}
880@end
881
882
883//
884// ScaleTo
885//
886#pragma mark -
887#pragma mark ScaleTo
888@implementation CCScaleTo
889+(id) actionWithDuration: (ccTime) t scale:(float) s
890{
891 return [[[self alloc] initWithDuration: t scale:s] autorelease];
892}
893
894-(id) initWithDuration: (ccTime) t scale:(float) s
895{
896 if( (self=[super initWithDuration: t]) ) {
897 endScaleX_ = s;
898 endScaleY_ = s;
899 }
900 return self;
901}
902
903+(id) actionWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy
904{
905 return [[[self alloc] initWithDuration: t scaleX:sx scaleY:sy] autorelease];
906}
907
908-(id) initWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy
909{
910 if( (self=[super initWithDuration: t]) ) {
911 endScaleX_ = sx;
912 endScaleY_ = sy;
913 }
914 return self;
915}
916
917-(id) copyWithZone: (NSZone*) zone
918{
919 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] scaleX:endScaleX_ scaleY:endScaleY_];
920 return copy;
921}
922
923-(void) startWithTarget:(CCNode *)aTarget
924{
925 [super startWithTarget:aTarget];
926 startScaleX_ = [target_ scaleX];
927 startScaleY_ = [target_ scaleY];
928 deltaX_ = endScaleX_ - startScaleX_;
929 deltaY_ = endScaleY_ - startScaleY_;
930}
931
932-(void) update: (ccTime) t
933{
934 [target_ setScaleX: (startScaleX_ + deltaX_ * t ) ];
935 [target_ setScaleY: (startScaleY_ + deltaY_ * t ) ];
936}
937@end
938
939//
940// ScaleBy
941//
942#pragma mark -
943#pragma mark ScaleBy
944@implementation CCScaleBy
945-(void) startWithTarget:(CCNode *)aTarget
946{
947 [super startWithTarget:aTarget];
948 deltaX_ = startScaleX_ * endScaleX_ - startScaleX_;
949 deltaY_ = startScaleY_ * endScaleY_ - startScaleY_;
950}
951
952-(CCActionInterval*) reverse
953{
954 return [[self class] actionWithDuration:duration_ scaleX:1/endScaleX_ scaleY:1/endScaleY_];
955}
956@end
957
958//
959// Blink
960//
961#pragma mark -
962#pragma mark Blink
963@implementation CCBlink
964+(id) actionWithDuration: (ccTime) t blinks: (NSUInteger) b
965{
966 return [[[ self alloc] initWithDuration: t blinks: b] autorelease];
967}
968
969-(id) initWithDuration: (ccTime) t blinks: (NSUInteger) b
970{
971 if( (self=[super initWithDuration: t] ) )
972 times_ = b;
973
974 return self;
975}
976
977-(id) copyWithZone: (NSZone*) zone
978{
979 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: times_];
980 return copy;
981}
982
983-(void) update: (ccTime) t
984{
985 if( ! [self isDone] ) {
986 ccTime slice = 1.0f / times_;
987 ccTime m = fmodf(t, slice);
988 [target_ setVisible: (m > slice/2) ? YES : NO];
989 }
990}
991
992-(CCActionInterval*) reverse
993{
994 // return 'self'
995 return [[self class] actionWithDuration:duration_ blinks: times_];
996}
997@end
998
999//
1000// FadeIn
1001//
1002#pragma mark -
1003#pragma mark FadeIn
1004@implementation CCFadeIn
1005-(void) update: (ccTime) t
1006{
1007 [(id<CCRGBAProtocol>) target_ setOpacity: 255 *t];
1008}
1009
1010-(CCActionInterval*) reverse
1011{
1012 return [CCFadeOut actionWithDuration:duration_];
1013}
1014@end
1015
1016//
1017// FadeOut
1018//
1019#pragma mark -
1020#pragma mark FadeOut
1021@implementation CCFadeOut
1022-(void) update: (ccTime) t
1023{
1024 [(id<CCRGBAProtocol>) target_ setOpacity: 255 *(1-t)];
1025}
1026
1027-(CCActionInterval*) reverse
1028{
1029 return [CCFadeIn actionWithDuration:duration_];
1030}
1031@end
1032
1033//
1034// FadeTo
1035//
1036#pragma mark -
1037#pragma mark FadeTo
1038@implementation CCFadeTo
1039+(id) actionWithDuration: (ccTime) t opacity: (GLubyte) o
1040{
1041 return [[[ self alloc] initWithDuration: t opacity: o] autorelease];
1042}
1043
1044-(id) initWithDuration: (ccTime) t opacity: (GLubyte) o
1045{
1046 if( (self=[super initWithDuration: t] ) )
1047 toOpacity_ = o;
1048
1049 return self;
1050}
1051
1052-(id) copyWithZone: (NSZone*) zone
1053{
1054 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] opacity:toOpacity_];
1055 return copy;
1056}
1057
1058-(void) startWithTarget:(CCNode *)aTarget
1059{
1060 [super startWithTarget:aTarget];
1061 fromOpacity_ = [(id<CCRGBAProtocol>)target_ opacity];
1062}
1063
1064-(void) update: (ccTime) t
1065{
1066 [(id<CCRGBAProtocol>)target_ setOpacity:fromOpacity_ + ( toOpacity_ - fromOpacity_ ) * t];
1067}
1068@end
1069
1070//
1071// TintTo
1072//
1073#pragma mark -
1074#pragma mark TintTo
1075@implementation CCTintTo
1076+(id) actionWithDuration:(ccTime)t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b
1077{
1078 return [[(CCTintTo*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease];
1079}
1080
1081-(id) initWithDuration: (ccTime) t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b
1082{
1083 if( (self=[super initWithDuration:t] ) )
1084 to_ = ccc3(r,g,b);
1085
1086 return self;
1087}
1088
1089-(id) copyWithZone: (NSZone*) zone
1090{
1091 CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration:[self duration] red:to_.r green:to_.g blue:to_.b];
1092 return copy;
1093}
1094
1095-(void) startWithTarget:(id)aTarget
1096{
1097 [super startWithTarget:aTarget];
1098
1099 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1100 from_ = [tn color];
1101}
1102
1103-(void) update: (ccTime) t
1104{
1105 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1106 [tn setColor:ccc3(from_.r + (to_.r - from_.r) * t, from_.g + (to_.g - from_.g) * t, from_.b + (to_.b - from_.b) * t)];
1107}
1108@end
1109
1110//
1111// TintBy
1112//
1113#pragma mark -
1114#pragma mark TintBy
1115@implementation CCTintBy
1116+(id) actionWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b
1117{
1118 return [[(CCTintBy*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease];
1119}
1120
1121-(id) initWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b
1122{
1123 if( (self=[super initWithDuration: t] ) ) {
1124 deltaR_ = r;
1125 deltaG_ = g;
1126 deltaB_ = b;
1127 }
1128 return self;
1129}
1130
1131-(id) copyWithZone: (NSZone*) zone
1132{
1133 return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:deltaR_ green:deltaG_ blue:deltaB_];
1134}
1135
1136-(void) startWithTarget:(id)aTarget
1137{
1138 [super startWithTarget:aTarget];
1139
1140 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1141 ccColor3B color = [tn color];
1142 fromR_ = color.r;
1143 fromG_ = color.g;
1144 fromB_ = color.b;
1145}
1146
1147-(void) update: (ccTime) t
1148{
1149 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1150 [tn setColor:ccc3( fromR_ + deltaR_ * t, fromG_ + deltaG_ * t, fromB_ + deltaB_ * t)];
1151}
1152
1153- (CCActionInterval*) reverse
1154{
1155 return [CCTintBy actionWithDuration:duration_ red:-deltaR_ green:-deltaG_ blue:-deltaB_];
1156}
1157@end
1158
1159//
1160// DelayTime
1161//
1162#pragma mark -
1163#pragma mark DelayTime
1164@implementation CCDelayTime
1165-(void) update: (ccTime) t
1166{
1167 return;
1168}
1169
1170-(id)reverse
1171{
1172 return [[self class] actionWithDuration:duration_];
1173}
1174@end
1175
1176//
1177// ReverseTime
1178//
1179#pragma mark -
1180#pragma mark ReverseTime
1181@implementation CCReverseTime
1182+(id) actionWithAction: (CCFiniteTimeAction*) action
1183{
1184 // casting to prevent warnings
1185 CCReverseTime *a = [super alloc];
1186 return [[a initWithAction:action] autorelease];
1187}
1188
1189-(id) initWithAction: (CCFiniteTimeAction*) action
1190{
1191 NSAssert(action != nil, @"CCReverseTime: action should not be nil");
1192 NSAssert(action != other_, @"CCReverseTime: re-init doesn't support using the same arguments");
1193
1194 if( (self=[super initWithDuration: [action duration]]) ) {
1195 // Don't leak if action is reused
1196 [other_ release];
1197 other_ = [action retain];
1198 }
1199
1200 return self;
1201}
1202
1203-(id) copyWithZone: (NSZone*) zone
1204{
1205 return [[[self class] allocWithZone: zone] initWithAction:[[other_ copy] autorelease] ];
1206}
1207
1208-(void) dealloc
1209{
1210 [other_ release];
1211 [super dealloc];
1212}
1213
1214-(void) startWithTarget:(id)aTarget
1215{
1216 [super startWithTarget:aTarget];
1217 [other_ startWithTarget:target_];
1218}
1219
1220-(void) stop
1221{
1222 [other_ stop];
1223 [super stop];
1224}
1225
1226-(void) update:(ccTime)t
1227{
1228 [other_ update:1-t];
1229}
1230
1231-(CCActionInterval*) reverse
1232{
1233 return [[other_ copy] autorelease];
1234}
1235@end
1236
1237//
1238// Animate
1239//
1240
1241#pragma mark -
1242#pragma mark Animate
1243@implementation CCAnimate
1244
1245@synthesize animation = animation_;
1246
1247+(id) actionWithAnimation: (CCAnimation*)anim
1248{
1249 return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:YES] autorelease];
1250}
1251
1252+(id) actionWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b
1253{
1254 return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:b] autorelease];
1255}
1256
1257+(id) actionWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b
1258{
1259 return [[[self alloc] initWithDuration:duration animation:anim restoreOriginalFrame:b] autorelease];
1260}
1261
1262-(id) initWithAnimation: (CCAnimation*)anim
1263{
1264 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1265 return [self initWithAnimation:anim restoreOriginalFrame:YES];
1266}
1267
1268-(id) initWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b
1269{
1270 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1271
1272 if( (self=[super initWithDuration: [[anim frames] count] * [anim delay]]) ) {
1273
1274 restoreOriginalFrame_ = b;
1275 self.animation = anim;
1276 origFrame_ = nil;
1277 }
1278 return self;
1279}
1280
1281-(id) initWithDuration:(ccTime)aDuration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b
1282{
1283 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1284
1285 if( (self=[super initWithDuration:aDuration] ) ) {
1286
1287 restoreOriginalFrame_ = b;
1288 self.animation = anim;
1289 origFrame_ = nil;
1290 }
1291 return self;
1292}
1293
1294
1295-(id) copyWithZone: (NSZone*) zone
1296{
1297 return [[[self class] allocWithZone: zone] initWithDuration:duration_ animation:animation_ restoreOriginalFrame:restoreOriginalFrame_];
1298}
1299
1300-(void) dealloc
1301{
1302 [animation_ release];
1303 [origFrame_ release];
1304 [super dealloc];
1305}
1306
1307-(void) startWithTarget:(id)aTarget
1308{
1309 [super startWithTarget:aTarget];
1310 CCSprite *sprite = target_;
1311
1312 [origFrame_ release];
1313
1314 if( restoreOriginalFrame_ )
1315 origFrame_ = [[sprite displayedFrame] retain];
1316}
1317
1318-(void) stop
1319{
1320 if( restoreOriginalFrame_ ) {
1321 CCSprite *sprite = target_;
1322 [sprite setDisplayFrame:origFrame_];
1323 }
1324
1325 [super stop];
1326}
1327
1328-(void) update: (ccTime) t
1329{
1330 NSArray *frames = [animation_ frames];
1331 NSUInteger numberOfFrames = [frames count];
1332
1333 NSUInteger idx = t * numberOfFrames;
1334
1335 if( idx >= numberOfFrames )
1336 idx = numberOfFrames -1;
1337
1338 CCSprite *sprite = target_;
1339 if (! [sprite isFrameDisplayed: [frames objectAtIndex: idx]] )
1340 [sprite setDisplayFrame: [frames objectAtIndex:idx]];
1341}
1342
1343- (CCActionInterval *) reverse
1344{
1345 NSArray *oldArray = [animation_ frames];
1346 NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[oldArray count]];
1347 NSEnumerator *enumerator = [oldArray reverseObjectEnumerator];
1348 for (id element in enumerator)
1349 [newArray addObject:[[element copy] autorelease]];
1350
1351 CCAnimation *newAnim = [CCAnimation animationWithFrames:newArray delay:animation_.delay];
1352 return [[self class] actionWithDuration:duration_ animation:newAnim restoreOriginalFrame:restoreOriginalFrame_];
1353}
1354
1355@end
diff --git a/libs/cocos2d/CCActionManager.h b/libs/cocos2d/CCActionManager.h new file mode 100755 index 0000000..0eeda91 --- /dev/null +++ b/libs/cocos2d/CCActionManager.h
@@ -0,0 +1,111 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30#import "CCAction.h"
31#import "Support/ccCArray.h"
32#import "Support/uthash.h"
33
34typedef struct _hashElement
35{
36 struct ccArray *actions;
37 id target;
38 NSUInteger actionIndex;
39 CCAction *currentAction;
40 BOOL currentActionSalvaged;
41 BOOL paused;
42 UT_hash_handle hh;
43} tHashElement;
44
45
46/** CCActionManager is a singleton that manages all the actions.
47 Normally you won't need to use this singleton directly. 99% of the cases you will use the CCNode interface,
48 which uses this singleton.
49 But there are some cases where you might need to use this singleton.
50 Examples:
51 - When you want to run an action where the target is different from a CCNode.
52 - When you want to pause / resume the actions
53
54 @since v0.8
55 */
56@interface CCActionManager : NSObject
57{
58 tHashElement *targets;
59 tHashElement *currentTarget;
60 BOOL currentTargetSalvaged;
61}
62
63/** returns a shared instance of the CCActionManager */
64+ (CCActionManager *)sharedManager;
65
66/** purges the shared action manager. It releases the retained instance.
67 @since v0.99.0
68 */
69+(void)purgeSharedManager;
70
71// actions
72
73/** Adds an action with a target.
74 If the target is already present, then the action will be added to the existing target.
75 If the target is not present, a new instance of this target will be created either paused or paused, and the action will be added to the newly created target.
76 When the target is paused, the queued actions won't be 'ticked'.
77 */
78-(void) addAction: (CCAction*) action target:(id)target paused:(BOOL)paused;
79/** Removes all actions from all the targers.
80 */
81-(void) removeAllActions;
82
83/** Removes all actions from a certain target.
84 All the actions that belongs to the target will be removed.
85 */
86-(void) removeAllActionsFromTarget:(id)target;
87/** Removes an action given an action reference.
88 */
89-(void) removeAction: (CCAction*) action;
90/** Removes an action given its tag and the target */
91-(void) removeActionByTag:(NSInteger)tag target:(id)target;
92/** Gets an action given its tag an a target
93 @return the Action the with the given tag
94 */
95-(CCAction*) getActionByTag:(NSInteger) tag target:(id)target;
96/** Returns the numbers of actions that are running in a certain target
97 * Composable actions are counted as 1 action. Example:
98 * If you are running 1 Sequence of 7 actions, it will return 1.
99 * If you are running 7 Sequences of 2 actions, it will return 7.
100 */
101-(NSUInteger) numberOfRunningActionsInTarget:(id)target;
102
103/** Pauses the target: all running actions and newly added actions will be paused.
104 */
105-(void) pauseTarget:(id)target;
106/** Resumes the target. All queued actions will be resumed.
107 */
108-(void) resumeTarget:(id)target;
109
110@end
111
diff --git a/libs/cocos2d/CCActionManager.m b/libs/cocos2d/CCActionManager.m new file mode 100755 index 0000000..8bdfbb7 --- /dev/null +++ b/libs/cocos2d/CCActionManager.m
@@ -0,0 +1,345 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30#import "CCActionManager.h"
31#import "CCScheduler.h"
32#import "ccMacros.h"
33
34
35//
36// singleton stuff
37//
38static CCActionManager *sharedManager_ = nil;
39
40@interface CCActionManager (Private)
41-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element;
42-(void) deleteHashElement:(tHashElement*)element;
43-(void) actionAllocWithHashElement:(tHashElement*)element;
44@end
45
46
47@implementation CCActionManager
48
49#pragma mark ActionManager - init
50+ (CCActionManager *)sharedManager
51{
52 if (!sharedManager_)
53 sharedManager_ = [[self alloc] init];
54
55 return sharedManager_;
56}
57
58+(id)alloc
59{
60 NSAssert(sharedManager_ == nil, @"Attempted to allocate a second instance of a singleton.");
61 return [super alloc];
62}
63
64+(void)purgeSharedManager
65{
66 [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
67 [sharedManager_ release];
68 sharedManager_ = nil;
69}
70
71-(id) init
72{
73 if ((self=[super init]) ) {
74 [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0 paused:NO];
75 targets = NULL;
76 }
77
78 return self;
79}
80
81- (void) dealloc
82{
83 CCLOGINFO( @"cocos2d: deallocing %@", self);
84
85 [self removeAllActions];
86
87 sharedManager_ = nil;
88
89 [super dealloc];
90}
91
92#pragma mark ActionManager - Private
93
94-(void) deleteHashElement:(tHashElement*)element
95{
96 ccArrayFree(element->actions);
97 HASH_DEL(targets, element);
98// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target);
99 [element->target release];
100 free(element);
101}
102
103-(void) actionAllocWithHashElement:(tHashElement*)element
104{
105 // 4 actions per Node by default
106 if( element->actions == nil )
107 element->actions = ccArrayNew(4);
108 else if( element->actions->num == element->actions->max )
109 ccArrayDoubleCapacity(element->actions);
110}
111
112-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element
113{
114 id action = element->actions->arr[index];
115
116 if( action == element->currentAction && !element->currentActionSalvaged ) {
117 [element->currentAction retain];
118 element->currentActionSalvaged = YES;
119 }
120
121 ccArrayRemoveObjectAtIndex(element->actions, index);
122
123 // update actionIndex in case we are in tick:, looping over the actions
124 if( element->actionIndex >= index )
125 element->actionIndex--;
126
127 if( element->actions->num == 0 ) {
128 if( currentTarget == element )
129 currentTargetSalvaged = YES;
130 else
131 [self deleteHashElement: element];
132 }
133}
134
135#pragma mark ActionManager - Pause / Resume
136
137-(void) pauseTarget:(id)target
138{
139 tHashElement *element = NULL;
140 HASH_FIND_INT(targets, &target, element);
141 if( element )
142 element->paused = YES;
143// else
144// CCLOG(@"cocos2d: pauseAllActions: Target not found");
145}
146
147-(void) resumeTarget:(id)target
148{
149 tHashElement *element = NULL;
150 HASH_FIND_INT(targets, &target, element);
151 if( element )
152 element->paused = NO;
153// else
154// CCLOG(@"cocos2d: resumeAllActions: Target not found");
155}
156
157#pragma mark ActionManager - run
158
159-(void) addAction:(CCAction*)action target:(id)target paused:(BOOL)paused
160{
161 NSAssert( action != nil, @"Argument action must be non-nil");
162 NSAssert( target != nil, @"Argument target must be non-nil");
163
164 tHashElement *element = NULL;
165 HASH_FIND_INT(targets, &target, element);
166 if( ! element ) {
167 element = calloc( sizeof( *element ), 1 );
168 element->paused = paused;
169 element->target = [target retain];
170 HASH_ADD_INT(targets, target, element);
171// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target);
172
173 }
174
175 [self actionAllocWithHashElement:element];
176
177 NSAssert( !ccArrayContainsObject(element->actions, action), @"runAction: Action already running");
178 ccArrayAppendObject(element->actions, action);
179
180 [action startWithTarget:target];
181}
182
183#pragma mark ActionManager - remove
184
185-(void) removeAllActions
186{
187 for(tHashElement *element=targets; element != NULL; ) {
188 id target = element->target;
189 element = element->hh.next;
190 [self removeAllActionsFromTarget:target];
191 }
192}
193-(void) removeAllActionsFromTarget:(id)target
194{
195 // explicit nil handling
196 if( target == nil )
197 return;
198
199 tHashElement *element = NULL;
200 HASH_FIND_INT(targets, &target, element);
201 if( element ) {
202 if( ccArrayContainsObject(element->actions, element->currentAction) && !element->currentActionSalvaged ) {
203 [element->currentAction retain];
204 element->currentActionSalvaged = YES;
205 }
206 ccArrayRemoveAllObjects(element->actions);
207 if( currentTarget == element )
208 currentTargetSalvaged = YES;
209 else
210 [self deleteHashElement:element];
211 }
212// else {
213// CCLOG(@"cocos2d: removeAllActionsFromTarget: Target not found");
214// }
215}
216
217-(void) removeAction: (CCAction*) action
218{
219 // explicit nil handling
220 if (action == nil)
221 return;
222
223 tHashElement *element = NULL;
224 id target = [action originalTarget];
225 HASH_FIND_INT(targets, &target, element );
226 if( element ) {
227 NSUInteger i = ccArrayGetIndexOfObject(element->actions, action);
228 if( i != NSNotFound )
229 [self removeActionAtIndex:i hashElement:element];
230 }
231// else {
232// CCLOG(@"cocos2d: removeAction: Target not found");
233// }
234}
235
236-(void) removeActionByTag:(NSInteger)aTag target:(id)target
237{
238 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
239 NSAssert( target != nil, @"Target should be ! nil");
240
241 tHashElement *element = NULL;
242 HASH_FIND_INT(targets, &target, element);
243
244 if( element ) {
245 NSUInteger limit = element->actions->num;
246 for( NSUInteger i = 0; i < limit; i++) {
247 CCAction *a = element->actions->arr[i];
248
249 if( a.tag == aTag && [a originalTarget]==target) {
250 [self removeActionAtIndex:i hashElement:element];
251 break;
252 }
253 }
254
255 }
256}
257
258#pragma mark ActionManager - get
259
260-(CCAction*) getActionByTag:(NSInteger)aTag target:(id)target
261{
262 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
263
264 tHashElement *element = NULL;
265 HASH_FIND_INT(targets, &target, element);
266
267 if( element ) {
268 if( element->actions != nil ) {
269 NSUInteger limit = element->actions->num;
270 for( NSUInteger i = 0; i < limit; i++) {
271 CCAction *a = element->actions->arr[i];
272
273 if( a.tag == aTag )
274 return a;
275 }
276 }
277// CCLOG(@"cocos2d: getActionByTag: Action not found");
278 }
279// else {
280// CCLOG(@"cocos2d: getActionByTag: Target not found");
281// }
282 return nil;
283}
284
285-(NSUInteger) numberOfRunningActionsInTarget:(id) target
286{
287 tHashElement *element = NULL;
288 HASH_FIND_INT(targets, &target, element);
289 if( element )
290 return element->actions ? element->actions->num : 0;
291
292// CCLOG(@"cocos2d: numberOfRunningActionsInTarget: Target not found");
293 return 0;
294}
295
296#pragma mark ActionManager - main loop
297
298-(void) update: (ccTime) dt
299{
300 for(tHashElement *elt = targets; elt != NULL; ) {
301
302 currentTarget = elt;
303 currentTargetSalvaged = NO;
304
305 if( ! currentTarget->paused ) {
306
307 // The 'actions' ccArray may change while inside this loop.
308 for( currentTarget->actionIndex = 0; currentTarget->actionIndex < currentTarget->actions->num; currentTarget->actionIndex++) {
309 currentTarget->currentAction = currentTarget->actions->arr[currentTarget->actionIndex];
310 currentTarget->currentActionSalvaged = NO;
311
312 [currentTarget->currentAction step: dt];
313
314 if( currentTarget->currentActionSalvaged ) {
315 // The currentAction told the node to remove it. To prevent the action from
316 // accidentally deallocating itself before finishing its step, we retained
317 // it. Now that step is done, it's safe to release it.
318 [currentTarget->currentAction release];
319
320 } else if( [currentTarget->currentAction isDone] ) {
321 [currentTarget->currentAction stop];
322
323 CCAction *a = currentTarget->currentAction;
324 // Make currentAction nil to prevent removeAction from salvaging it.
325 currentTarget->currentAction = nil;
326 [self removeAction:a];
327 }
328
329 currentTarget->currentAction = nil;
330 }
331 }
332
333 // elt, at this moment, is still valid
334 // so it is safe to ask this here (issue #490)
335 elt = elt->hh.next;
336
337 // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
338 if( currentTargetSalvaged && currentTarget->actions->num == 0 )
339 [self deleteHashElement:currentTarget];
340 }
341
342 // issue #635
343 currentTarget = nil;
344}
345@end
diff --git a/libs/cocos2d/CCActionPageTurn3D.h b/libs/cocos2d/CCActionPageTurn3D.h new file mode 100755 index 0000000..39eb31d --- /dev/null +++ b/libs/cocos2d/CCActionPageTurn3D.h
@@ -0,0 +1,42 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionGrid3D.h"
28
29/**
30 * This action simulates a page turn from the bottom right hand corner of the screen
31 * It's not much use by itself but is used by the PageTurnTransition.
32 *
33 * Based on an original paper by L Hong et al.
34 * http://www.parc.com/publication/1638/turning-pages-of-3d-electronic-books.html
35 *
36 * @since v0.8.2
37 */
38@interface CCPageTurn3D : CCGrid3DAction
39{
40}
41
42@end
diff --git a/libs/cocos2d/CCActionPageTurn3D.m b/libs/cocos2d/CCActionPageTurn3D.m new file mode 100755 index 0000000..ee59500 --- /dev/null +++ b/libs/cocos2d/CCActionPageTurn3D.m
@@ -0,0 +1,86 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "CCActionPageTurn3D.h"
27
28@implementation CCPageTurn3D
29
30/*
31 * Update each tick
32 * Time is the percentage of the way through the duration
33 */
34-(void)update:(ccTime)time
35{
36 float tt = MAX( 0, time - 0.25f );
37 float deltaAy = ( tt * tt * 500);
38 float ay = -100 - deltaAy;
39
40 float deltaTheta = - (float) M_PI_2 * sqrtf( time) ;
41 float theta = /*0.01f*/ + (float) M_PI_2 +deltaTheta;
42
43 float sinTheta = sinf(theta);
44 float cosTheta = cosf(theta);
45
46 for( int i = 0; i <=gridSize_.x; i++ )
47 {
48 for( int j = 0; j <= gridSize_.y; j++ )
49 {
50 // Get original vertex
51 ccVertex3F p = [self originalVertex:ccg(i,j)];
52
53 float R = sqrtf(p.x*p.x + (p.y - ay) * (p.y - ay));
54 float r = R * sinTheta;
55 float alpha = asinf( p.x / R );
56 float beta = alpha / sinTheta;
57 float cosBeta = cosf( beta );
58
59 // If beta > PI then we've wrapped around the cone
60 // Reduce the radius to stop these points interfering with others
61 if( beta <= M_PI)
62 p.x = ( r * sinf(beta));
63 else
64 {
65 // Force X = 0 to stop wrapped
66 // points
67 p.x = 0;
68 }
69
70 p.y = ( R + ay - ( r*(1 - cosBeta)*sinTheta));
71
72 // We scale z here to avoid the animation being
73 // too much bigger than the screen due to perspectve transform
74 p.z = (r * ( 1 - cosBeta ) * cosTheta) / 7; // "100" didn't work for
75
76 // Stop z coord from dropping beneath underlying page in a transition
77 // issue #751
78 if( p.z<0.5f )
79 p.z = 0.5f;
80
81 // Set new coords
82 [self setVertex:ccg(i,j) vertex:p];
83 }
84 }
85}
86@end
diff --git a/libs/cocos2d/CCActionProgressTimer.h b/libs/cocos2d/CCActionProgressTimer.h new file mode 100755 index 0000000..500631b --- /dev/null +++ b/libs/cocos2d/CCActionProgressTimer.h
@@ -0,0 +1,59 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (C) 2010 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28#import "CCProgressTimer.h"
29#import "CCActionInterval.h"
30
31/**
32 Progress to percentage
33@since v0.99.1
34*/
35@interface CCProgressTo : CCActionInterval <NSCopying>
36{
37 float to_;
38 float from_;
39}
40/** Creates and initializes with a duration and a percent */
41+(id) actionWithDuration:(ccTime)duration percent:(float)percent;
42/** Initializes with a duration and a percent */
43-(id) initWithDuration:(ccTime)duration percent:(float)percent;
44@end
45
46/**
47 Progress from a percentage to another percentage
48 @since v0.99.1
49 */
50@interface CCProgressFromTo : CCActionInterval <NSCopying>
51{
52 float to_;
53 float from_;
54}
55/** Creates and initializes the action with a duration, a "from" percentage and a "to" percentage */
56+(id) actionWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage;
57/** Initializes the action with a duration, a "from" percentage and a "to" percentage */
58-(id) initWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage;
59@end
diff --git a/libs/cocos2d/CCActionProgressTimer.m b/libs/cocos2d/CCActionProgressTimer.m new file mode 100755 index 0000000..c242570 --- /dev/null +++ b/libs/cocos2d/CCActionProgressTimer.m
@@ -0,0 +1,103 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (C) 2010 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionProgressTimer.h"
28
29#define kProgressTimerCast CCProgressTimer*
30
31@implementation CCProgressTo
32+(id) actionWithDuration: (ccTime) t percent: (float) v
33{
34 return [[[ self alloc] initWithDuration: t percent: v] autorelease];
35}
36
37-(id) initWithDuration: (ccTime) t percent: (float) v
38{
39 if( (self=[super initWithDuration: t] ) )
40 to_ = v;
41
42 return self;
43}
44
45-(id) copyWithZone: (NSZone*) zone
46{
47 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:duration_ percent:to_];
48 return copy;
49}
50
51-(void) startWithTarget:(id) aTarget;
52{
53 [super startWithTarget:aTarget];
54 from_ = [(kProgressTimerCast)target_ percentage];
55
56 // XXX: Is this correct ?
57 // Adding it to support CCRepeat
58 if( from_ == 100)
59 from_ = 0;
60}
61
62-(void) update: (ccTime) t
63{
64 [(kProgressTimerCast)target_ setPercentage: from_ + ( to_ - from_ ) * t];
65}
66@end
67
68@implementation CCProgressFromTo
69+(id) actionWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage
70{
71 return [[[self alloc] initWithDuration: t from: fromPercentage to: toPercentage] autorelease];
72}
73
74-(id) initWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage
75{
76 if( (self=[super initWithDuration: t] ) ){
77 to_ = toPercentage;
78 from_ = fromPercentage;
79 }
80 return self;
81}
82
83-(id) copyWithZone: (NSZone*) zone
84{
85 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:duration_ from:from_ to:to_];
86 return copy;
87}
88
89- (CCActionInterval *) reverse
90{
91 return [[self class] actionWithDuration:duration_ from:to_ to:from_];
92}
93
94-(void) startWithTarget:(id) aTarget;
95{
96 [super startWithTarget:aTarget];
97}
98
99-(void) update: (ccTime) t
100{
101 [(kProgressTimerCast)target_ setPercentage: from_ + ( to_ - from_ ) * t];
102}
103@end
diff --git a/libs/cocos2d/CCActionTiledGrid.h b/libs/cocos2d/CCActionTiledGrid.h new file mode 100755 index 0000000..d66132d --- /dev/null +++ b/libs/cocos2d/CCActionTiledGrid.h
@@ -0,0 +1,211 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "CCActionGrid.h"
27
28/** CCShakyTiles3D action */
29@interface CCShakyTiles3D : CCTiledGrid3DAction
30{
31 int randrange;
32 BOOL shakeZ;
33}
34
35/** creates the action with a range, whether or not to shake Z vertices, a grid size, and duration */
36+(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d;
37/** initializes the action with a range, whether or not to shake Z vertices, a grid size, and duration */
38-(id)initWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d;
39
40@end
41
42////////////////////////////////////////////////////////////
43
44/** CCShatteredTiles3D action */
45@interface CCShatteredTiles3D : CCTiledGrid3DAction
46{
47 int randrange;
48 BOOL once;
49 BOOL shatterZ;
50}
51
52/** creates the action with a range, whether of not to shatter Z vertices, a grid size and duration */
53+(id)actionWithRange:(int)range shatterZ:(BOOL)shatterZ grid:(ccGridSize)gridSize duration:(ccTime)d;
54/** initializes the action with a range, whether or not to shatter Z vertices, a grid size and duration */
55-(id)initWithRange:(int)range shatterZ:(BOOL)shatterZ grid:(ccGridSize)gridSize duration:(ccTime)d;
56
57@end
58
59////////////////////////////////////////////////////////////
60
61/** CCShuffleTiles action
62 Shuffle the tiles in random order
63 */
64@interface CCShuffleTiles : CCTiledGrid3DAction
65{
66 int seed;
67 NSUInteger tilesCount;
68 int *tilesOrder;
69 void *tiles;
70}
71
72/** creates the action with a random seed, the grid size and the duration */
73+(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d;
74/** initializes the action with a random seed, the grid size and the duration */
75-(id)initWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d;
76
77@end
78
79////////////////////////////////////////////////////////////
80
81/** CCFadeOutTRTiles action
82 Fades out the tiles in a Top-Right direction
83 */
84@interface CCFadeOutTRTiles : CCTiledGrid3DAction
85{
86}
87@end
88
89////////////////////////////////////////////////////////////
90
91/** CCFadeOutBLTiles action.
92 Fades out the tiles in a Bottom-Left direction
93 */
94@interface CCFadeOutBLTiles : CCFadeOutTRTiles
95{
96}
97@end
98
99////////////////////////////////////////////////////////////
100
101/** CCFadeOutUpTiles action.
102 Fades out the tiles in upwards direction
103 */
104@interface CCFadeOutUpTiles : CCFadeOutTRTiles
105{
106}
107@end
108
109////////////////////////////////////////////////////////////
110
111/** CCFadeOutDownTiles action.
112 Fades out the tiles in downwards direction
113 */
114@interface CCFadeOutDownTiles : CCFadeOutUpTiles
115{
116}
117@end
118
119////////////////////////////////////////////////////////////
120
121/** CCTurnOffTiles action.
122 Turn off the files in random order
123 */
124@interface CCTurnOffTiles : CCTiledGrid3DAction
125{
126 int seed;
127 NSUInteger tilesCount;
128 int *tilesOrder;
129}
130
131/** creates the action with a random seed, the grid size and the duration */
132+(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d;
133/** initializes the action with a random seed, the grid size and the duration */
134-(id)initWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d;
135@end
136
137////////////////////////////////////////////////////////////
138
139/** CCWavesTiles3D action. */
140@interface CCWavesTiles3D : CCTiledGrid3DAction
141{
142 int waves;
143 float amplitude;
144 float amplitudeRate;
145}
146
147/** waves amplitude */
148@property (nonatomic,readwrite) float amplitude;
149/** waves amplitude rate */
150@property (nonatomic,readwrite) float amplitudeRate;
151
152/** creates the action with a number of waves, the waves amplitude, the grid size and the duration */
153+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
154/** initializes the action with a number of waves, the waves amplitude, the grid size and the duration */
155-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
156
157@end
158
159////////////////////////////////////////////////////////////
160
161/** CCJumpTiles3D action.
162 A sin function is executed to move the tiles across the Z axis
163 */
164@interface CCJumpTiles3D : CCTiledGrid3DAction
165{
166 int jumps;
167 float amplitude;
168 float amplitudeRate;
169}
170
171/** amplitude of the sin*/
172@property (nonatomic,readwrite) float amplitude;
173/** amplitude rate */
174@property (nonatomic,readwrite) float amplitudeRate;
175
176/** creates the action with the number of jumps, the sin amplitude, the grid size and the duration */
177+(id)actionWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
178/** initializes the action with the number of jumps, the sin amplitude, the grid size and the duration */
179-(id)initWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d;
180
181@end
182
183////////////////////////////////////////////////////////////
184
185/** CCSplitRows action */
186@interface CCSplitRows : CCTiledGrid3DAction
187{
188 int rows;
189 CGSize winSize;
190}
191/** creates the action with the number of rows to split and the duration */
192+(id)actionWithRows:(int)rows duration:(ccTime)duration;
193/** initializes the action with the number of rows to split and the duration */
194-(id)initWithRows:(int)rows duration:(ccTime)duration;
195
196@end
197
198////////////////////////////////////////////////////////////
199
200/** CCSplitCols action */
201@interface CCSplitCols : CCTiledGrid3DAction
202{
203 int cols;
204 CGSize winSize;
205}
206/** creates the action with the number of columns to split and the duration */
207+(id)actionWithCols:(int)cols duration:(ccTime)duration;
208/** initializes the action with the number of columns to split and the duration */
209-(id)initWithCols:(int)cols duration:(ccTime)duration;
210
211@end
diff --git a/libs/cocos2d/CCActionTiledGrid.m b/libs/cocos2d/CCActionTiledGrid.m new file mode 100755 index 0000000..75965ec --- /dev/null +++ b/libs/cocos2d/CCActionTiledGrid.m
@@ -0,0 +1,768 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCActionTiledGrid.h"
28#import "CCDirector.h"
29#import "ccMacros.h"
30#import "Support/CGPointExtension.h"
31
32typedef struct
33{
34 CGPoint position;
35 CGPoint startPosition;
36 ccGridSize delta;
37} Tile;
38
39#pragma mark -
40#pragma mark ShakyTiles3D
41
42@implementation CCShakyTiles3D
43
44+(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d
45{
46 return [[[self alloc] initWithRange:range shakeZ:shakeZ grid:gridSize duration:d] autorelease];
47}
48
49-(id)initWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d
50{
51 if ( (self = [super initWithSize:gSize duration:d]) )
52 {
53 randrange = range;
54 shakeZ = sz;
55 }
56
57 return self;
58}
59
60-(id) copyWithZone: (NSZone*) zone
61{
62 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shakeZ:shakeZ grid:gridSize_ duration:duration_];
63 return copy;
64}
65
66
67-(void)update:(ccTime)time
68{
69 int i, j;
70
71 for( i = 0; i < gridSize_.x; i++ )
72 {
73 for( j = 0; j < gridSize_.y; j++ )
74 {
75 ccQuad3 coords = [self originalTile:ccg(i,j)];
76
77 // X
78 coords.bl.x += ( rand() % (randrange*2) ) - randrange;
79 coords.br.x += ( rand() % (randrange*2) ) - randrange;
80 coords.tl.x += ( rand() % (randrange*2) ) - randrange;
81 coords.tr.x += ( rand() % (randrange*2) ) - randrange;
82
83 // Y
84 coords.bl.y += ( rand() % (randrange*2) ) - randrange;
85 coords.br.y += ( rand() % (randrange*2) ) - randrange;
86 coords.tl.y += ( rand() % (randrange*2) ) - randrange;
87 coords.tr.y += ( rand() % (randrange*2) ) - randrange;
88
89 if( shakeZ ) {
90 coords.bl.z += ( rand() % (randrange*2) ) - randrange;
91 coords.br.z += ( rand() % (randrange*2) ) - randrange;
92 coords.tl.z += ( rand() % (randrange*2) ) - randrange;
93 coords.tr.z += ( rand() % (randrange*2) ) - randrange;
94 }
95
96 [self setTile:ccg(i,j) coords:coords];
97 }
98 }
99}
100
101@end
102
103////////////////////////////////////////////////////////////
104
105#pragma mark -
106#pragma mark CCShatteredTiles3D
107
108@implementation CCShatteredTiles3D
109
110+(id)actionWithRange:(int)range shatterZ:(BOOL)sz grid:(ccGridSize)gridSize duration:(ccTime)d
111{
112 return [[[self alloc] initWithRange:range shatterZ:sz grid:gridSize duration:d] autorelease];
113}
114
115-(id)initWithRange:(int)range shatterZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d
116{
117 if ( (self = [super initWithSize:gSize duration:d]) )
118 {
119 once = NO;
120 randrange = range;
121 shatterZ = sz;
122 }
123
124 return self;
125}
126
127-(id) copyWithZone: (NSZone*) zone
128{
129 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shatterZ:shatterZ grid:gridSize_ duration:duration_];
130 return copy;
131}
132
133
134-(void)update:(ccTime)time
135{
136 int i, j;
137
138 if ( once == NO )
139 {
140 for( i = 0; i < gridSize_.x; i++ )
141 {
142 for( j = 0; j < gridSize_.y; j++ )
143 {
144 ccQuad3 coords = [self originalTile:ccg(i,j)];
145
146 // X
147 coords.bl.x += ( rand() % (randrange*2) ) - randrange;
148 coords.br.x += ( rand() % (randrange*2) ) - randrange;
149 coords.tl.x += ( rand() % (randrange*2) ) - randrange;
150 coords.tr.x += ( rand() % (randrange*2) ) - randrange;
151
152 // Y
153 coords.bl.y += ( rand() % (randrange*2) ) - randrange;
154 coords.br.y += ( rand() % (randrange*2) ) - randrange;
155 coords.tl.y += ( rand() % (randrange*2) ) - randrange;
156 coords.tr.y += ( rand() % (randrange*2) ) - randrange;
157
158 if( shatterZ ) {
159 coords.bl.z += ( rand() % (randrange*2) ) - randrange;
160 coords.br.z += ( rand() % (randrange*2) ) - randrange;
161 coords.tl.z += ( rand() % (randrange*2) ) - randrange;
162 coords.tr.z += ( rand() % (randrange*2) ) - randrange;
163 }
164
165 [self setTile:ccg(i,j) coords:coords];
166 }
167 }
168
169 once = YES;
170 }
171}
172
173@end
174
175////////////////////////////////////////////////////////////
176
177#pragma mark -
178#pragma mark CCShuffleTiles
179
180@implementation CCShuffleTiles
181
182+(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d
183{
184 return [[[self alloc] initWithSeed:s grid:gridSize duration:d] autorelease];
185}
186
187-(id)initWithSeed:(int)s grid:(ccGridSize)gSize duration:(ccTime)d
188{
189 if ( (self = [super initWithSize:gSize duration:d]) )
190 {
191 seed = s;
192 tilesOrder = nil;
193 tiles = nil;
194 }
195
196 return self;
197}
198
199-(id) copyWithZone: (NSZone*) zone
200{
201 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSeed:seed grid:gridSize_ duration:duration_];
202 return copy;
203}
204
205
206-(void)dealloc
207{
208 if ( tilesOrder ) free(tilesOrder);
209 if ( tiles ) free(tiles);
210 [super dealloc];
211}
212
213-(void)shuffle:(int*)array count:(NSUInteger)len
214{
215 NSInteger i;
216 for( i = len - 1; i >= 0; i-- )
217 {
218 NSInteger j = rand() % (i+1);
219 int v = array[i];
220 array[i] = array[j];
221 array[j] = v;
222 }
223}
224
225-(ccGridSize)getDelta:(ccGridSize)pos
226{
227 CGPoint pos2;
228
229 NSInteger idx = pos.x * gridSize_.y + pos.y;
230
231 pos2.x = tilesOrder[idx] / (int)gridSize_.y;
232 pos2.y = tilesOrder[idx] % (int)gridSize_.y;
233
234 return ccg(pos2.x - pos.x, pos2.y - pos.y);
235}
236
237-(void)placeTile:(ccGridSize)pos tile:(Tile)t
238{
239 ccQuad3 coords = [self originalTile:pos];
240
241 CGPoint step = [[target_ grid] step];
242 coords.bl.x += (int)(t.position.x * step.x);
243 coords.bl.y += (int)(t.position.y * step.y);
244
245 coords.br.x += (int)(t.position.x * step.x);
246 coords.br.y += (int)(t.position.y * step.y);
247
248 coords.tl.x += (int)(t.position.x * step.x);
249 coords.tl.y += (int)(t.position.y * step.y);
250
251 coords.tr.x += (int)(t.position.x * step.x);
252 coords.tr.y += (int)(t.position.y * step.y);
253
254 [self setTile:pos coords:coords];
255}
256
257-(void)startWithTarget:(id)aTarget
258{
259 [super startWithTarget:aTarget];
260
261 if ( seed != -1 )
262 srand(seed);
263
264 tilesCount = gridSize_.x * gridSize_.y;
265 tilesOrder = (int*)malloc(tilesCount*sizeof(int));
266 int i, j;
267
268 for( i = 0; i < tilesCount; i++ )
269 tilesOrder[i] = i;
270
271 [self shuffle:tilesOrder count:tilesCount];
272
273 tiles = malloc(tilesCount*sizeof(Tile));
274 Tile *tileArray = (Tile*)tiles;
275
276 for( i = 0; i < gridSize_.x; i++ )
277 {
278 for( j = 0; j < gridSize_.y; j++ )
279 {
280 tileArray->position = ccp(i,j);
281 tileArray->startPosition = ccp(i,j);
282 tileArray->delta = [self getDelta:ccg(i,j)];
283 tileArray++;
284 }
285 }
286}
287
288-(void)update:(ccTime)time
289{
290 int i, j;
291
292 Tile *tileArray = (Tile*)tiles;
293
294 for( i = 0; i < gridSize_.x; i++ )
295 {
296 for( j = 0; j < gridSize_.y; j++ )
297 {
298 tileArray->position = ccpMult( ccp(tileArray->delta.x, tileArray->delta.y), time);
299 [self placeTile:ccg(i,j) tile:*tileArray];
300 tileArray++;
301 }
302 }
303}
304
305@end
306
307////////////////////////////////////////////////////////////
308
309#pragma mark -
310#pragma mark CCFadeOutTRTiles
311
312@implementation CCFadeOutTRTiles
313
314-(float)testFunc:(ccGridSize)pos time:(ccTime)time
315{
316 CGPoint n = ccpMult( ccp(gridSize_.x,gridSize_.y), time);
317 if ( (n.x+n.y) == 0.0f )
318 return 1.0f;
319
320 return powf( (pos.x+pos.y) / (n.x+n.y), 6 );
321}
322
323-(void)turnOnTile:(ccGridSize)pos
324{
325 [self setTile:pos coords:[self originalTile:pos]];
326}
327
328-(void)turnOffTile:(ccGridSize)pos
329{
330 ccQuad3 coords;
331 bzero(&coords, sizeof(ccQuad3));
332 [self setTile:pos coords:coords];
333}
334
335-(void)transformTile:(ccGridSize)pos distance:(float)distance
336{
337 ccQuad3 coords = [self originalTile:pos];
338 CGPoint step = [[target_ grid] step];
339
340 coords.bl.x += (step.x / 2) * (1.0f - distance);
341 coords.bl.y += (step.y / 2) * (1.0f - distance);
342
343 coords.br.x -= (step.x / 2) * (1.0f - distance);
344 coords.br.y += (step.y / 2) * (1.0f - distance);
345
346 coords.tl.x += (step.x / 2) * (1.0f - distance);
347 coords.tl.y -= (step.y / 2) * (1.0f - distance);
348
349 coords.tr.x -= (step.x / 2) * (1.0f - distance);
350 coords.tr.y -= (step.y / 2) * (1.0f - distance);
351
352 [self setTile:pos coords:coords];
353}
354
355-(void)update:(ccTime)time
356{
357 int i, j;
358
359 for( i = 0; i < gridSize_.x; i++ )
360 {
361 for( j = 0; j < gridSize_.y; j++ )
362 {
363 float distance = [self testFunc:ccg(i,j) time:time];
364 if ( distance == 0 )
365 [self turnOffTile:ccg(i,j)];
366 else if ( distance < 1 )
367 [self transformTile:ccg(i,j) distance:distance];
368 else
369 [self turnOnTile:ccg(i,j)];
370 }
371 }
372}
373
374@end
375
376////////////////////////////////////////////////////////////
377
378#pragma mark -
379#pragma mark CCFadeOutBLTiles
380
381@implementation CCFadeOutBLTiles
382
383-(float)testFunc:(ccGridSize)pos time:(ccTime)time
384{
385 CGPoint n = ccpMult(ccp(gridSize_.x, gridSize_.y), (1.0f-time));
386 if ( (pos.x+pos.y) == 0 )
387 return 1.0f;
388
389 return powf( (n.x+n.y) / (pos.x+pos.y), 6 );
390}
391
392@end
393
394////////////////////////////////////////////////////////////
395
396#pragma mark -
397#pragma mark CCFadeOutUpTiles
398
399@implementation CCFadeOutUpTiles
400
401-(float)testFunc:(ccGridSize)pos time:(ccTime)time
402{
403 CGPoint n = ccpMult(ccp(gridSize_.x, gridSize_.y), time);
404 if ( n.y == 0 )
405 return 1.0f;
406
407 return powf( pos.y / n.y, 6 );
408}
409
410-(void)transformTile:(ccGridSize)pos distance:(float)distance
411{
412 ccQuad3 coords = [self originalTile:pos];
413 CGPoint step = [[target_ grid] step];
414
415 coords.bl.y += (step.y / 2) * (1.0f - distance);
416 coords.br.y += (step.y / 2) * (1.0f - distance);
417 coords.tl.y -= (step.y / 2) * (1.0f - distance);
418 coords.tr.y -= (step.y / 2) * (1.0f - distance);
419
420 [self setTile:pos coords:coords];
421}
422
423@end
424
425////////////////////////////////////////////////////////////
426
427#pragma mark -
428#pragma mark CCFadeOutDownTiles
429
430@implementation CCFadeOutDownTiles
431
432-(float)testFunc:(ccGridSize)pos time:(ccTime)time
433{
434 CGPoint n = ccpMult(ccp(gridSize_.x,gridSize_.y), (1.0f - time));
435 if ( pos.y == 0 )
436 return 1.0f;
437
438 return powf( n.y / pos.y, 6 );
439}
440
441@end
442
443////////////////////////////////////////////////////////////
444
445#pragma mark -
446#pragma mark TurnOffTiles
447
448@implementation CCTurnOffTiles
449
450+(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d
451{
452 return [[[self alloc] initWithSeed:s grid:gridSize duration:d] autorelease];
453}
454
455-(id)initWithSeed:(int)s grid:(ccGridSize)gSize duration:(ccTime)d
456{
457 if ( (self = [super initWithSize:gSize duration:d]) )
458 {
459 seed = s;
460 tilesOrder = nil;
461 }
462
463 return self;
464}
465
466-(id) copyWithZone: (NSZone*) zone
467{
468 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSeed:seed grid:gridSize_ duration:duration_];
469 return copy;
470}
471
472-(void)dealloc
473{
474 if ( tilesOrder ) free(tilesOrder);
475 [super dealloc];
476}
477
478-(void)shuffle:(int*)array count:(NSUInteger)len
479{
480 NSInteger i;
481 for( i = len - 1; i >= 0; i-- )
482 {
483 NSInteger j = rand() % (i+1);
484 int v = array[i];
485 array[i] = array[j];
486 array[j] = v;
487 }
488}
489
490-(void)turnOnTile:(ccGridSize)pos
491{
492 [self setTile:pos coords:[self originalTile:pos]];
493}
494
495-(void)turnOffTile:(ccGridSize)pos
496{
497 ccQuad3 coords;
498
499 bzero(&coords, sizeof(ccQuad3));
500 [self setTile:pos coords:coords];
501}
502
503-(void)startWithTarget:(id)aTarget
504{
505 int i;
506
507 [super startWithTarget:aTarget];
508
509 if ( seed != -1 )
510 srand(seed);
511
512 tilesCount = gridSize_.x * gridSize_.y;
513 tilesOrder = (int*)malloc(tilesCount*sizeof(int));
514
515 for( i = 0; i < tilesCount; i++ )
516 tilesOrder[i] = i;
517
518 [self shuffle:tilesOrder count:tilesCount];
519}
520
521-(void)update:(ccTime)time
522{
523 int i, l, t;
524
525 l = (int)(time * (float)tilesCount);
526
527 for( i = 0; i < tilesCount; i++ )
528 {
529 t = tilesOrder[i];
530 ccGridSize tilePos = ccg( t / gridSize_.y, t % gridSize_.y );
531
532 if ( i < l )
533 [self turnOffTile:tilePos];
534 else
535 [self turnOnTile:tilePos];
536 }
537}
538
539@end
540
541////////////////////////////////////////////////////////////
542
543#pragma mark -
544#pragma mark CCWavesTiles3D
545
546@implementation CCWavesTiles3D
547
548@synthesize amplitude;
549@synthesize amplitudeRate;
550
551+(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
552{
553 return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease];
554}
555
556-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
557{
558 if ( (self = [super initWithSize:gSize duration:d]) )
559 {
560 waves = wav;
561 amplitude = amp;
562 amplitudeRate = 1.0f;
563 }
564
565 return self;
566}
567
568-(id) copyWithZone: (NSZone*) zone
569{
570 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_];
571 return copy;
572}
573
574
575-(void)update:(ccTime)time
576{
577 int i, j;
578
579 for( i = 0; i < gridSize_.x; i++ )
580 {
581 for( j = 0; j < gridSize_.y; j++ )
582 {
583 ccQuad3 coords = [self originalTile:ccg(i,j)];
584
585 coords.bl.z = (sinf(time*(CGFloat)M_PI*waves*2 + (coords.bl.y+coords.bl.x) * .01f) * amplitude * amplitudeRate );
586 coords.br.z = coords.bl.z;
587 coords.tl.z = coords.bl.z;
588 coords.tr.z = coords.bl.z;
589
590 [self setTile:ccg(i,j) coords:coords];
591 }
592 }
593}
594@end
595
596////////////////////////////////////////////////////////////
597
598#pragma mark -
599#pragma mark CCJumpTiles3D
600
601@implementation CCJumpTiles3D
602
603@synthesize amplitude;
604@synthesize amplitudeRate;
605
606+(id)actionWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d
607{
608 return [[[self alloc] initWithJumps:j amplitude:amp grid:gridSize duration:d] autorelease];
609}
610
611-(id)initWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d
612{
613 if ( (self = [super initWithSize:gSize duration:d]) )
614 {
615 jumps = j;
616 amplitude = amp;
617 amplitudeRate = 1.0f;
618 }
619
620 return self;
621}
622
623-(id) copyWithZone: (NSZone*) zone
624{
625 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithJumps:jumps amplitude:amplitude grid:gridSize_ duration:duration_];
626 return copy;
627}
628
629
630-(void)update:(ccTime)time
631{
632 int i, j;
633
634 float sinz = (sinf((CGFloat)M_PI*time*jumps*2) * amplitude * amplitudeRate );
635 float sinz2 = (sinf((CGFloat)M_PI*(time*jumps*2 + 1)) * amplitude * amplitudeRate );
636
637 for( i = 0; i < gridSize_.x; i++ )
638 {
639 for( j = 0; j < gridSize_.y; j++ )
640 {
641 ccQuad3 coords = [self originalTile:ccg(i,j)];
642
643 if ( ((i+j) % 2) == 0 )
644 {
645 coords.bl.z += sinz;
646 coords.br.z += sinz;
647 coords.tl.z += sinz;
648 coords.tr.z += sinz;
649 }
650 else
651 {
652 coords.bl.z += sinz2;
653 coords.br.z += sinz2;
654 coords.tl.z += sinz2;
655 coords.tr.z += sinz2;
656 }
657
658 [self setTile:ccg(i,j) coords:coords];
659 }
660 }
661}
662@end
663
664////////////////////////////////////////////////////////////
665
666#pragma mark -
667#pragma mark SplitRows
668
669@implementation CCSplitRows
670
671+(id)actionWithRows:(int)r duration:(ccTime)d
672{
673 return [[[self alloc] initWithRows:r duration:d] autorelease];
674}
675
676-(id)initWithRows:(int)r duration:(ccTime)d
677{
678 rows = r;
679 return [super initWithSize:ccg(1,r) duration:d];
680}
681
682-(id) copyWithZone: (NSZone*) zone
683{
684 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRows:rows duration:duration_];
685 return copy;
686}
687
688-(void)startWithTarget:(id)aTarget
689{
690 [super startWithTarget:aTarget];
691 winSize = [[CCDirector sharedDirector] winSizeInPixels];
692}
693
694-(void)update:(ccTime)time
695{
696 int j;
697
698 for( j = 0; j < gridSize_.y; j++ )
699 {
700 ccQuad3 coords = [self originalTile:ccg(0,j)];
701 float direction = 1;
702
703 if ( (j % 2 ) == 0 )
704 direction = -1;
705
706 coords.bl.x += direction * winSize.width * time;
707 coords.br.x += direction * winSize.width * time;
708 coords.tl.x += direction * winSize.width * time;
709 coords.tr.x += direction * winSize.width * time;
710
711 [self setTile:ccg(0,j) coords:coords];
712 }
713}
714
715@end
716
717////////////////////////////////////////////////////////////
718
719#pragma mark -
720#pragma mark CCSplitCols
721
722@implementation CCSplitCols
723
724+(id)actionWithCols:(int)c duration:(ccTime)d
725{
726 return [[[self alloc] initWithCols:c duration:d] autorelease];
727}
728
729-(id)initWithCols:(int)c duration:(ccTime)d
730{
731 cols = c;
732 return [super initWithSize:ccg(c,1) duration:d];
733}
734
735-(id) copyWithZone: (NSZone*) zone
736{
737 CCGridAction *copy = [[[self class] allocWithZone:zone] initWithCols:cols duration:duration_];
738 return copy;
739}
740
741-(void)startWithTarget:(id)aTarget
742{
743 [super startWithTarget:aTarget];
744 winSize = [[CCDirector sharedDirector] winSizeInPixels];
745}
746
747-(void)update:(ccTime)time
748{
749 int i;
750
751 for( i = 0; i < gridSize_.x; i++ )
752 {
753 ccQuad3 coords = [self originalTile:ccg(i,0)];
754 float direction = 1;
755
756 if ( (i % 2 ) == 0 )
757 direction = -1;
758
759 coords.bl.y += direction * winSize.height * time;
760 coords.br.y += direction * winSize.height * time;
761 coords.tl.y += direction * winSize.height * time;
762 coords.tr.y += direction * winSize.height * time;
763
764 [self setTile:ccg(i,0) coords:coords];
765 }
766}
767
768@end
diff --git a/libs/cocos2d/CCActionTween.h b/libs/cocos2d/CCActionTween.h new file mode 100755 index 0000000..69fdea5 --- /dev/null +++ b/libs/cocos2d/CCActionTween.h
@@ -0,0 +1,62 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright 2009 lhunath (Maarten Billemont)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28#import "CCActionInterval.h"
29
30/** CCActionTween
31
32 CCActionTween is an action that lets you update any property of an object.
33 For example, if you want to modify the "width" property of a target from 200 to 300 in 2 senconds, then:
34
35 id modifyWidth = [CCActionTween actionWithDuration:2 key:@"width" from:200 to:300];
36 [target runAction:modifyWidth];
37
38
39 Another example: CCScaleTo action could be rewriten using CCPropertyAction:
40
41 // scaleA and scaleB are equivalents
42 id scaleA = [CCScaleTo actionWithDuration:2 scale:3];
43 id scaleB = [CCActionTween actionWithDuration:2 key:@"scale" from:1 to:3];
44
45
46 @since v0.99.2
47 */
48@interface CCActionTween : CCActionInterval
49{
50 NSString *key_;
51
52 float from_, to_;
53 float delta_;
54}
55
56/** creates an initializes the action with the property name (key), and the from and to parameters. */
57+ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to;
58
59/** initializes the action with the property name (key), and the from and to parameters. */
60- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to;
61
62@end
diff --git a/libs/cocos2d/CCActionTween.m b/libs/cocos2d/CCActionTween.m new file mode 100755 index 0000000..95ae572 --- /dev/null +++ b/libs/cocos2d/CCActionTween.m
@@ -0,0 +1,72 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright 2009 lhunath (Maarten Billemont)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "CCActionTween.h"
27
28
29@implementation CCActionTween
30
31+ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)aKey from:(float)aFrom to:(float)aTo {
32
33 return [[[[self class] alloc] initWithDuration:aDuration key:aKey from:aFrom to:aTo] autorelease];
34}
35
36- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to {
37
38 if ((self = [super initWithDuration:aDuration])) {
39
40 key_ = [key copy];
41 to_ = to;
42 from_ = from;
43
44 }
45
46 return self;
47}
48
49- (void) dealloc
50{
51 [key_ release];
52 [super dealloc];
53}
54
55- (void)startWithTarget:aTarget
56{
57 [super startWithTarget:aTarget];
58 delta_ = to_ - from_;
59}
60
61- (void) update:(ccTime) dt
62{
63 [target_ setValue:[NSNumber numberWithFloat:to_ - delta_ * (1 - dt)] forKey:key_];
64}
65
66- (CCActionInterval *) reverse
67{
68 return [[self class] actionWithDuration:duration_ key:key_ from:to_ to:from_];
69}
70
71
72@end
diff --git a/libs/cocos2d/CCAnimation.h b/libs/cocos2d/CCAnimation.h new file mode 100755 index 0000000..24b3d96 --- /dev/null +++ b/libs/cocos2d/CCAnimation.h
@@ -0,0 +1,136 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Foundation/Foundation.h>
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#import <CoreGraphics/CoreGraphics.h>
30#endif // IPHONE
31
32@class CCSpriteFrame;
33@class CCTexture2D;
34
35/** A CCAnimation object is used to perform animations on the CCSprite objects.
36
37 The CCAnimation object contains CCSpriteFrame objects, and a possible delay between the frames.
38 You can animate a CCAnimation object by using the CCAnimate action. Example:
39
40 [sprite runAction:[CCAnimate actionWithAnimation:animation]];
41
42 */
43@interface CCAnimation : NSObject
44{
45 NSString *name_;
46 float delay_;
47 NSMutableArray *frames_;
48}
49
50/** name of the animation */
51@property (nonatomic,readwrite,retain) NSString *name;
52/** delay between frames in seconds. */
53@property (nonatomic,readwrite,assign) float delay;
54/** array of frames */
55@property (nonatomic,readwrite,retain) NSMutableArray *frames;
56
57/** Creates an animation
58 @since v0.99.5
59 */
60+(id) animation;
61
62/** Creates an animation with frames.
63 @since v0.99.5
64 */
65+(id) animationWithFrames:(NSArray*)frames;
66
67/* Creates an animation with frames and a delay between frames.
68 @since v0.99.5
69 */
70+(id) animationWithFrames:(NSArray*)frames delay:(float)delay;
71
72/** Creates a CCAnimation with a name
73 @since v0.99.3
74 @deprecated Will be removed in 1.0.1. Use "animation" instead.
75 */
76+(id) animationWithName:(NSString*)name DEPRECATED_ATTRIBUTE;
77
78/** Creates a CCAnimation with a name and frames
79 @since v0.99.3
80 @deprecated Will be removed in 1.0.1. Use "animationWithFrames" instead.
81 */
82+(id) animationWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE;
83
84/** Creates a CCAnimation with a name and delay between frames. */
85+(id) animationWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE;
86
87/** Creates a CCAnimation with a name, delay and an array of CCSpriteFrames. */
88+(id) animationWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE;
89
90
91/** Initializes a CCAnimation with frames.
92 @since v0.99.5
93*/
94-(id) initWithFrames:(NSArray*)frames;
95
96/** Initializes a CCAnimation with frames and a delay between frames
97 @since v0.99.5
98 */
99-(id) initWithFrames:(NSArray *)frames delay:(float)delay;
100
101/** Initializes a CCAnimation with a name
102 @since v0.99.3
103 @deprecated Will be removed in 1.0.1. Use "init" instead.
104 */
105-(id) initWithName:(NSString*)name DEPRECATED_ATTRIBUTE;
106
107/** Initializes a CCAnimation with a name and frames
108 @since v0.99.3
109 @deprecated Will be removed in 1.0.1. Use "initWithFrames" instead.
110 */
111-(id) initWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE;
112
113/** Initializes a CCAnimation with a name and delay between frames.
114 @deprecated Will be removed in 1.0.1. Use "initWithFrames:nil delay:delay" instead.
115*/
116-(id) initWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE;
117
118/** Initializes a CCAnimation with a name, delay and an array of CCSpriteFrames.
119 @deprecated Will be removed in 1.0.1. Use "initWithFrames:frames delay:delay" instead.
120*/
121-(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE;
122
123/** Adds a frame to a CCAnimation. */
124-(void) addFrame:(CCSpriteFrame*)frame;
125
126/** Adds a frame with an image filename. Internally it will create a CCSpriteFrame and it will add it.
127 Added to facilitate the migration from v0.8 to v0.9.
128 */
129-(void) addFrameWithFilename:(NSString*)filename;
130
131/** Adds a frame with a texture and a rect. Internally it will create a CCSpriteFrame and it will add it.
132 Added to facilitate the migration from v0.8 to v0.9.
133 */
134-(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
135
136@end
diff --git a/libs/cocos2d/CCAnimation.m b/libs/cocos2d/CCAnimation.m new file mode 100755 index 0000000..eb674c6 --- /dev/null +++ b/libs/cocos2d/CCAnimation.m
@@ -0,0 +1,153 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "ccMacros.h"
28#import "CCAnimation.h"
29#import "CCSpriteFrame.h"
30#import "CCTexture2D.h"
31#import "CCTextureCache.h"
32
33@implementation CCAnimation
34@synthesize name = name_, delay = delay_, frames = frames_;
35
36+(id) animation
37{
38 return [[[self alloc] init] autorelease];
39}
40
41+(id) animationWithFrames:(NSArray*)frames
42{
43 return [[[self alloc] initWithFrames:frames] autorelease];
44}
45
46+(id) animationWithFrames:(NSArray*)frames delay:(float)delay
47{
48 return [[[self alloc] initWithFrames:frames delay:delay] autorelease];
49}
50
51+(id) animationWithName:(NSString*)name
52{
53 return [[[self alloc] initWithName:name] autorelease];
54}
55
56+(id) animationWithName:(NSString*)name frames:(NSArray*)frames
57{
58 return [[[self alloc] initWithName:name frames:frames] autorelease];
59}
60
61+(id) animationWithName:(NSString*)aname delay:(float)d frames:(NSArray*)array
62{
63 return [[[self alloc] initWithName:aname delay:d frames:array] autorelease];
64}
65
66+(id) animationWithName:(NSString*)aname delay:(float)d
67{
68 return [[[self alloc] initWithName:aname delay:d] autorelease];
69}
70
71-(id) init
72{
73 return [self initWithFrames:nil delay:0];
74}
75
76-(id) initWithFrames:(NSArray*)frames
77{
78 return [self initWithFrames:frames delay:0];
79}
80
81-(id) initWithFrames:(NSArray*)array delay:(float)delay
82{
83 if( (self=[super init]) ) {
84
85 delay_ = delay;
86 self.frames = [NSMutableArray arrayWithArray:array];
87 }
88 return self;
89}
90
91-(id) initWithName:(NSString*)name
92{
93 return [self initWithName:name delay:0 frames:nil];
94}
95
96-(id) initWithName:(NSString*)name frames:(NSArray*)frames
97{
98 return [self initWithName:name delay:0 frames:frames];
99}
100
101-(id) initWithName:(NSString*)t delay:(float)d
102{
103 return [self initWithName:t delay:d frames:nil];
104}
105
106-(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)array
107{
108 if( (self=[super init]) ) {
109
110 delay_ = delay;
111 self.name = name;
112 self.frames = [NSMutableArray arrayWithArray:array];
113 }
114 return self;
115}
116
117- (NSString*) description
118{
119 return [NSString stringWithFormat:@"<%@ = %08X | frames=%d, delay:%f>", [self class], self,
120 [frames_ count],
121 delay_
122 ];
123}
124
125-(void) dealloc
126{
127 CCLOGINFO( @"cocos2d: deallocing %@",self);
128 [name_ release];
129 [frames_ release];
130 [super dealloc];
131}
132
133-(void) addFrame:(CCSpriteFrame*)frame
134{
135 [frames_ addObject:frame];
136}
137
138-(void) addFrameWithFilename:(NSString*)filename
139{
140 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename];
141 CGRect rect = CGRectZero;
142 rect.size = texture.contentSize;
143 CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect];
144 [frames_ addObject:frame];
145}
146
147-(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
148{
149 CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect];
150 [frames_ addObject:frame];
151}
152
153@end
diff --git a/libs/cocos2d/CCAnimationCache.h b/libs/cocos2d/CCAnimationCache.h new file mode 100755 index 0000000..075c836 --- /dev/null +++ b/libs/cocos2d/CCAnimationCache.h
@@ -0,0 +1,64 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Foundation/Foundation.h>
28
29@class CCAnimation;
30
31/** Singleton that manages the Animations.
32 It saves in a cache the animations. You should use this class if you want to save your animations in a cache.
33
34 Before v0.99.5, the recommend way was to save them on the CCSprite. Since v0.99.5, you should use this class instead.
35
36 @since v0.99.5
37 */
38@interface CCAnimationCache : NSObject
39{
40 NSMutableDictionary *animations_;
41}
42
43/** Retruns ths shared instance of the Animation cache */
44+ (CCAnimationCache *) sharedAnimationCache;
45
46/** Purges the cache. It releases all the CCAnimation objects and the shared instance.
47 */
48+(void)purgeSharedAnimationCache;
49
50/** Adds a CCAnimation with a name.
51 */
52-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name;
53
54/** Deletes a CCAnimation from the cache.
55 */
56-(void) removeAnimationByName:(NSString*)name;
57
58/** Returns a CCAnimation that was previously added.
59 If the name is not found it will return nil.
60 You should retain the returned copy if you are going to use it.
61 */
62-(CCAnimation*) animationByName:(NSString*)name;
63
64@end
diff --git a/libs/cocos2d/CCAnimationCache.m b/libs/cocos2d/CCAnimationCache.m new file mode 100755 index 0000000..f508227 --- /dev/null +++ b/libs/cocos2d/CCAnimationCache.m
@@ -0,0 +1,101 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "ccMacros.h"
28#import "CCAnimationCache.h"
29#import "CCAnimation.h"
30#import "CCSprite.h"
31
32
33@implementation CCAnimationCache
34
35#pragma mark CCAnimationCache - Alloc, Init & Dealloc
36
37static CCAnimationCache *sharedAnimationCache_=nil;
38
39+ (CCAnimationCache *)sharedAnimationCache
40{
41 if (!sharedAnimationCache_)
42 sharedAnimationCache_ = [[CCAnimationCache alloc] init];
43
44 return sharedAnimationCache_;
45}
46
47+(id)alloc
48{
49 NSAssert(sharedAnimationCache_ == nil, @"Attempted to allocate a second instance of a singleton.");
50 return [super alloc];
51}
52
53+(void)purgeSharedAnimationCache
54{
55 [sharedAnimationCache_ release];
56 sharedAnimationCache_ = nil;
57}
58
59-(id) init
60{
61 if( (self=[super init]) ) {
62 animations_ = [[NSMutableDictionary alloc] initWithCapacity: 20];
63 }
64
65 return self;
66}
67
68- (NSString*) description
69{
70 return [NSString stringWithFormat:@"<%@ = %08X | num of animations = %i>", [self class], self, [animations_ count]];
71}
72
73-(void) dealloc
74{
75 CCLOGINFO(@"cocos2d: deallocing %@", self);
76
77 [animations_ release];
78 [super dealloc];
79}
80
81#pragma mark CCAnimationCache - load/get/del
82
83-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name
84{
85 [animations_ setObject:animation forKey:name];
86}
87
88-(void) removeAnimationByName:(NSString*)name
89{
90 if( ! name )
91 return;
92
93 [animations_ removeObjectForKey:name];
94}
95
96-(CCAnimation*) animationByName:(NSString*)name
97{
98 return [animations_ objectForKey:name];
99}
100
101@end
diff --git a/libs/cocos2d/CCAtlasNode.h b/libs/cocos2d/CCAtlasNode.h new file mode 100755 index 0000000..43e57c2 --- /dev/null +++ b/libs/cocos2d/CCAtlasNode.h
@@ -0,0 +1,93 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27
28#import "CCTextureAtlas.h"
29#import "CCNode.h"
30#import "CCProtocols.h"
31
32/** CCAtlasNode is a subclass of CCNode that implements the CCRGBAProtocol and
33 CCTextureProtocol protocol
34
35 It knows how to render a TextureAtlas object.
36 If you are going to render a TextureAtlas consider subclassing CCAtlasNode (or a subclass of CCAtlasNode)
37
38 All features from CCNode are valid, plus the following features:
39 - opacity and RGB colors
40 */
41@interface CCAtlasNode : CCNode <CCRGBAProtocol, CCTextureProtocol>
42{
43 // texture atlas
44 CCTextureAtlas *textureAtlas_;
45
46 // chars per row
47 NSUInteger itemsPerRow_;
48 // chars per column
49 NSUInteger itemsPerColumn_;
50
51 // width of each char
52 NSUInteger itemWidth_;
53 // height of each char
54 NSUInteger itemHeight_;
55
56 // quads to draw
57 NSUInteger quadsToDraw_;
58
59 // blend function
60 ccBlendFunc blendFunc_;
61
62 // texture RGBA.
63 GLubyte opacity_;
64 ccColor3B color_;
65 ccColor3B colorUnmodified_;
66 BOOL opacityModifyRGB_;
67}
68
69/** conforms to CCTextureProtocol protocol */
70@property (nonatomic,readwrite,retain) CCTextureAtlas *textureAtlas;
71
72/** conforms to CCTextureProtocol protocol */
73@property (nonatomic,readwrite) ccBlendFunc blendFunc;
74
75/** conforms to CCRGBAProtocol protocol */
76@property (nonatomic,readwrite) GLubyte opacity;
77/** conforms to CCRGBAProtocol protocol */
78@property (nonatomic,readwrite) ccColor3B color;
79
80/** how many quads to draw */
81@property (readwrite) NSUInteger quadsToDraw;
82
83/** creates a CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/
84+(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c;
85
86/** initializes an CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/
87-(id) initWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c;
88
89/** updates the Atlas (indexed vertex array).
90 * Shall be overriden in subclasses
91 */
92-(void) updateAtlasValues;
93@end
diff --git a/libs/cocos2d/CCAtlasNode.m b/libs/cocos2d/CCAtlasNode.m new file mode 100755 index 0000000..3f44633 --- /dev/null +++ b/libs/cocos2d/CCAtlasNode.m
@@ -0,0 +1,211 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import "CCAtlasNode.h"
28#import "ccMacros.h"
29
30
31@interface CCAtlasNode ()
32-(void) calculateMaxItems;
33-(void) updateBlendFunc;
34-(void) updateOpacityModifyRGB;
35@end
36
37@implementation CCAtlasNode
38
39@synthesize textureAtlas = textureAtlas_;
40@synthesize blendFunc = blendFunc_;
41@synthesize quadsToDraw = quadsToDraw_;
42
43#pragma mark CCAtlasNode - Creation & Init
44+(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c
45{
46 return [[[self alloc] initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender:c] autorelease];
47}
48
49-(id) initWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c
50{
51 if( (self=[super init]) ) {
52
53 itemWidth_ = w * CC_CONTENT_SCALE_FACTOR();
54 itemHeight_ = h * CC_CONTENT_SCALE_FACTOR();
55
56 opacity_ = 255;
57 color_ = colorUnmodified_ = ccWHITE;
58 opacityModifyRGB_ = YES;
59
60 blendFunc_.src = CC_BLEND_SRC;
61 blendFunc_.dst = CC_BLEND_DST;
62
63 // double retain to avoid the autorelease pool
64 // also, using: self.textureAtlas supports re-initialization without leaking
65 self.textureAtlas = [[CCTextureAtlas alloc] initWithFile:tile capacity:c];
66 [textureAtlas_ release];
67
68 if( ! textureAtlas_ ) {
69 CCLOG(@"cocos2d: Could not initialize CCAtlasNode. Invalid Texture");
70 [self release];
71 return nil;
72 }
73
74 [self updateBlendFunc];
75 [self updateOpacityModifyRGB];
76
77 [self calculateMaxItems];
78
79 self.quadsToDraw = c;
80
81 }
82 return self;
83}
84
85-(void) dealloc
86{
87 [textureAtlas_ release];
88
89 [super dealloc];
90}
91
92#pragma mark CCAtlasNode - Atlas generation
93
94-(void) calculateMaxItems
95{
96 CGSize s = [[textureAtlas_ texture] contentSizeInPixels];
97 itemsPerColumn_ = s.height / itemHeight_;
98 itemsPerRow_ = s.width / itemWidth_;
99}
100
101-(void) updateAtlasValues
102{
103 [NSException raise:@"CCAtlasNode:Abstract" format:@"updateAtlasValue not overriden"];
104}
105
106#pragma mark CCAtlasNode - draw
107- (void) draw
108{
109 [super draw];
110
111 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
112 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
113 // Unneeded states: GL_COLOR_ARRAY
114 glDisableClientState(GL_COLOR_ARRAY);
115
116 glColor4ub( color_.r, color_.g, color_.b, opacity_);
117
118 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
119 if( newBlend )
120 glBlendFunc( blendFunc_.src, blendFunc_.dst );
121
122 [textureAtlas_ drawNumberOfQuads:quadsToDraw_ fromIndex:0];
123
124 if( newBlend )
125 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
126
127 // is this chepear than saving/restoring color state ?
128 // XXX: There is no need to restore the color to (255,255,255,255). Objects should use the color
129 // XXX: that they need
130// glColor4ub( 255, 255, 255, 255);
131
132 // restore default GL state
133 glEnableClientState(GL_COLOR_ARRAY);
134
135}
136
137#pragma mark CCAtlasNode - RGBA protocol
138
139- (ccColor3B) color
140{
141 if(opacityModifyRGB_)
142 return colorUnmodified_;
143
144 return color_;
145}
146
147-(void) setColor:(ccColor3B)color3
148{
149 color_ = colorUnmodified_ = color3;
150
151 if( opacityModifyRGB_ ){
152 color_.r = color3.r * opacity_/255;
153 color_.g = color3.g * opacity_/255;
154 color_.b = color3.b * opacity_/255;
155 }
156}
157
158-(GLubyte) opacity
159{
160 return opacity_;
161}
162
163-(void) setOpacity:(GLubyte) anOpacity
164{
165 opacity_ = anOpacity;
166
167 // special opacity for premultiplied textures
168 if( opacityModifyRGB_ )
169 [self setColor: colorUnmodified_];
170}
171
172-(void) setOpacityModifyRGB:(BOOL)modify
173{
174 ccColor3B oldColor = self.color;
175 opacityModifyRGB_ = modify;
176 self.color = oldColor;
177}
178
179-(BOOL) doesOpacityModifyRGB
180{
181 return opacityModifyRGB_;
182}
183
184-(void) updateOpacityModifyRGB
185{
186 opacityModifyRGB_ = [textureAtlas_.texture hasPremultipliedAlpha];
187}
188
189#pragma mark CCAtlasNode - CocosNodeTexture protocol
190
191-(void) updateBlendFunc
192{
193 if( ! [textureAtlas_.texture hasPremultipliedAlpha] ) {
194 blendFunc_.src = GL_SRC_ALPHA;
195 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
196 }
197}
198
199-(void) setTexture:(CCTexture2D*)texture
200{
201 textureAtlas_.texture = texture;
202 [self updateBlendFunc];
203 [self updateOpacityModifyRGB];
204}
205
206-(CCTexture2D*) texture
207{
208 return textureAtlas_.texture;
209}
210
211@end
diff --git a/libs/cocos2d/CCBlockSupport.h b/libs/cocos2d/CCBlockSupport.h new file mode 100755 index 0000000..339d5aa --- /dev/null +++ b/libs/cocos2d/CCBlockSupport.h
@@ -0,0 +1,51 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28
29/** @file
30 cocos2d blocks support
31 */
32
33// To comply with Apple Objective C runtime (this is defined in NSObjCRuntime.h)
34#if !defined(NS_BLOCKS_AVAILABLE)
35 #if __BLOCKS__
36 #define NS_BLOCKS_AVAILABLE 1
37 #else
38 #define NS_BLOCKS_AVAILABLE 0
39 #endif
40#endif
41
42#if NS_BLOCKS_AVAILABLE
43
44@interface NSObject(CCBlocksAdditions)
45
46- (void)ccCallbackBlock;
47- (void)ccCallbackBlockWithSender:(id)sender;
48
49@end
50
51#endif // NS_BLOCKS_AVAILABLE
diff --git a/libs/cocos2d/CCBlockSupport.m b/libs/cocos2d/CCBlockSupport.m new file mode 100755 index 0000000..9ac99b3 --- /dev/null +++ b/libs/cocos2d/CCBlockSupport.m
@@ -0,0 +1,46 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCBlockSupport.h"
28
29#if NS_BLOCKS_AVAILABLE
30
31@implementation NSObject(CCBlocksAdditions)
32
33- (void)ccCallbackBlock {
34 void (^block)(void) = (id)self;
35 block();
36}
37
38- (void)ccCallbackBlockWithSender:(id)sender {
39 void (^block)(id) = (id)self;
40 block(sender);
41}
42
43
44@end
45
46#endif
diff --git a/libs/cocos2d/CCCamera.h b/libs/cocos2d/CCCamera.h new file mode 100755 index 0000000..19a7712 --- /dev/null +++ b/libs/cocos2d/CCCamera.h
@@ -0,0 +1,95 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27
28#import "CCNode.h"
29
30/**
31 A CCCamera is used in every CCNode.
32 Useful to look at the object from different views.
33 The OpenGL gluLookAt() function is used to locate the
34 camera.
35
36 If the object is transformed by any of the scale, rotation or
37 position attributes, then they will override the camera.
38
39 IMPORTANT: Either your use the camera or the rotation/scale/position properties. You can't use both.
40 World coordinates won't work if you use the camera.
41
42 Limitations:
43
44 - Some nodes, like CCParallaxNode, CCParticle uses world node coordinates, and they won't work properly if you move them (or any of their ancestors)
45 using the camera.
46
47 - It doesn't work on batched nodes like CCSprite objects when they are parented to a CCSpriteBatchNode object.
48
49 - It is recommended to use it ONLY if you are going to create 3D effects. For 2D effecs, use the action CCFollow or position/scale/rotate.
50
51*/
52
53@interface CCCamera : NSObject
54{
55 float eyeX_;
56 float eyeY_;
57 float eyeZ_;
58
59 float centerX_;
60 float centerY_;
61 float centerZ_;
62
63 float upX_;
64 float upY_;
65 float upZ_;
66
67 BOOL dirty_;
68}
69
70/** whether of not the camera is dirty */
71@property (nonatomic,readwrite) BOOL dirty;
72
73/** returns the Z eye */
74+(float) getZEye;
75
76/** sets the camera in the defaul position */
77-(void) restore;
78/** Sets the camera using gluLookAt using its eye, center and up_vector */
79-(void) locate;
80/** sets the eye values in points */
81-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z;
82/** sets the center values in points */
83-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z;
84/** sets the up values */
85-(void) setUpX: (float)x upY:(float)y upZ:(float)z;
86
87/** get the eye vector values in points */
88-(void) eyeX:(float*)x eyeY:(float*)y eyeZ:(float*)z;
89/** get the center vector values in points */
90-(void) centerX:(float*)x centerY:(float*)y centerZ:(float*)z;
91/** get the up vector values */
92-(void) upX:(float*)x upY:(float*)y upZ:(float*)z;
93
94
95@end
diff --git a/libs/cocos2d/CCCamera.m b/libs/cocos2d/CCCamera.m new file mode 100755 index 0000000..1ef6655 --- /dev/null +++ b/libs/cocos2d/CCCamera.m
@@ -0,0 +1,131 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import "Platforms/CCGL.h"
28#import "CCCamera.h"
29#import "ccMacros.h"
30#import "CCDrawingPrimitives.h"
31
32@implementation CCCamera
33
34@synthesize dirty = dirty_;
35
36-(id) init
37{
38 if( (self=[super init]) )
39 [self restore];
40
41 return self;
42}
43
44- (NSString*) description
45{
46 return [NSString stringWithFormat:@"<%@ = %08X | center = (%.2f,%.2f,%.2f)>", [self class], self, centerX_, centerY_, centerZ_];
47}
48
49
50- (void) dealloc
51{
52 CCLOGINFO(@"cocos2d: deallocing %@", self);
53 [super dealloc];
54}
55
56-(void) restore
57{
58 eyeX_ = eyeY_ = 0;
59 eyeZ_ = [CCCamera getZEye];
60
61 centerX_ = centerY_ = centerZ_ = 0;
62
63 upX_ = 0.0f;
64 upY_ = 1.0f;
65 upZ_ = 0.0f;
66
67 dirty_ = NO;
68}
69
70-(void) locate
71{
72 if( dirty_ )
73 gluLookAt( eyeX_, eyeY_, eyeZ_,
74 centerX_, centerY_, centerZ_,
75 upX_, upY_, upZ_
76 );
77}
78
79+(float) getZEye
80{
81 return FLT_EPSILON;
82// CGSize s = [[CCDirector sharedDirector] displaySize];
83// return ( s.height / 1.1566f );
84}
85
86-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z
87{
88 eyeX_ = x * CC_CONTENT_SCALE_FACTOR();
89 eyeY_ = y * CC_CONTENT_SCALE_FACTOR();
90 eyeZ_ = z * CC_CONTENT_SCALE_FACTOR();
91 dirty_ = YES;
92}
93
94-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z
95{
96 centerX_ = x * CC_CONTENT_SCALE_FACTOR();
97 centerY_ = y * CC_CONTENT_SCALE_FACTOR();
98 centerZ_ = z * CC_CONTENT_SCALE_FACTOR();
99 dirty_ = YES;
100}
101
102-(void) setUpX: (float)x upY:(float)y upZ:(float)z
103{
104 upX_ = x;
105 upY_ = y;
106 upZ_ = z;
107 dirty_ = YES;
108}
109
110-(void) eyeX: (float*)x eyeY:(float*)y eyeZ:(float*)z
111{
112 *x = eyeX_ / CC_CONTENT_SCALE_FACTOR();
113 *y = eyeY_ / CC_CONTENT_SCALE_FACTOR();
114 *z = eyeZ_ / CC_CONTENT_SCALE_FACTOR();
115}
116
117-(void) centerX: (float*)x centerY:(float*)y centerZ:(float*)z
118{
119 *x = centerX_ / CC_CONTENT_SCALE_FACTOR();
120 *y = centerY_ / CC_CONTENT_SCALE_FACTOR();
121 *z = centerZ_ / CC_CONTENT_SCALE_FACTOR();
122}
123
124-(void) upX: (float*)x upY:(float*)y upZ:(float*)z
125{
126 *x = upX_;
127 *y = upY_;
128 *z = upZ_;
129}
130
131@end
diff --git a/libs/cocos2d/CCConfiguration.h b/libs/cocos2d/CCConfiguration.h new file mode 100755 index 0000000..04e1b55 --- /dev/null +++ b/libs/cocos2d/CCConfiguration.h
@@ -0,0 +1,116 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#import <Foundation/Foundation.h>
27
28#import "Platforms/CCGL.h"
29
30/** OS version definitions. Includes both iOS and Mac OS versions
31 */
32enum {
33 kCCiOSVersion_3_0 = 0x03000000,
34 kCCiOSVersion_3_1 = 0x03010000,
35 kCCiOSVersion_3_1_1 = 0x03010100,
36 kCCiOSVersion_3_1_2 = 0x03010200,
37 kCCiOSVersion_3_1_3 = 0x03010300,
38 kCCiOSVersion_3_2 = 0x03020000,
39 kCCiOSVersion_3_2_1 = 0x03020100,
40 kCCiOSVersion_4_0 = 0x04000000,
41 kCCiOSVersion_4_0_1 = 0x04000100,
42 kCCiOSVersion_4_1 = 0x04010000,
43 kCCiOSVersion_4_2 = 0x04020000,
44 kCCiOSVersion_4_3 = 0x04030000,
45 kCCiOSVersion_4_3_1 = 0x04030100,
46 kCCiOSVersion_4_3_2 = 0x04030200,
47 kCCiOSVersion_4_3_3 = 0x04030300,
48
49 kCCMacVersion_10_5 = 0x0a050000,
50 kCCMacVersion_10_6 = 0x0a060000,
51 kCCMacVersion_10_7 = 0x0a070000,
52};
53
54/**
55 CCConfiguration contains some openGL variables
56 @since v0.99.0
57 */
58@interface CCConfiguration : NSObject {
59
60 GLint maxTextureSize_;
61 GLint maxModelviewStackDepth_;
62 BOOL supportsPVRTC_;
63 BOOL supportsNPOT_;
64 BOOL supportsBGRA8888_;
65 BOOL supportsDiscardFramebuffer_;
66 unsigned int OSVersion_;
67 GLint maxSamplesAllowed_;
68}
69
70/** OpenGL Max texture size. */
71@property (nonatomic, readonly) GLint maxTextureSize;
72
73/** OpenGL Max Modelview Stack Depth. */
74@property (nonatomic, readonly) GLint maxModelviewStackDepth;
75
76/** Whether or not the GPU supports NPOT (Non Power Of Two) textures.
77 NPOT textures have the following limitations:
78 - They can't have mipmaps
79 - They only accept GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}
80
81 @since v0.99.2
82 */
83@property (nonatomic, readonly) BOOL supportsNPOT;
84
85/** Whether or not PVR Texture Compressed is supported */
86@property (nonatomic, readonly) BOOL supportsPVRTC;
87
88/** Whether or not BGRA8888 textures are supported.
89
90 @since v0.99.2
91 */
92@property (nonatomic, readonly) BOOL supportsBGRA8888;
93
94/** Whether or not glDiscardFramebufferEXT is supported
95
96 @since v0.99.2
97 */
98@property (nonatomic, readonly) BOOL supportsDiscardFramebuffer;
99
100/** returns the OS version.
101 - On iOS devices it returns the firmware version.
102 - On Mac returns the OS version
103
104 @since v0.99.5
105 */
106@property (nonatomic, readonly) unsigned int OSVersion;
107
108/** returns a shared instance of the CCConfiguration */
109+(CCConfiguration *) sharedConfiguration;
110
111/** returns whether or not an OpenGL is supported */
112- (BOOL) checkForGLExtension:(NSString *)searchName;
113
114
115
116@end
diff --git a/libs/cocos2d/CCConfiguration.m b/libs/cocos2d/CCConfiguration.m new file mode 100755 index 0000000..d51cd58 --- /dev/null +++ b/libs/cocos2d/CCConfiguration.m
@@ -0,0 +1,193 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#import <Availability.h>
27
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#import <UIKit/UIKit.h> // Needed for UIDevice
30#endif
31
32#import "Platforms/CCGL.h"
33#import "CCBlockSupport.h"
34#import "CCConfiguration.h"
35#import "ccMacros.h"
36#import "ccConfig.h"
37#import "Support/OpenGL_Internal.h"
38
39@implementation CCConfiguration
40
41@synthesize maxTextureSize = maxTextureSize_;
42@synthesize supportsPVRTC = supportsPVRTC_;
43@synthesize maxModelviewStackDepth = maxModelviewStackDepth_;
44@synthesize supportsNPOT = supportsNPOT_;
45@synthesize supportsBGRA8888 = supportsBGRA8888_;
46@synthesize supportsDiscardFramebuffer = supportsDiscardFramebuffer_;
47@synthesize OSVersion = OSVersion_;
48
49//
50// singleton stuff
51//
52static CCConfiguration *_sharedConfiguration = nil;
53
54static char * glExtensions;
55
56+ (CCConfiguration *)sharedConfiguration
57{
58 if (!_sharedConfiguration)
59 _sharedConfiguration = [[self alloc] init];
60
61 return _sharedConfiguration;
62}
63
64+(id)alloc
65{
66 NSAssert(_sharedConfiguration == nil, @"Attempted to allocate a second instance of a singleton.");
67 return [super alloc];
68}
69
70
71#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
72#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
73- (NSString*)getMacVersion
74{
75 SInt32 versionMajor, versionMinor, versionBugFix;
76 Gestalt(gestaltSystemVersionMajor, &versionMajor);
77 Gestalt(gestaltSystemVersionMinor, &versionMinor);
78 Gestalt(gestaltSystemVersionBugFix, &versionBugFix);
79
80 return [NSString stringWithFormat:@"%d.%d.%d", versionMajor, versionMinor, versionBugFix];
81}
82#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
83
84-(id) init
85{
86 if( (self=[super init])) {
87
88 // Obtain iOS version
89 OSVersion_ = 0;
90#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
91 NSString *OSVer = [[UIDevice currentDevice] systemVersion];
92#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
93 NSString *OSVer = [self getMacVersion];
94#endif
95 NSArray *arr = [OSVer componentsSeparatedByString:@"."];
96 int idx=0x01000000;
97 for( NSString *str in arr ) {
98 int value = [str intValue];
99 OSVersion_ += value * idx;
100 idx = idx >> 8;
101 }
102 CCLOG(@"cocos2d: OS version: %@ (0x%08x)", OSVer, OSVersion_);
103
104 CCLOG(@"cocos2d: GL_VENDOR: %s", glGetString(GL_VENDOR) );
105 CCLOG(@"cocos2d: GL_RENDERER: %s", glGetString ( GL_RENDERER ) );
106 CCLOG(@"cocos2d: GL_VERSION: %s", glGetString ( GL_VERSION ) );
107
108 glExtensions = (char*) glGetString(GL_EXTENSIONS);
109
110 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize_);
111 glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &maxModelviewStackDepth_);
112#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
113 if( OSVersion_ >= kCCiOSVersion_4_0 )
114 glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamplesAllowed_);
115 else
116 maxSamplesAllowed_ = 0;
117#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
118 glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesAllowed_);
119#endif
120
121 supportsPVRTC_ = [self checkForGLExtension:@"GL_IMG_texture_compression_pvrtc"];
122#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
123 supportsNPOT_ = [self checkForGLExtension:@"GL_APPLE_texture_2D_limited_npot"];
124#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
125 supportsNPOT_ = [self checkForGLExtension:@"GL_ARB_texture_non_power_of_two"];
126#endif
127 // It seems that somewhere between firmware iOS 3.0 and 4.2 Apple renamed
128 // GL_IMG_... to GL_APPLE.... So we should check both names
129
130#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
131 BOOL bgra8a = [self checkForGLExtension:@"GL_IMG_texture_format_BGRA8888"];
132 BOOL bgra8b = [self checkForGLExtension:@"GL_APPLE_texture_format_BGRA8888"];
133 supportsBGRA8888_ = bgra8a | bgra8b;
134#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
135 supportsBGRA8888_ = [self checkForGLExtension:@"GL_EXT_bgra"];
136#endif
137
138 supportsDiscardFramebuffer_ = [self checkForGLExtension:@"GL_EXT_discard_framebuffer"];
139
140 CCLOG(@"cocos2d: GL_MAX_TEXTURE_SIZE: %d", maxTextureSize_);
141 CCLOG(@"cocos2d: GL_MAX_MODELVIEW_STACK_DEPTH: %d",maxModelviewStackDepth_);
142 CCLOG(@"cocos2d: GL_MAX_SAMPLES: %d", maxSamplesAllowed_);
143 CCLOG(@"cocos2d: GL supports PVRTC: %s", (supportsPVRTC_ ? "YES" : "NO") );
144 CCLOG(@"cocos2d: GL supports BGRA8888 textures: %s", (supportsBGRA8888_ ? "YES" : "NO") );
145 CCLOG(@"cocos2d: GL supports NPOT textures: %s", (supportsNPOT_ ? "YES" : "NO") );
146 CCLOG(@"cocos2d: GL supports discard_framebuffer: %s", (supportsDiscardFramebuffer_ ? "YES" : "NO") );
147 CCLOG(@"cocos2d: compiled with NPOT support: %s",
148#if CC_TEXTURE_NPOT_SUPPORT
149 "YES"
150#else
151 "NO"
152#endif
153 );
154 CCLOG(@"cocos2d: compiled with VBO support in TextureAtlas : %s",
155#if CC_USES_VBO
156 "YES"
157#else
158 "NO"
159#endif
160 );
161
162 CCLOG(@"cocos2d: compiled with Affine Matrix transformation in CCNode : %s",
163#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
164 "YES"
165#else
166 "NO"
167#endif
168 );
169
170 CCLOG(@"cocos2d: compiled with Profiling Support: %s",
171#if CC_ENABLE_PROFILERS
172
173 "YES - *** Disable it when you finish profiling ***"
174#else
175 "NO"
176#endif
177 );
178
179 CHECK_GL_ERROR();
180 }
181
182 return self;
183}
184
185- (BOOL) checkForGLExtension:(NSString *)searchName
186{
187 // For best results, extensionsNames should be stored in your renderer so that it does not
188 // need to be recreated on each invocation.
189 NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding];
190 NSArray *extensionsNames = [extensionsString componentsSeparatedByString:@" "];
191 return [extensionsNames containsObject: searchName];
192}
193@end
diff --git a/libs/cocos2d/CCDirector.h b/libs/cocos2d/CCDirector.h new file mode 100755 index 0000000..9c3f3fe --- /dev/null +++ b/libs/cocos2d/CCDirector.h
@@ -0,0 +1,307 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import "ccConfig.h"
28#import "ccTypes.h"
29
30// OpenGL related
31#import "Platforms/CCGL.h"
32#import "CCProtocols.h"
33
34/** @typedef ccDirectorProjection
35 Possible OpenGL projections used by director
36 */
37typedef enum {
38 /// sets a 2D projection (orthogonal projection).
39 kCCDirectorProjection2D,
40
41 /// sets a 3D projection with a fovy=60, znear=0.5f and zfar=1500.
42 kCCDirectorProjection3D,
43
44 /// it calls "updateProjection" on the projection delegate.
45 kCCDirectorProjectionCustom,
46
47 /// Detault projection is 3D projection
48 kCCDirectorProjectionDefault = kCCDirectorProjection3D,
49
50 // backward compatibility stuff
51 CCDirectorProjection2D = kCCDirectorProjection2D,
52 CCDirectorProjection3D = kCCDirectorProjection3D,
53 CCDirectorProjectionCustom = kCCDirectorProjectionCustom,
54
55} ccDirectorProjection;
56
57
58@class CCLabelAtlas;
59@class CCScene;
60
61/**Class that creates and handle the main Window and manages how
62and when to execute the Scenes.
63
64 The CCDirector is also resposible for:
65 - initializing the OpenGL ES context
66 - setting the OpenGL pixel format (default on is RGB565)
67 - setting the OpenGL buffer depth (default one is 0-bit)
68 - setting the projection (default one is 3D)
69 - setting the orientation (default one is Protrait)
70
71 Since the CCDirector is a singleton, the standard way to use it is by calling:
72 - [[CCDirector sharedDirector] methodName];
73
74 The CCDirector also sets the default OpenGL context:
75 - GL_TEXTURE_2D is enabled
76 - GL_VERTEX_ARRAY is enabled
77 - GL_COLOR_ARRAY is enabled
78 - GL_TEXTURE_COORD_ARRAY is enabled
79*/
80@interface CCDirector : NSObject
81{
82 CC_GLVIEW *openGLView_;
83
84 // internal timer
85 NSTimeInterval animationInterval_;
86 NSTimeInterval oldAnimationInterval_;
87
88 /* display FPS ? */
89 BOOL displayFPS_;
90
91 NSUInteger frames_;
92 ccTime accumDt_;
93 ccTime frameRate_;
94#if CC_DIRECTOR_FAST_FPS
95 CCLabelAtlas *FPSLabel_;
96#endif
97
98 /* is the running scene paused */
99 BOOL isPaused_;
100
101 /* The running scene */
102 CCScene *runningScene_;
103
104 /* This object will be visited after the scene. Useful to hook a notification node */
105 id notificationNode_;
106
107 /* will be the next 'runningScene' in the next frame
108 nextScene is a weak reference. */
109 CCScene *nextScene_;
110
111 /* If YES, then "old" scene will receive the cleanup message */
112 BOOL sendCleanupToScene_;
113
114 /* scheduled scenes */
115 NSMutableArray *scenesStack_;
116
117 /* last time the main loop was updated */
118 struct timeval lastUpdate_;
119 /* delta time since last tick to main loop */
120 ccTime dt;
121 /* whether or not the next delta time will be zero */
122 BOOL nextDeltaTimeZero_;
123
124 /* projection used */
125 ccDirectorProjection projection_;
126
127 /* Projection protocol delegate */
128 id<CCProjectionProtocol> projectionDelegate_;
129
130 /* window size in points */
131 CGSize winSizeInPoints_;
132
133 /* window size in pixels */
134 CGSize winSizeInPixels_;
135
136 /* the cocos2d running thread */
137 NSThread *runningThread_;
138
139 // profiler
140#if CC_ENABLE_PROFILERS
141 ccTime accumDtForProfiler_;
142#endif
143}
144
145/** returns the cocos2d thread.
146 If you want to run any cocos2d task, run it in this thread.
147 On iOS usually it is the main thread.
148 @since v0.99.5
149 */
150@property (readonly, nonatomic ) NSThread *runningThread;
151/** The current running Scene. Director can only run one Scene at the time */
152@property (nonatomic,readonly) CCScene* runningScene;
153/** The FPS value */
154@property (nonatomic,readwrite, assign) NSTimeInterval animationInterval;
155/** Whether or not to display the FPS on the bottom-left corner */
156@property (nonatomic,readwrite, assign) BOOL displayFPS;
157/** The OpenGLView, where everything is rendered */
158@property (nonatomic,readwrite,retain) CC_GLVIEW *openGLView;
159/** whether or not the next delta time will be zero */
160@property (nonatomic,readwrite,assign) BOOL nextDeltaTimeZero;
161/** Whether or not the Director is paused */
162@property (nonatomic,readonly) BOOL isPaused;
163/** Sets an OpenGL projection
164 @since v0.8.2
165 */
166@property (nonatomic,readwrite) ccDirectorProjection projection;
167/** How many frames were called since the director started */
168@property (readonly) NSUInteger frames;
169
170/** Whether or not the replaced scene will receive the cleanup message.
171 If the new scene is pushed, then the old scene won't receive the "cleanup" message.
172 If the new scene replaces the old one, the it will receive the "cleanup" message.
173 @since v0.99.0
174 */
175@property (nonatomic, readonly) BOOL sendCleanupToScene;
176
177/** This object will be visited after the main scene is visited.
178 This object MUST implement the "visit" selector.
179 Useful to hook a notification object, like CCNotifications (http://github.com/manucorporat/CCNotifications)
180 @since v0.99.5
181 */
182@property (nonatomic, readwrite, retain) id notificationNode;
183
184/** This object will be called when the OpenGL projection is udpated and only when the kCCDirectorProjectionCustom projection is used.
185 @since v0.99.5
186 */
187@property (nonatomic, readwrite, retain) id<CCProjectionProtocol> projectionDelegate;
188
189/** returns a shared instance of the director */
190+(CCDirector *)sharedDirector;
191
192
193
194// Window size
195
196/** returns the size of the OpenGL view in points.
197 It takes into account any possible rotation (device orientation) of the window
198 */
199- (CGSize) winSize;
200
201/** returns the size of the OpenGL view in pixels.
202 It takes into account any possible rotation (device orientation) of the window.
203 On Mac winSize and winSizeInPixels return the same value.
204 */
205- (CGSize) winSizeInPixels;
206/** returns the display size of the OpenGL view in pixels.
207 It doesn't take into account any possible rotation of the window.
208 */
209-(CGSize) displaySizeInPixels;
210/** changes the projection size */
211-(void) reshapeProjection:(CGSize)newWindowSize;
212
213/** converts a UIKit coordinate to an OpenGL coordinate
214 Useful to convert (multi) touchs coordinates to the current layout (portrait or landscape)
215 */
216-(CGPoint) convertToGL: (CGPoint) p;
217/** converts an OpenGL coordinate to a UIKit coordinate
218 Useful to convert node points to window points for calls such as glScissor
219 */
220-(CGPoint) convertToUI:(CGPoint)p;
221
222/// XXX: missing description
223-(float) getZEye;
224
225// Scene Management
226
227/**Enters the Director's main loop with the given Scene.
228 * Call it to run only your FIRST scene.
229 * Don't call it if there is already a running scene.
230 */
231- (void) runWithScene:(CCScene*) scene;
232
233/**Suspends the execution of the running scene, pushing it on the stack of suspended scenes.
234 * The new scene will be executed.
235 * Try to avoid big stacks of pushed scenes to reduce memory allocation.
236 * ONLY call it if there is a running scene.
237 */
238- (void) pushScene:(CCScene*) scene;
239
240/**Pops out a scene from the queue.
241 * This scene will replace the running one.
242 * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated.
243 * ONLY call it if there is a running scene.
244 */
245- (void) popScene;
246
247/** Replaces the running scene with a new one. The running scene is terminated.
248 * ONLY call it if there is a running scene.
249 */
250-(void) replaceScene: (CCScene*) scene;
251
252/** Ends the execution, releases the running scene.
253 It doesn't remove the OpenGL view from its parent. You have to do it manually.
254 */
255-(void) end;
256
257/** Pauses the running scene.
258 The running scene will be _drawed_ but all scheduled timers will be paused
259 While paused, the draw rate will be 4 FPS to reduce CPU consuption
260 */
261-(void) pause;
262
263/** Resumes the paused scene
264 The scheduled timers will be activated again.
265 The "delta time" will be 0 (as if the game wasn't paused)
266 */
267-(void) resume;
268
269/** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore.
270 If you wan't to pause your animation call [pause] instead.
271 */
272-(void) stopAnimation;
273
274/** The main loop is triggered again.
275 Call this function only if [stopAnimation] was called earlier
276 @warning Dont' call this function to start the main loop. To run the main loop call runWithScene
277 */
278-(void) startAnimation;
279
280/** Draw the scene.
281 This method is called every frame. Don't call it manually.
282 */
283-(void) drawScene;
284
285// Memory Helper
286
287/** Removes all the cocos2d data that was cached automatically.
288 It will purge the CCTextureCache, CCLabelBMFont cache.
289 IMPORTANT: The CCSpriteFrameCache won't be purged. If you want to purge it, you have to purge it manually.
290 @since v0.99.3
291 */
292-(void) purgeCachedData;
293
294// OpenGL Helper
295
296/** sets the OpenGL default values */
297-(void) setGLDefaultValues;
298
299/** enables/disables OpenGL alpha blending */
300- (void) setAlphaBlending: (BOOL) on;
301/** enables/disables OpenGL depth test */
302- (void) setDepthTest: (BOOL) on;
303
304// Profiler
305-(void) showProfilers;
306
307@end
diff --git a/libs/cocos2d/CCDirector.m b/libs/cocos2d/CCDirector.m new file mode 100755 index 0000000..292bc28 --- /dev/null +++ b/libs/cocos2d/CCDirector.m
@@ -0,0 +1,565 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27/* Idea of decoupling Window from Director taken from OC3D project: http://code.google.com/p/oc3d/
28 */
29
30#import <unistd.h>
31#import <Availability.h>
32
33// cocos2d imports
34#import "CCDirector.h"
35#import "CCScheduler.h"
36#import "CCActionManager.h"
37#import "CCTextureCache.h"
38#import "CCAnimationCache.h"
39#import "CCLabelAtlas.h"
40#import "ccMacros.h"
41#import "CCTransition.h"
42#import "CCScene.h"
43#import "CCSpriteFrameCache.h"
44#import "CCTexture2D.h"
45#import "CCLabelBMFont.h"
46#import "CCLayer.h"
47
48// support imports
49#import "Platforms/CCGL.h"
50#import "Platforms/CCNS.h"
51
52#import "Support/OpenGL_Internal.h"
53#import "Support/CGPointExtension.h"
54
55#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
56#import "Platforms/iOS/CCDirectorIOS.h"
57#define CC_DIRECTOR_DEFAULT CCDirectorTimer
58#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
59#import "Platforms/Mac/CCDirectorMac.h"
60#define CC_DIRECTOR_DEFAULT CCDirectorDisplayLink
61#endif
62
63#import "Support/CCProfiling.h"
64
65#define kDefaultFPS 60.0 // 60 frames per second
66
67extern NSString * cocos2dVersion(void);
68
69
70@interface CCDirector (Private)
71-(void) setNextScene;
72// shows the FPS in the screen
73-(void) showFPS;
74// calculates delta time since last time it was called
75-(void) calculateDeltaTime;
76@end
77
78@implementation CCDirector
79
80@synthesize animationInterval = animationInterval_;
81@synthesize runningScene = runningScene_;
82@synthesize displayFPS = displayFPS_;
83@synthesize nextDeltaTimeZero = nextDeltaTimeZero_;
84@synthesize isPaused = isPaused_;
85@synthesize sendCleanupToScene = sendCleanupToScene_;
86@synthesize runningThread = runningThread_;
87@synthesize notificationNode = notificationNode_;
88@synthesize projectionDelegate = projectionDelegate_;
89@synthesize frames = frames_;
90//
91// singleton stuff
92//
93static CCDirector *_sharedDirector = nil;
94
95+ (CCDirector *)sharedDirector
96{
97 if (!_sharedDirector) {
98
99 //
100 // Default Director is TimerDirector
101 //
102 if( [ [CCDirector class] isEqual:[self class]] )
103 _sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init];
104 else
105 _sharedDirector = [[self alloc] init];
106 }
107
108 return _sharedDirector;
109}
110
111+(id)alloc
112{
113 NSAssert(_sharedDirector == nil, @"Attempted to allocate a second instance of a singleton.");
114 return [super alloc];
115}
116
117- (id) init
118{
119 CCLOG(@"cocos2d: %@", cocos2dVersion() );
120
121 if( (self=[super init]) ) {
122
123 CCLOG(@"cocos2d: Using Director Type:%@", [self class]);
124
125 // scenes
126 runningScene_ = nil;
127 nextScene_ = nil;
128
129 notificationNode_ = nil;
130
131 oldAnimationInterval_ = animationInterval_ = 1.0 / kDefaultFPS;
132 scenesStack_ = [[NSMutableArray alloc] initWithCapacity:10];
133
134 // Set default projection (3D)
135 projection_ = kCCDirectorProjectionDefault;
136
137 // projection delegate if "Custom" projection is used
138 projectionDelegate_ = nil;
139
140 // FPS
141 displayFPS_ = NO;
142 frames_ = 0;
143
144 // paused ?
145 isPaused_ = NO;
146
147 // running thread
148 runningThread_ = nil;
149
150 winSizeInPixels_ = winSizeInPoints_ = CGSizeZero;
151 }
152
153 return self;
154}
155
156- (void) dealloc
157{
158 CCLOGINFO(@"cocos2d: deallocing %@", self);
159
160#if CC_DIRECTOR_FAST_FPS
161 [FPSLabel_ release];
162#endif
163 [runningScene_ release];
164 [notificationNode_ release];
165 [scenesStack_ release];
166
167 [projectionDelegate_ release];
168
169 _sharedDirector = nil;
170
171 [super dealloc];
172}
173
174-(void) setGLDefaultValues
175{
176 // This method SHOULD be called only after openGLView_ was initialized
177 NSAssert( openGLView_, @"openGLView_ must be initialized");
178
179 [self setAlphaBlending: YES];
180 [self setDepthTest: YES];
181 [self setProjection: projection_];
182
183 // set other opengl default values
184 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
185
186#if CC_DIRECTOR_FAST_FPS
187 if (!FPSLabel_) {
188 CCTexture2DPixelFormat currentFormat = [CCTexture2D defaultAlphaPixelFormat];
189 [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444];
190 FPSLabel_ = [[CCLabelAtlas labelWithString:@"00.0" charMapFile:@"fps_images.png" itemWidth:16 itemHeight:24 startCharMap:'.'] retain];
191 [CCTexture2D setDefaultAlphaPixelFormat:currentFormat];
192 }
193#endif // CC_DIRECTOR_FAST_FPS
194}
195
196//
197// Draw the Scene
198//
199- (void) drawScene
200{
201 // Override me
202}
203
204-(void) calculateDeltaTime
205{
206 struct timeval now;
207
208 if( gettimeofday( &now, NULL) != 0 ) {
209 CCLOG(@"cocos2d: error in gettimeofday");
210 dt = 0;
211 return;
212 }
213
214 // new delta time
215 if( nextDeltaTimeZero_ ) {
216 dt = 0;
217 nextDeltaTimeZero_ = NO;
218 } else {
219 dt = (now.tv_sec - lastUpdate_.tv_sec) + (now.tv_usec - lastUpdate_.tv_usec) / 1000000.0f;
220 dt = MAX(0,dt);
221 }
222
223#ifdef DEBUG
224 // If we are debugging our code, prevent big delta time
225 if( dt > 0.2f )
226 dt = 1/60.0f;
227#endif
228
229 lastUpdate_ = now;
230}
231
232#pragma mark Director - Memory Helper
233
234-(void) purgeCachedData
235{
236 [CCLabelBMFont purgeCachedData];
237 [[CCTextureCache sharedTextureCache] removeUnusedTextures];
238}
239
240#pragma mark Director - Scene OpenGL Helper
241
242-(ccDirectorProjection) projection
243{
244 return projection_;
245}
246
247-(float) getZEye
248{
249 return ( winSizeInPixels_.height / 1.1566f );
250}
251
252-(void) setProjection:(ccDirectorProjection)projection
253{
254 CCLOG(@"cocos2d: override me");
255}
256
257- (void) setAlphaBlending: (BOOL) on
258{
259 if (on) {
260 glEnable(GL_BLEND);
261 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
262
263 } else
264 glDisable(GL_BLEND);
265}
266
267- (void) setDepthTest: (BOOL) on
268{
269 if (on) {
270 ccglClearDepth(1.0f);
271 glEnable(GL_DEPTH_TEST);
272 glDepthFunc(GL_LEQUAL);
273// glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
274 } else
275 glDisable( GL_DEPTH_TEST );
276}
277
278#pragma mark Director Integration with a UIKit view
279
280-(CC_GLVIEW*) openGLView
281{
282 return openGLView_;
283}
284
285-(void) setOpenGLView:(CC_GLVIEW *)view
286{
287 NSAssert( view, @"OpenGLView must be non-nil");
288
289 if( view != openGLView_ ) {
290 [openGLView_ release];
291 openGLView_ = [view retain];
292
293 // set size
294 winSizeInPixels_ = winSizeInPoints_ = CCNSSizeToCGSize( [view bounds].size );
295
296 [self setGLDefaultValues];
297 }
298}
299
300#pragma mark Director Scene Landscape
301
302-(CGPoint)convertToGL:(CGPoint)uiPoint
303{
304 CCLOG(@"CCDirector#convertToGL: OVERRIDE ME.");
305 return CGPointZero;
306}
307
308-(CGPoint)convertToUI:(CGPoint)glPoint
309{
310 CCLOG(@"CCDirector#convertToUI: OVERRIDE ME.");
311 return CGPointZero;
312}
313
314-(CGSize)winSize
315{
316 return winSizeInPoints_;
317}
318
319-(CGSize)winSizeInPixels
320{
321 return winSizeInPixels_;
322}
323
324-(CGSize)displaySizeInPixels
325{
326 return winSizeInPixels_;
327}
328
329-(void) reshapeProjection:(CGSize)newWindowSize
330{
331 winSizeInPixels_ = winSizeInPoints_ = newWindowSize;
332 [self setProjection:projection_];
333}
334
335#pragma mark Director Scene Management
336
337- (void)runWithScene:(CCScene*) scene
338{
339 NSAssert( scene != nil, @"Argument must be non-nil");
340 NSAssert( runningScene_ == nil, @"You can't run an scene if another Scene is running. Use replaceScene or pushScene instead");
341
342 [self pushScene:scene];
343 [self startAnimation];
344}
345
346-(void) replaceScene: (CCScene*) scene
347{
348 NSAssert( scene != nil, @"Argument must be non-nil");
349
350 NSUInteger index = [scenesStack_ count];
351
352 sendCleanupToScene_ = YES;
353 [scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
354 nextScene_ = scene; // nextScene_ is a weak ref
355}
356
357- (void) pushScene: (CCScene*) scene
358{
359 NSAssert( scene != nil, @"Argument must be non-nil");
360
361 sendCleanupToScene_ = NO;
362
363 [scenesStack_ addObject: scene];
364 nextScene_ = scene; // nextScene_ is a weak ref
365}
366
367-(void) popScene
368{
369 NSAssert( runningScene_ != nil, @"A running Scene is needed");
370
371 [scenesStack_ removeLastObject];
372 NSUInteger c = [scenesStack_ count];
373
374 if( c == 0 )
375 [self end];
376 else {
377 sendCleanupToScene_ = YES;
378 nextScene_ = [scenesStack_ objectAtIndex:c-1];
379 }
380}
381
382-(void) end
383{
384 [runningScene_ onExit];
385 [runningScene_ cleanup];
386 [runningScene_ release];
387
388 runningScene_ = nil;
389 nextScene_ = nil;
390
391 // remove all objects, but don't release it.
392 // runWithScene might be executed after 'end'.
393 [scenesStack_ removeAllObjects];
394
395 [self stopAnimation];
396
397#if CC_DIRECTOR_FAST_FPS
398 [FPSLabel_ release];
399 FPSLabel_ = nil;
400#endif
401
402 [projectionDelegate_ release];
403 projectionDelegate_ = nil;
404
405 // Purge bitmap cache
406 [CCLabelBMFont purgeCachedData];
407
408 // Purge all managers
409 [CCAnimationCache purgeSharedAnimationCache];
410 [CCSpriteFrameCache purgeSharedSpriteFrameCache];
411 [CCScheduler purgeSharedScheduler];
412 [CCActionManager purgeSharedManager];
413 [CCTextureCache purgeSharedTextureCache];
414
415
416 // OpenGL view
417
418 // Since the director doesn't attach the openglview to the window
419 // it shouldn't remove it from the window too.
420// [openGLView_ removeFromSuperview];
421
422 [openGLView_ release];
423 openGLView_ = nil;
424}
425
426-(void) setNextScene
427{
428 Class transClass = [CCTransitionScene class];
429 BOOL runningIsTransition = [runningScene_ isKindOfClass:transClass];
430 BOOL newIsTransition = [nextScene_ isKindOfClass:transClass];
431
432 // If it is not a transition, call onExit/cleanup
433 if( ! newIsTransition ) {
434 [runningScene_ onExit];
435
436 // issue #709. the root node (scene) should receive the cleanup message too
437 // otherwise it might be leaked.
438 if( sendCleanupToScene_)
439 [runningScene_ cleanup];
440 }
441
442 [runningScene_ release];
443
444 runningScene_ = [nextScene_ retain];
445 nextScene_ = nil;
446
447 if( ! runningIsTransition ) {
448 [runningScene_ onEnter];
449 [runningScene_ onEnterTransitionDidFinish];
450 }
451}
452
453-(void) pause
454{
455 if( isPaused_ )
456 return;
457
458 oldAnimationInterval_ = animationInterval_;
459
460 // when paused, don't consume CPU
461 [self setAnimationInterval:1/4.0];
462 isPaused_ = YES;
463}
464
465-(void) resume
466{
467 if( ! isPaused_ )
468 return;
469
470 [self setAnimationInterval: oldAnimationInterval_];
471
472 if( gettimeofday( &lastUpdate_, NULL) != 0 ) {
473 CCLOG(@"cocos2d: Director: Error in gettimeofday");
474 }
475
476 isPaused_ = NO;
477 dt = 0;
478}
479
480- (void)startAnimation
481{
482 CCLOG(@"cocos2d: Director#startAnimation. Override me");
483}
484
485- (void)stopAnimation
486{
487 CCLOG(@"cocos2d: Director#stopAnimation. Override me");
488}
489
490- (void)setAnimationInterval:(NSTimeInterval)interval
491{
492 CCLOG(@"cocos2d: Director#setAnimationInterval. Override me");
493}
494
495#if CC_DIRECTOR_FAST_FPS
496
497// display the FPS using a LabelAtlas
498// updates the FPS every frame
499-(void) showFPS
500{
501 frames_++;
502 accumDt_ += dt;
503
504 if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) {
505 frameRate_ = frames_/accumDt_;
506 frames_ = 0;
507 accumDt_ = 0;
508
509// sprintf(format,"%.1f",frameRate);
510// [FPSLabel setCString:format];
511
512 NSString *str = [[NSString alloc] initWithFormat:@"%.1f", frameRate_];
513 [FPSLabel_ setString:str];
514 [str release];
515 }
516
517 [FPSLabel_ draw];
518}
519#else
520// display the FPS using a manually generated Texture (very slow)
521// updates the FPS 3 times per second aprox.
522-(void) showFPS
523{
524 frames_++;
525 accumDt_ += dt;
526
527 if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) {
528 frameRate_ = frames_/accumDt_;
529 frames_ = 0;
530 accumDt_ = 0;
531 }
532
533 NSString *str = [NSString stringWithFormat:@"%.2f",frameRate_];
534 CCTexture2D *texture = [[CCTexture2D alloc] initWithString:str dimensions:CGSizeMake(100,30) alignment:CCTextAlignmentLeft fontName:@"Arial" fontSize:24];
535
536 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
537 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
538 // Unneeded states: GL_COLOR_ARRAY
539 glDisableClientState(GL_COLOR_ARRAY);
540
541 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
542
543 glColor4ub(224,224,244,200);
544 [texture drawAtPoint: ccp(5,2)];
545 [texture release];
546
547 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
548
549 // restore default GL state
550 glEnableClientState(GL_COLOR_ARRAY);
551}
552#endif
553
554- (void) showProfilers {
555#if CC_ENABLE_PROFILERS
556 accumDtForProfiler_ += dt;
557 if (accumDtForProfiler_ > 1.0f) {
558 accumDtForProfiler_ = 0;
559 [[CCProfiler sharedProfiler] displayTimers];
560 }
561#endif // CC_ENABLE_PROFILERS
562}
563
564@end
565
diff --git a/libs/cocos2d/CCDrawingPrimitives.h b/libs/cocos2d/CCDrawingPrimitives.h new file mode 100755 index 0000000..8d1dbe5 --- /dev/null +++ b/libs/cocos2d/CCDrawingPrimitives.h
@@ -0,0 +1,92 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#ifndef __CC_DRAWING_PRIMITIVES_H
28#define __CC_DRAWING_PRIMITIVES_H
29
30#import <Availability.h>
31#import <Foundation/Foundation.h>
32
33#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
34#import <CoreGraphics/CGGeometry.h> // for CGPoint
35#endif
36
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42/**
43 @file
44 Drawing OpenGL ES primitives.
45 - ccDrawPoint
46 - ccDrawLine
47 - ccDrawPoly
48 - ccDrawCircle
49 - ccDrawQuadBezier
50 - ccDrawCubicBezier
51
52 You can change the color, width and other property by calling the
53 glColor4ub(), glLineWidth(), glPointSize().
54
55 @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. If you are going to make a game that depends on these primitives, I suggest creating a batch.
56 */
57
58
59/** draws a point given x and y coordinate measured in points. */
60void ccDrawPoint( CGPoint point );
61
62/** draws an array of points.
63 @since v0.7.2
64 */
65void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints );
66
67/** draws a line given the origin and destination point measured in points. */
68void ccDrawLine( CGPoint origin, CGPoint destination );
69
70/** draws a poligon given a pointer to CGPoint coordiantes and the number of vertices measured in points.
71 The polygon can be closed or open
72 */
73void ccDrawPoly( const CGPoint *vertices, NSUInteger numOfVertices, BOOL closePolygon );
74
75/** draws a circle given the center, radius and number of segments measured in points */
76void ccDrawCircle( CGPoint center, float radius, float angle, NSUInteger segments, BOOL drawLineToCenter);
77
78/** draws a quad bezier path measured in points.
79 @since v0.8
80 */
81void ccDrawQuadBezier(CGPoint origin, CGPoint control, CGPoint destination, NSUInteger segments);
82
83/** draws a cubic bezier path measured in points.
84 @since v0.8
85 */
86void ccDrawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments);
87
88#ifdef __cplusplus
89}
90#endif
91
92#endif // __CC_DRAWING_PRIMITIVES_H
diff --git a/libs/cocos2d/CCDrawingPrimitives.m b/libs/cocos2d/CCDrawingPrimitives.m new file mode 100755 index 0000000..f7df2b6 --- /dev/null +++ b/libs/cocos2d/CCDrawingPrimitives.m
@@ -0,0 +1,272 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#import <math.h>
27#import <stdlib.h>
28#import <string.h>
29
30#import "CCDrawingPrimitives.h"
31#import "ccTypes.h"
32#import "ccMacros.h"
33#import "Platforms/CCGL.h"
34
35void ccDrawPoint( CGPoint point )
36{
37 ccVertex2F p = (ccVertex2F) {point.x * CC_CONTENT_SCALE_FACTOR(), point.y * CC_CONTENT_SCALE_FACTOR() };
38
39 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
40 // Needed states: GL_VERTEX_ARRAY,
41 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
42 glDisable(GL_TEXTURE_2D);
43 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
44 glDisableClientState(GL_COLOR_ARRAY);
45
46 glVertexPointer(2, GL_FLOAT, 0, &p);
47 glDrawArrays(GL_POINTS, 0, 1);
48
49 // restore default state
50 glEnableClientState(GL_COLOR_ARRAY);
51 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
52 glEnable(GL_TEXTURE_2D);
53}
54
55void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints )
56{
57 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
58 // Needed states: GL_VERTEX_ARRAY,
59 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
60 glDisable(GL_TEXTURE_2D);
61 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
62 glDisableClientState(GL_COLOR_ARRAY);
63
64 ccVertex2F newPoints[numberOfPoints];
65
66 // iPhone and 32-bit machines optimization
67 if( sizeof(CGPoint) == sizeof(ccVertex2F) ) {
68
69 // points ?
70 if( CC_CONTENT_SCALE_FACTOR() != 1 ) {
71 for( NSUInteger i=0; i<numberOfPoints;i++)
72 newPoints[i] = (ccVertex2F){ points[i].x * CC_CONTENT_SCALE_FACTOR(), points[i].y * CC_CONTENT_SCALE_FACTOR() };
73
74 glVertexPointer(2, GL_FLOAT, 0, newPoints);
75
76 } else
77 glVertexPointer(2, GL_FLOAT, 0, points);
78
79 glDrawArrays(GL_POINTS, 0, (GLsizei) numberOfPoints);
80
81 } else {
82
83 // Mac on 64-bit
84 for( NSUInteger i=0; i<numberOfPoints;i++)
85 newPoints[i] = (ccVertex2F) { points[i].x, points[i].y };
86
87 glVertexPointer(2, GL_FLOAT, 0, newPoints);
88 glDrawArrays(GL_POINTS, 0, (GLsizei) numberOfPoints);
89
90 }
91
92
93 // restore default state
94 glEnableClientState(GL_COLOR_ARRAY);
95 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
96 glEnable(GL_TEXTURE_2D);
97}
98
99
100void ccDrawLine( CGPoint origin, CGPoint destination )
101{
102 ccVertex2F vertices[2] = {
103 {origin.x * CC_CONTENT_SCALE_FACTOR(), origin.y * CC_CONTENT_SCALE_FACTOR() },
104 {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() }
105 };
106
107 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
108 // Needed states: GL_VERTEX_ARRAY,
109 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
110 glDisable(GL_TEXTURE_2D);
111 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
112 glDisableClientState(GL_COLOR_ARRAY);
113
114 glVertexPointer(2, GL_FLOAT, 0, vertices);
115 glDrawArrays(GL_LINES, 0, 2);
116
117 // restore default state
118 glEnableClientState(GL_COLOR_ARRAY);
119 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
120 glEnable(GL_TEXTURE_2D);
121}
122
123
124void ccDrawPoly( const CGPoint *poli, NSUInteger numberOfPoints, BOOL closePolygon )
125{
126 ccVertex2F newPoint[numberOfPoints];
127
128 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
129 // Needed states: GL_VERTEX_ARRAY,
130 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
131 glDisable(GL_TEXTURE_2D);
132 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
133 glDisableClientState(GL_COLOR_ARRAY);
134
135
136 // iPhone and 32-bit machines
137 if( sizeof(CGPoint) == sizeof(ccVertex2F) ) {
138
139 // convert to pixels ?
140 if( CC_CONTENT_SCALE_FACTOR() != 1 ) {
141 memcpy( newPoint, poli, numberOfPoints * sizeof(ccVertex2F) );
142 for( NSUInteger i=0; i<numberOfPoints;i++)
143 newPoint[i] = (ccVertex2F) { poli[i].x * CC_CONTENT_SCALE_FACTOR(), poli[i].y * CC_CONTENT_SCALE_FACTOR() };
144
145 glVertexPointer(2, GL_FLOAT, 0, newPoint);
146
147 } else
148 glVertexPointer(2, GL_FLOAT, 0, poli);
149
150
151 } else {
152 // 64-bit machines (Mac)
153
154 for( NSUInteger i=0; i<numberOfPoints;i++)
155 newPoint[i] = (ccVertex2F) { poli[i].x, poli[i].y };
156
157 glVertexPointer(2, GL_FLOAT, 0, newPoint );
158
159 }
160
161 if( closePolygon )
162 glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) numberOfPoints);
163 else
164 glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) numberOfPoints);
165
166 // restore default state
167 glEnableClientState(GL_COLOR_ARRAY);
168 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
169 glEnable(GL_TEXTURE_2D);
170}
171
172void ccDrawCircle( CGPoint center, float r, float a, NSUInteger segs, BOOL drawLineToCenter)
173{
174 int additionalSegment = 1;
175 if (drawLineToCenter)
176 additionalSegment++;
177
178 const float coef = 2.0f * (float)M_PI/segs;
179
180 GLfloat *vertices = calloc( sizeof(GLfloat)*2*(segs+2), 1);
181 if( ! vertices )
182 return;
183
184 for(NSUInteger i=0;i<=segs;i++)
185 {
186 float rads = i*coef;
187 GLfloat j = r * cosf(rads + a) + center.x;
188 GLfloat k = r * sinf(rads + a) + center.y;
189
190 vertices[i*2] = j * CC_CONTENT_SCALE_FACTOR();
191 vertices[i*2+1] =k * CC_CONTENT_SCALE_FACTOR();
192 }
193 vertices[(segs+1)*2] = center.x * CC_CONTENT_SCALE_FACTOR();
194 vertices[(segs+1)*2+1] = center.y * CC_CONTENT_SCALE_FACTOR();
195
196 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
197 // Needed states: GL_VERTEX_ARRAY,
198 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
199 glDisable(GL_TEXTURE_2D);
200 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
201 glDisableClientState(GL_COLOR_ARRAY);
202
203 glVertexPointer(2, GL_FLOAT, 0, vertices);
204 glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segs+additionalSegment);
205
206 // restore default state
207 glEnableClientState(GL_COLOR_ARRAY);
208 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
209 glEnable(GL_TEXTURE_2D);
210
211 free( vertices );
212}
213
214void ccDrawQuadBezier(CGPoint origin, CGPoint control, CGPoint destination, NSUInteger segments)
215{
216 ccVertex2F vertices[segments + 1];
217
218 float t = 0.0f;
219 for(NSUInteger i = 0; i < segments; i++)
220 {
221 GLfloat x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x;
222 GLfloat y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y;
223 vertices[i] = (ccVertex2F) {x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() };
224 t += 1.0f / segments;
225 }
226 vertices[segments] = (ccVertex2F) {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() };
227
228 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
229 // Needed states: GL_VERTEX_ARRAY,
230 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
231 glDisable(GL_TEXTURE_2D);
232 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
233 glDisableClientState(GL_COLOR_ARRAY);
234
235 glVertexPointer(2, GL_FLOAT, 0, vertices);
236 glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
237
238 // restore default state
239 glEnableClientState(GL_COLOR_ARRAY);
240 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
241 glEnable(GL_TEXTURE_2D);
242}
243
244void ccDrawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments)
245{
246 ccVertex2F vertices[segments + 1];
247
248 float t = 0;
249 for(NSUInteger i = 0; i < segments; i++)
250 {
251 GLfloat x = powf(1 - t, 3) * origin.x + 3.0f * powf(1 - t, 2) * t * control1.x + 3.0f * (1 - t) * t * t * control2.x + t * t * t * destination.x;
252 GLfloat y = powf(1 - t, 3) * origin.y + 3.0f * powf(1 - t, 2) * t * control1.y + 3.0f * (1 - t) * t * t * control2.y + t * t * t * destination.y;
253 vertices[i] = (ccVertex2F) {x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() };
254 t += 1.0f / segments;
255 }
256 vertices[segments] = (ccVertex2F) {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() };
257
258 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
259 // Needed states: GL_VERTEX_ARRAY,
260 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
261 glDisable(GL_TEXTURE_2D);
262 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
263 glDisableClientState(GL_COLOR_ARRAY);
264
265 glVertexPointer(2, GL_FLOAT, 0, vertices);
266 glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
267
268 // restore default state
269 glEnableClientState(GL_COLOR_ARRAY);
270 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
271 glEnable(GL_TEXTURE_2D);
272}
diff --git a/libs/cocos2d/CCGrabber.h b/libs/cocos2d/CCGrabber.h new file mode 100755 index 0000000..f1ce6cb --- /dev/null +++ b/libs/cocos2d/CCGrabber.h
@@ -0,0 +1,43 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "Platforms/CCGL.h"
28#import <Foundation/Foundation.h>
29
30@class CCTexture2D;
31
32/** FBO class that grabs the the contents of the screen */
33@interface CCGrabber : NSObject
34{
35 GLuint fbo;
36 GLint oldFBO;
37}
38
39-(void)grab:(CCTexture2D*)texture;
40-(void)beforeRender:(CCTexture2D*)texture;
41-(void)afterRender:(CCTexture2D*)texture;
42
43@end
diff --git a/libs/cocos2d/CCGrabber.m b/libs/cocos2d/CCGrabber.m new file mode 100755 index 0000000..a259091 --- /dev/null +++ b/libs/cocos2d/CCGrabber.m
@@ -0,0 +1,95 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "Platforms/CCGL.h"
28#import "CCGrabber.h"
29#import "ccMacros.h"
30#import "CCTexture2D.h"
31#import "Support/OpenGL_Internal.h"
32
33@implementation CCGrabber
34
35-(id) init
36{
37 if(( self = [super init] )) {
38 // generate FBO
39 ccglGenFramebuffers(1, &fbo);
40 }
41 return self;
42}
43
44-(void)grab:(CCTexture2D*)texture
45{
46 glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO);
47
48 // bind
49 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo);
50
51 // associate texture with FBO
52 ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.name, 0);
53
54 // check if it worked (probably worth doing :) )
55 GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER);
56 if (status != CC_GL_FRAMEBUFFER_COMPLETE)
57 [NSException raise:@"Frame Grabber" format:@"Could not attach texture to framebuffer"];
58
59 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO);
60}
61
62-(void)beforeRender:(CCTexture2D*)texture
63{
64 glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO);
65 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo);
66
67 // BUG XXX: doesn't work with RGB565.
68
69
70 glClearColor(0,0,0,0);
71
72 // BUG #631: To fix #631, uncomment the lines with #631
73 // Warning: But it CCGrabber won't work with 2 effects at the same time
74// glClearColor(0.0f,0.0f,0.0f,1.0f); // #631
75
76 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
77
78// glColorMask(TRUE, TRUE, TRUE, FALSE); // #631
79
80}
81
82-(void)afterRender:(CCTexture2D*)texture
83{
84 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO);
85// glColorMask(TRUE, TRUE, TRUE, TRUE); // #631
86}
87
88- (void) dealloc
89{
90 CCLOGINFO(@"cocos2d: deallocing %@", self);
91 ccglDeleteFramebuffers(1, &fbo);
92 [super dealloc];
93}
94
95@end
diff --git a/libs/cocos2d/CCGrid.h b/libs/cocos2d/CCGrid.h new file mode 100755 index 0000000..e5e77e8 --- /dev/null +++ b/libs/cocos2d/CCGrid.h
@@ -0,0 +1,121 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28
29#import "CCNode.h"
30#import "CCCamera.h"
31#import "ccTypes.h"
32
33@class CCTexture2D;
34@class CCGrabber;
35
36/** Base class for other
37 */
38@interface CCGridBase : NSObject
39{
40 BOOL active_;
41 int reuseGrid_;
42 ccGridSize gridSize_;
43 CCTexture2D *texture_;
44 CGPoint step_;
45 CCGrabber *grabber_;
46 BOOL isTextureFlipped_;
47}
48
49/** wheter or not the grid is active */
50@property (nonatomic,readwrite) BOOL active;
51/** number of times that the grid will be reused */
52@property (nonatomic,readwrite) int reuseGrid;
53/** size of the grid */
54@property (nonatomic,readonly) ccGridSize gridSize;
55/** pixels between the grids */
56@property (nonatomic,readwrite) CGPoint step;
57/** texture used */
58@property (nonatomic, retain) CCTexture2D *texture;
59/** grabber used */
60@property (nonatomic, retain) CCGrabber *grabber;
61/** is texture flipped */
62@property (nonatomic, readwrite) BOOL isTextureFlipped;
63
64+(id) gridWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped;
65+(id) gridWithSize:(ccGridSize)gridSize;
66
67-(id) initWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped;
68-(id)initWithSize:(ccGridSize)gridSize;
69-(void)beforeDraw;
70-(void)afterDraw:(CCNode*)target;
71-(void)blit;
72-(void)reuse;
73
74-(void)calculateVertexPoints;
75
76@end
77
78////////////////////////////////////////////////////////////
79
80/**
81 CCGrid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z
82 */
83@interface CCGrid3D : CCGridBase
84{
85 GLvoid *texCoordinates;
86 GLvoid *vertices;
87 GLvoid *originalVertices;
88 GLushort *indices;
89}
90
91/** returns the vertex at a given position */
92-(ccVertex3F)vertex:(ccGridSize)pos;
93/** returns the original (non-transformed) vertex at a given position */
94-(ccVertex3F)originalVertex:(ccGridSize)pos;
95/** sets a new vertex at a given position */
96-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex;
97
98@end
99
100////////////////////////////////////////////////////////////
101
102/**
103 CCTiledGrid3D is a 3D grid implementation. It differs from Grid3D in that
104 the tiles can be separated from the grid.
105*/
106@interface CCTiledGrid3D : CCGridBase
107{
108 GLvoid *texCoordinates;
109 GLvoid *vertices;
110 GLvoid *originalVertices;
111 GLushort *indices;
112}
113
114/** returns the tile at the given position */
115-(ccQuad3)tile:(ccGridSize)pos;
116/** returns the original tile (untransformed) at the given position */
117-(ccQuad3)originalTile:(ccGridSize)pos;
118/** sets a new tile */
119-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords;
120
121@end
diff --git a/libs/cocos2d/CCGrid.m b/libs/cocos2d/CCGrid.m new file mode 100755 index 0000000..c2ed19d --- /dev/null +++ b/libs/cocos2d/CCGrid.m
@@ -0,0 +1,571 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Availability.h>
28
29#import "ccMacros.h"
30#import "CCGrid.h"
31#import "CCTexture2D.h"
32#import "CCDirector.h"
33#import "CCGrabber.h"
34
35#import "Platforms/CCGL.h"
36#import "Support/CGPointExtension.h"
37#import "Support/ccUtils.h"
38
39#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
40#import "Platforms/iOS/CCDirectorIOS.h"
41#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
42
43#pragma mark -
44#pragma mark CCGridBase
45
46@implementation CCGridBase
47
48@synthesize reuseGrid = reuseGrid_;
49@synthesize texture = texture_;
50@synthesize grabber = grabber_;
51@synthesize gridSize = gridSize_;
52@synthesize step = step_;
53
54+(id) gridWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped
55{
56 return [[[self alloc] initWithSize:gridSize texture:texture flippedTexture:flipped] autorelease];
57}
58
59+(id) gridWithSize:(ccGridSize)gridSize
60{
61 return [[(CCGridBase*)[self alloc] initWithSize:gridSize] autorelease];
62}
63
64-(id) initWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped
65{
66 if( (self=[super init]) ) {
67
68 active_ = NO;
69 reuseGrid_ = 0;
70 gridSize_ = gridSize;
71
72 self.texture = texture;
73 isTextureFlipped_ = flipped;
74
75 CGSize texSize = [texture_ contentSizeInPixels];
76 step_.x = texSize.width / gridSize_.x;
77 step_.y = texSize.height / gridSize_.y;
78
79 grabber_ = [[CCGrabber alloc] init];
80 [grabber_ grab:texture_];
81
82 [self calculateVertexPoints];
83 }
84 return self;
85}
86
87-(id)initWithSize:(ccGridSize)gSize
88{
89 CCDirector *director = [CCDirector sharedDirector];
90 CGSize s = [director winSizeInPixels];
91
92 unsigned long POTWide = ccNextPOT(s.width);
93 unsigned long POTHigh = ccNextPOT(s.height);
94
95#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
96 EAGLView *glview = [[CCDirector sharedDirector] openGLView];
97 NSString *pixelFormat = [glview pixelFormat];
98
99 CCTexture2DPixelFormat format = [pixelFormat isEqualToString: kEAGLColorFormatRGB565] ? kCCTexture2DPixelFormat_RGB565 : kCCTexture2DPixelFormat_RGBA8888;
100#else
101 CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;
102#endif
103
104 void *data = calloc((int)(POTWide * POTHigh * 4), 1);
105 if( ! data ) {
106 CCLOG(@"cocos2d: CCGrid: not enough memory");
107 [self release];
108 return nil;
109 }
110
111 CCTexture2D *texture = [[CCTexture2D alloc] initWithData:data pixelFormat:format pixelsWide:POTWide pixelsHigh:POTHigh contentSize:s];
112 free( data );
113
114 if( ! texture ) {
115 CCLOG(@"cocos2d: CCGrid: error creating texture");
116 [self release];
117 return nil;
118 }
119
120 self = [self initWithSize:gSize texture:texture flippedTexture:NO];
121
122 [texture release];
123
124 return self;
125}
126- (NSString*) description
127{
128 return [NSString stringWithFormat:@"<%@ = %08X | Dimensions = %ix%i>", [self class], self, gridSize_.x, gridSize_.y];
129}
130
131- (void) dealloc
132{
133 CCLOGINFO(@"cocos2d: deallocing %@", self);
134
135 [self setActive: NO];
136
137 [texture_ release];
138 [grabber_ release];
139 [super dealloc];
140}
141
142// properties
143-(BOOL) active
144{
145 return active_;
146}
147
148-(void) setActive:(BOOL)active
149{
150 active_ = active;
151 if( ! active ) {
152 CCDirector *director = [CCDirector sharedDirector];
153 ccDirectorProjection proj = [director projection];
154 [director setProjection:proj];
155 }
156}
157
158-(BOOL) isTextureFlipped
159{
160 return isTextureFlipped_;
161}
162
163-(void) setIsTextureFlipped:(BOOL)flipped
164{
165 if( isTextureFlipped_ != flipped ) {
166 isTextureFlipped_ = flipped;
167 [self calculateVertexPoints];
168 }
169}
170
171// This routine can be merged with Director
172#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
173-(void)applyLandscape
174{
175 CCDirector *director = [CCDirector sharedDirector];
176
177 CGSize winSize = [director displaySizeInPixels];
178 float w = winSize.width / 2;
179 float h = winSize.height / 2;
180
181 ccDeviceOrientation orientation = [director deviceOrientation];
182
183 switch (orientation) {
184 case CCDeviceOrientationLandscapeLeft:
185 glTranslatef(w,h,0);
186 glRotatef(-90,0,0,1);
187 glTranslatef(-h,-w,0);
188 break;
189 case CCDeviceOrientationLandscapeRight:
190 glTranslatef(w,h,0);
191 glRotatef(90,0,0,1);
192 glTranslatef(-h,-w,0);
193 break;
194 case CCDeviceOrientationPortraitUpsideDown:
195 glTranslatef(w,h,0);
196 glRotatef(180,0,0,1);
197 glTranslatef(-w,-h,0);
198 break;
199 default:
200 break;
201 }
202}
203#endif
204
205-(void)set2DProjection
206{
207 CGSize winSize = [[CCDirector sharedDirector] winSizeInPixels];
208
209 glLoadIdentity();
210 glViewport(0, 0, winSize.width, winSize.height);
211 glMatrixMode(GL_PROJECTION);
212 glLoadIdentity();
213 ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024);
214 glMatrixMode(GL_MODELVIEW);
215}
216
217// This routine can be merged with Director
218-(void)set3DProjection
219{
220 CCDirector *director = [CCDirector sharedDirector];
221
222 CGSize winSize = [director displaySizeInPixels];
223
224 glViewport(0, 0, winSize.width, winSize.height);
225 glMatrixMode(GL_PROJECTION);
226 glLoadIdentity();
227 gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f);
228
229 glMatrixMode(GL_MODELVIEW);
230 glLoadIdentity();
231 gluLookAt( winSize.width/2, winSize.height/2, [director getZEye],
232 winSize.width/2, winSize.height/2, 0,
233 0.0f, 1.0f, 0.0f
234 );
235}
236
237-(void)beforeDraw
238{
239 [self set2DProjection];
240 [grabber_ beforeRender:texture_];
241}
242
243-(void)afterDraw:(CCNode *)target
244{
245 [grabber_ afterRender:texture_];
246
247 [self set3DProjection];
248#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
249 [self applyLandscape];
250#endif
251
252 if( target.camera.dirty ) {
253
254 CGPoint offset = [target anchorPointInPixels];
255
256 //
257 // XXX: Camera should be applied in the AnchorPoint
258 //
259 ccglTranslate(offset.x, offset.y, 0);
260 [target.camera locate];
261 ccglTranslate(-offset.x, -offset.y, 0);
262 }
263
264 glBindTexture(GL_TEXTURE_2D, texture_.name);
265
266 [self blit];
267}
268
269-(void)blit
270{
271 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
272}
273
274-(void)reuse
275{
276 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
277}
278
279-(void)calculateVertexPoints
280{
281 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
282}
283
284@end
285
286////////////////////////////////////////////////////////////
287
288#pragma mark -
289#pragma mark CCGrid3D
290@implementation CCGrid3D
291
292-(void)dealloc
293{
294 free(texCoordinates);
295 free(vertices);
296 free(indices);
297 free(originalVertices);
298 [super dealloc];
299}
300
301-(void)blit
302{
303 NSInteger n = gridSize_.x * gridSize_.y;
304
305 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
306 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
307 // Unneeded states: GL_COLOR_ARRAY
308 glDisableClientState(GL_COLOR_ARRAY);
309
310 glVertexPointer(3, GL_FLOAT, 0, vertices);
311 glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
312 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
313
314 // restore GL default state
315 glEnableClientState(GL_COLOR_ARRAY);
316}
317
318-(void)calculateVertexPoints
319{
320 float width = (float)texture_.pixelsWide;
321 float height = (float)texture_.pixelsHigh;
322 float imageH = texture_.contentSizeInPixels.height;
323
324 int x, y, i;
325
326 vertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
327 originalVertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
328 texCoordinates = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(CGPoint));
329 indices = malloc(gridSize_.x*gridSize_.y*sizeof(GLushort)*6);
330
331 float *vertArray = (float*)vertices;
332 float *texArray = (float*)texCoordinates;
333 GLushort *idxArray = (GLushort *)indices;
334
335 for( x = 0; x < gridSize_.x; x++ )
336 {
337 for( y = 0; y < gridSize_.y; y++ )
338 {
339 NSInteger idx = (y * gridSize_.x) + x;
340
341 float x1 = x * step_.x;
342 float x2 = x1 + step_.x;
343 float y1 = y * step_.y;
344 float y2 = y1 + step_.y;
345
346 GLushort a = x * (gridSize_.y+1) + y;
347 GLushort b = (x+1) * (gridSize_.y+1) + y;
348 GLushort c = (x+1) * (gridSize_.y+1) + (y+1);
349 GLushort d = x * (gridSize_.y+1) + (y+1);
350
351 GLushort tempidx[6] = { a, b, d, b, c, d };
352
353 memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));
354
355 int l1[4] = { a*3, b*3, c*3, d*3 };
356 ccVertex3F e = {x1,y1,0};
357 ccVertex3F f = {x2,y1,0};
358 ccVertex3F g = {x2,y2,0};
359 ccVertex3F h = {x1,y2,0};
360
361 ccVertex3F l2[4] = { e, f, g, h };
362
363 int tex1[4] = { a*2, b*2, c*2, d*2 };
364 CGPoint tex2[4] = { ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2) };
365
366 for( i = 0; i < 4; i++ )
367 {
368 vertArray[ l1[i] ] = l2[i].x;
369 vertArray[ l1[i] + 1 ] = l2[i].y;
370 vertArray[ l1[i] + 2 ] = l2[i].z;
371
372 texArray[ tex1[i] ] = tex2[i].x / width;
373 if( isTextureFlipped_ )
374 texArray[ tex1[i] + 1 ] = (imageH - tex2[i].y) / height;
375 else
376 texArray[ tex1[i] + 1 ] = tex2[i].y / height;
377 }
378 }
379 }
380
381 memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
382}
383
384-(ccVertex3F)vertex:(ccGridSize)pos
385{
386 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
387 float *vertArray = (float *)vertices;
388
389 ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] };
390
391 return vert;
392}
393
394-(ccVertex3F)originalVertex:(ccGridSize)pos
395{
396 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
397 float *vertArray = (float *)originalVertices;
398
399 ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] };
400
401 return vert;
402}
403
404-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex
405{
406 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
407 float *vertArray = (float *)vertices;
408 vertArray[index] = vertex.x;
409 vertArray[index+1] = vertex.y;
410 vertArray[index+2] = vertex.z;
411}
412
413-(void)reuse
414{
415 if ( reuseGrid_ > 0 )
416 {
417 memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
418 reuseGrid_--;
419 }
420}
421
422@end
423
424////////////////////////////////////////////////////////////
425
426#pragma mark -
427#pragma mark CCTiledGrid3D
428
429@implementation CCTiledGrid3D
430
431-(void)dealloc
432{
433 free(texCoordinates);
434 free(vertices);
435 free(indices);
436 free(originalVertices);
437 [super dealloc];
438}
439
440-(void)blit
441{
442 NSInteger n = gridSize_.x * gridSize_.y;
443
444 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
445 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
446 // Unneeded states: GL_COLOR_ARRAY
447 glDisableClientState(GL_COLOR_ARRAY);
448
449 glVertexPointer(3, GL_FLOAT, 0, vertices);
450 glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
451 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
452
453 // restore default GL state
454 glEnableClientState(GL_COLOR_ARRAY);
455}
456
457-(void)calculateVertexPoints
458{
459 float width = (float)texture_.pixelsWide;
460 float height = (float)texture_.pixelsHigh;
461 float imageH = texture_.contentSizeInPixels.height;
462
463 NSInteger numQuads = gridSize_.x * gridSize_.y;
464
465 vertices = malloc(numQuads*12*sizeof(GLfloat));
466 originalVertices = malloc(numQuads*12*sizeof(GLfloat));
467 texCoordinates = malloc(numQuads*8*sizeof(GLfloat));
468 indices = malloc(numQuads*6*sizeof(GLushort));
469
470 float *vertArray = (float*)vertices;
471 float *texArray = (float*)texCoordinates;
472 GLushort *idxArray = (GLushort *)indices;
473
474 int x, y;
475
476 for( x = 0; x < gridSize_.x; x++ )
477 {
478 for( y = 0; y < gridSize_.y; y++ )
479 {
480 float x1 = x * step_.x;
481 float x2 = x1 + step_.x;
482 float y1 = y * step_.y;
483 float y2 = y1 + step_.y;
484
485 *vertArray++ = x1;
486 *vertArray++ = y1;
487 *vertArray++ = 0;
488 *vertArray++ = x2;
489 *vertArray++ = y1;
490 *vertArray++ = 0;
491 *vertArray++ = x1;
492 *vertArray++ = y2;
493 *vertArray++ = 0;
494 *vertArray++ = x2;
495 *vertArray++ = y2;
496 *vertArray++ = 0;
497
498 float newY1 = y1;
499 float newY2 = y2;
500
501 if( isTextureFlipped_ ) {
502 newY1 = imageH - y1;
503 newY2 = imageH - y2;
504 }
505
506 *texArray++ = x1 / width;
507 *texArray++ = newY1 / height;
508 *texArray++ = x2 / width;
509 *texArray++ = newY1 / height;
510 *texArray++ = x1 / width;
511 *texArray++ = newY2 / height;
512 *texArray++ = x2 / width;
513 *texArray++ = newY2 / height;
514 }
515 }
516
517 for( x = 0; x < numQuads; x++)
518 {
519 idxArray[x*6+0] = x*4+0;
520 idxArray[x*6+1] = x*4+1;
521 idxArray[x*6+2] = x*4+2;
522
523 idxArray[x*6+3] = x*4+1;
524 idxArray[x*6+4] = x*4+2;
525 idxArray[x*6+5] = x*4+3;
526 }
527
528 memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat));
529}
530
531-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords
532{
533 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
534 float *vertArray = (float*)vertices;
535 memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
536}
537
538-(ccQuad3)originalTile:(ccGridSize)pos
539{
540 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
541 float *vertArray = (float*)originalVertices;
542
543 ccQuad3 ret;
544 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
545
546 return ret;
547}
548
549-(ccQuad3)tile:(ccGridSize)pos
550{
551 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
552 float *vertArray = (float*)vertices;
553
554 ccQuad3 ret;
555 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
556
557 return ret;
558}
559
560-(void)reuse
561{
562 if ( reuseGrid_ > 0 )
563 {
564 NSInteger numQuads = gridSize_.x * gridSize_.y;
565
566 memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat));
567 reuseGrid_--;
568 }
569}
570
571@end
diff --git a/libs/cocos2d/CCLabelAtlas.h b/libs/cocos2d/CCLabelAtlas.h new file mode 100755 index 0000000..f7781a4 --- /dev/null +++ b/libs/cocos2d/CCLabelAtlas.h
@@ -0,0 +1,62 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCAtlasNode.h"
29#import "CCTextureAtlas.h"
30
31/** CCLabelAtlas is a subclass of CCAtlasNode.
32
33 It can be as a replacement of CCLabel since it is MUCH faster.
34
35 CCLabelAtlas versus CCLabel:
36 - CCLabelAtlas is MUCH faster than CCLabel
37 - CCLabelAtlas "characters" have a fixed height and width
38 - CCLabelAtlas "characters" can be anything you want since they are taken from an image file
39
40 A more flexible class is CCLabelBMFont. It supports variable width characters and it also has a nice editor.
41 */
42@interface CCLabelAtlas : CCAtlasNode <CCLabelProtocol>
43{
44 // string to render
45 NSString *string_;
46
47 // the first char in the charmap
48 unsigned char mapStartChar_;
49}
50
51
52/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas */
53+(id) labelWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c;
54
55/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas.
56 @deprecated Will be removed in 1.0.1. Use "labelWithString:" instead
57 */
58+(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c DEPRECATED_ATTRIBUTE;
59
60/** initializes the CCLabelAtlas with a string, a char map file(the atlas), the width and height in points of each element and the starting char of the atlas */
61-(id) initWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c;
62@end
diff --git a/libs/cocos2d/CCLabelAtlas.m b/libs/cocos2d/CCLabelAtlas.m new file mode 100755 index 0000000..386f8c3 --- /dev/null +++ b/libs/cocos2d/CCLabelAtlas.m
@@ -0,0 +1,170 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "ccConfig.h"
29#import "ccMacros.h"
30#import "CCDrawingPrimitives.h"
31#import "CCLabelAtlas.h"
32#import "Support/CGPointExtension.h"
33
34
35
36@implementation CCLabelAtlas
37
38#pragma mark CCLabelAtlas - Creation & Init
39+(id) labelWithString:(NSString*)string charMapFile:(NSString*)charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c
40{
41 return [[[self alloc] initWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c] autorelease];
42}
43
44// XXX DEPRECATED. Remove it in 1.0.1
45+(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c
46{
47 return [self labelWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c];
48}
49
50
51-(id) initWithString:(NSString*) theString charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c
52{
53
54 if ((self=[super initWithTileFile:charmapfile tileWidth:w tileHeight:h itemsToRender:[theString length] ]) ) {
55
56 mapStartChar_ = c;
57 [self setString: theString];
58 }
59
60 return self;
61}
62
63-(void) dealloc
64{
65 [string_ release];
66
67 [super dealloc];
68}
69
70#pragma mark CCLabelAtlas - Atlas generation
71
72-(void) updateAtlasValues
73{
74 NSUInteger n = [string_ length];
75
76 ccV3F_C4B_T2F_Quad quad;
77
78 const unsigned char *s = (unsigned char*) [string_ UTF8String];
79
80 CCTexture2D *texture = [textureAtlas_ texture];
81 float textureWide = [texture pixelsWide];
82 float textureHigh = [texture pixelsHigh];
83
84 for( NSUInteger i=0; i<n; i++) {
85 unsigned char a = s[i] - mapStartChar_;
86 float row = (a % itemsPerRow_);
87 float col = (a / itemsPerRow_);
88
89#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
90 // Issue #938. Don't use texStepX & texStepY
91 float left = (2*row*itemWidth_+1)/(2*textureWide);
92 float right = left+(itemWidth_*2-2)/(2*textureWide);
93 float top = (2*col*itemHeight_+1)/(2*textureHigh);
94 float bottom = top+(itemHeight_*2-2)/(2*textureHigh);
95#else
96 float left = row*itemWidth_/textureWide;
97 float right = left+itemWidth_/textureWide;
98 float top = col*itemHeight_/textureHigh;
99 float bottom = top+itemHeight_/textureHigh;
100#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
101
102 quad.tl.texCoords.u = left;
103 quad.tl.texCoords.v = top;
104 quad.tr.texCoords.u = right;
105 quad.tr.texCoords.v = top;
106 quad.bl.texCoords.u = left;
107 quad.bl.texCoords.v = bottom;
108 quad.br.texCoords.u = right;
109 quad.br.texCoords.v = bottom;
110
111 quad.bl.vertices.x = (int) (i * itemWidth_);
112 quad.bl.vertices.y = 0;
113 quad.bl.vertices.z = 0.0f;
114 quad.br.vertices.x = (int)(i * itemWidth_ + itemWidth_);
115 quad.br.vertices.y = 0;
116 quad.br.vertices.z = 0.0f;
117 quad.tl.vertices.x = (int)(i * itemWidth_);
118 quad.tl.vertices.y = (int)(itemHeight_);
119 quad.tl.vertices.z = 0.0f;
120 quad.tr.vertices.x = (int)(i * itemWidth_ + itemWidth_);
121 quad.tr.vertices.y = (int)(itemHeight_);
122 quad.tr.vertices.z = 0.0f;
123
124 [textureAtlas_ updateQuad:&quad atIndex:i];
125 }
126}
127
128#pragma mark CCLabelAtlas - CCLabelProtocol
129
130- (void) setString:(NSString*) newString
131{
132 NSUInteger len = [newString length];
133 if( len > textureAtlas_.capacity )
134 [textureAtlas_ resizeCapacity:len];
135
136 [string_ release];
137 string_ = [newString copy];
138 [self updateAtlasValues];
139
140 CGSize s;
141 s.width = len * itemWidth_;
142 s.height = itemHeight_;
143 [self setContentSizeInPixels:s];
144
145 self.quadsToDraw = len;
146}
147
148-(NSString*) string
149{
150 return string_;
151}
152
153#pragma mark CCLabelAtlas - DebugDraw
154
155#if CC_LABELATLAS_DEBUG_DRAW
156- (void) draw
157{
158 [super draw];
159
160 CGSize s = [self contentSize];
161 CGPoint vertices[4]={
162 ccp(0,0),ccp(s.width,0),
163 ccp(s.width,s.height),ccp(0,s.height),
164 };
165 ccDrawPoly(vertices, 4, YES);
166
167}
168#endif // CC_LABELATLAS_DEBUG_DRAW
169
170@end
diff --git a/libs/cocos2d/CCLabelBMFont.h b/libs/cocos2d/CCLabelBMFont.h new file mode 100755 index 0000000..c839ad1 --- /dev/null +++ b/libs/cocos2d/CCLabelBMFont.h
@@ -0,0 +1,190 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 * Portions of this code are based and inspired on:
26 * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class
27 * by Michael Daley
28 *
29 * Use any of these editors to generate BMFonts:
30 * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
31 * http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
32 * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
33 * http://www.angelcode.com/products/bmfont/ (Free, Windows only)
34 */
35
36#import "CCSpriteBatchNode.h"
37#import "Support/uthash.h"
38
39struct _KerningHashElement;
40
41/** @struct ccBMFontDef
42 BMFont definition
43 */
44typedef struct _BMFontDef {
45 //! ID of the character
46 unsigned int charID;
47 //! origin and size of the font
48 CGRect rect;
49 //! The X amount the image should be offset when drawing the image (in pixels)
50 int xOffset;
51 //! The Y amount the image should be offset when drawing the image (in pixels)
52 int yOffset;
53 //! The amount to move the current position after drawing the character (in pixels)
54 int xAdvance;
55} ccBMFontDef;
56
57/** @struct ccBMFontPadding
58 BMFont padding
59 @since v0.8.2
60 */
61typedef struct _BMFontPadding {
62 /// padding left
63 int left;
64 /// padding top
65 int top;
66 /// padding right
67 int right;
68 /// padding bottom
69 int bottom;
70} ccBMFontPadding;
71
72enum {
73 // how many characters are supported
74 kCCBMFontMaxChars = 2048, //256,
75};
76
77/** CCBMFontConfiguration has parsed configuration of the the .fnt file
78 @since v0.8
79 */
80@interface CCBMFontConfiguration : NSObject
81{
82// XXX: Creating a public interface so that the bitmapFontArray[] is accesible
83@public
84 // The characters building up the font
85 ccBMFontDef BMFontArray_[kCCBMFontMaxChars];
86
87 // FNTConfig: Common Height
88 NSUInteger commonHeight_;
89
90 // Padding
91 ccBMFontPadding padding_;
92
93 // atlas name
94 NSString *atlasName_;
95
96 // values for kerning
97 struct _KerningHashElement *kerningDictionary_;
98}
99
100/** allocates a CCBMFontConfiguration with a FNT file */
101+(id) configurationWithFNTFile:(NSString*)FNTfile;
102/** initializes a CCBMFontConfiguration with a FNT file */
103-(id) initWithFNTfile:(NSString*)FNTfile;
104@end
105
106
107/** CCLabelBMFont is a subclass of CCSpriteBatchNode
108
109 Features:
110 - Treats each character like a CCSprite. This means that each individual character can be:
111 - rotated
112 - scaled
113 - translated
114 - tinted
115 - chage the opacity
116 - It can be used as part of a menu item.
117 - anchorPoint can be used to align the "label"
118 - Supports AngelCode text format
119
120 Limitations:
121 - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it
122 because it might affect the rendering
123
124 CCLabelBMFont implements the protocol CCLabelProtocol, like CCLabel and CCLabelAtlas.
125 CCLabelBMFont has the flexibility of CCLabel, the speed of CCLabelAtlas and all the features of CCSprite.
126 If in doubt, use CCLabelBMFont instead of CCLabelAtlas / CCLabel.
127
128 Supported editors:
129 - http://www.n4te.com/hiero/hiero.jnlp
130 - http://slick.cokeandcode.com/demos/hiero.jnlp
131 - http://www.angelcode.com/products/bmfont/
132
133 @since v0.8
134 */
135
136@interface CCLabelBMFont : CCSpriteBatchNode <CCLabelProtocol, CCRGBAProtocol>
137{
138 // string to render
139 NSString *string_;
140
141 CCBMFontConfiguration *configuration_;
142
143 // texture RGBA
144 GLubyte opacity_;
145 ccColor3B color_;
146 BOOL opacityModifyRGB_;
147}
148
149/** Purges the cached data.
150 Removes from memory the cached configurations and the atlas name dictionary.
151 @since v0.99.3
152 */
153+(void) purgeCachedData;
154
155/** conforms to CCRGBAProtocol protocol */
156@property (nonatomic,readwrite) GLubyte opacity;
157/** conforms to CCRGBAProtocol protocol */
158@property (nonatomic,readwrite) ccColor3B color;
159
160
161/** creates a BMFont label with an initial string and the FNT file */
162+(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile;
163
164/** creates a BMFont label with an initial string and the FNT file
165 @deprecated Will be removed in 1.0.1. Use "labelWithString" instead.
166 */
167+(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile DEPRECATED_ATTRIBUTE;
168
169/** init a BMFont label with an initial string and the FNT file */
170-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile;
171
172/** updates the font chars based on the string to render */
173-(void) createFontChars;
174@end
175
176/** Free function that parses a FNT file a place it on the cache
177*/
178CCBMFontConfiguration * FNTConfigLoadFile( NSString *file );
179/** Purges the FNT config cache
180 */
181void FNTConfigRemoveCache( void );
182
183
184
185/** CCBitmapFontAtlas
186 @deprecated Use CCLabelBMFont instead. Will be removed 1.0.1
187 */
188DEPRECATED_ATTRIBUTE @interface CCBitmapFontAtlas : CCLabelBMFont
189@end
190
diff --git a/libs/cocos2d/CCLabelBMFont.m b/libs/cocos2d/CCLabelBMFont.m new file mode 100755 index 0000000..614cd6e --- /dev/null +++ b/libs/cocos2d/CCLabelBMFont.m
@@ -0,0 +1,675 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 * Portions of this code are based and inspired on:
26 * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class
27 * by Michael Daley
28 *
29 *
30 * Use any of these editors to generate BMFonts:
31 * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
32 * http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
33 * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
34 * http://www.angelcode.com/products/bmfont/ (Free, Windows only)
35 */
36
37#import "ccConfig.h"
38#import "CCLabelBMFont.h"
39#import "CCSprite.h"
40#import "CCDrawingPrimitives.h"
41#import "CCConfiguration.h"
42#import "Support/CCFileUtils.h"
43#import "Support/CGPointExtension.h"
44#import "Support/uthash.h"
45
46#pragma mark -
47#pragma mark FNTConfig Cache - free functions
48
49NSMutableDictionary *configurations = nil;
50CCBMFontConfiguration* FNTConfigLoadFile( NSString *fntFile)
51{
52 CCBMFontConfiguration *ret = nil;
53
54 if( configurations == nil )
55 configurations = [[NSMutableDictionary dictionaryWithCapacity:3] retain];
56
57 ret = [configurations objectForKey:fntFile];
58 if( ret == nil ) {
59 ret = [CCBMFontConfiguration configurationWithFNTFile:fntFile];
60 [configurations setObject:ret forKey:fntFile];
61 }
62
63 return ret;
64}
65
66void FNTConfigRemoveCache( void )
67{
68 [configurations removeAllObjects];
69}
70
71#pragma mark - Hash Element
72
73// Equal function for targetSet.
74typedef struct _KerningHashElement
75{
76 int key; // key for the hash. 16-bit for 1st element, 16-bit for 2nd element
77 int amount;
78 UT_hash_handle hh;
79} tKerningHashElement;
80
81#pragma mark -
82#pragma mark BitmapFontConfiguration
83
84
85@interface CCBMFontConfiguration (Private)
86-(void) parseConfigFile:(NSString*)controlFile;
87-(void) parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition;
88-(void) parseInfoArguments:(NSString*)line;
89-(void) parseCommonArguments:(NSString*)line;
90-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile;
91-(void) parseKerningCapacity:(NSString*)line;
92-(void) parseKerningEntry:(NSString*)line;
93-(void) purgeKerningDictionary;
94@end
95
96@implementation CCBMFontConfiguration
97
98+(id) configurationWithFNTFile:(NSString*)FNTfile
99{
100 return [[[self alloc] initWithFNTfile:FNTfile] autorelease];
101}
102
103-(id) initWithFNTfile:(NSString*)fntFile
104{
105 if((self=[super init])) {
106
107 kerningDictionary_ = NULL;
108
109 [self parseConfigFile:fntFile];
110 }
111 return self;
112}
113
114- (void) dealloc
115{
116 CCLOGINFO( @"cocos2d: deallocing %@", self);
117 [self purgeKerningDictionary];
118 [atlasName_ release];
119 [super dealloc];
120}
121
122- (NSString*) description
123{
124 return [NSString stringWithFormat:@"<%@ = %08X | Kernings:%d | Image = %@>", [self class], self,
125 HASH_COUNT(kerningDictionary_),
126 atlasName_];
127}
128
129
130-(void) purgeKerningDictionary
131{
132 tKerningHashElement *current;
133
134 while(kerningDictionary_) {
135 current = kerningDictionary_;
136 HASH_DEL(kerningDictionary_,current);
137 free(current);
138 }
139}
140
141- (void)parseConfigFile:(NSString*)fntFile
142{
143 NSString *fullpath = [CCFileUtils fullPathFromRelativePath:fntFile];
144 NSError *error;
145 NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:&error];
146
147 NSAssert1( contents, @"cocos2d: Error parsing FNTfile: %@", error);
148
149
150 // Move all lines in the string, which are denoted by \n, into an array
151 NSArray *lines = [[NSArray alloc] initWithArray:[contents componentsSeparatedByString:@"\n"]];
152
153 // Create an enumerator which we can use to move through the lines read from the control file
154 NSEnumerator *nse = [lines objectEnumerator];
155
156 // Create a holder for each line we are going to work with
157 NSString *line;
158
159 // Loop through all the lines in the lines array processing each one
160 while( (line = [nse nextObject]) ) {
161 // parse spacing / padding
162 if([line hasPrefix:@"info face"]) {
163 // XXX: info parsing is incomplete
164 // Not needed for the Hiero editors, but needed for the AngelCode editor
165// [self parseInfoArguments:line];
166 }
167 // Check to see if the start of the line is something we are interested in
168 else if([line hasPrefix:@"common lineHeight"]) {
169 [self parseCommonArguments:line];
170 }
171 else if([line hasPrefix:@"page id"]) {
172 [self parseImageFileName:line fntFile:fntFile];
173 }
174 else if([line hasPrefix:@"chars c"]) {
175 // Ignore this line
176 }
177 else if([line hasPrefix:@"char"]) {
178 // Parse the current line and create a new CharDef
179 ccBMFontDef characterDefinition;
180 [self parseCharacterDefinition:line charDef:&characterDefinition];
181
182 // Add the CharDef returned to the charArray
183 BMFontArray_[ characterDefinition.charID ] = characterDefinition;
184 }
185 else if([line hasPrefix:@"kernings count"]) {
186 [self parseKerningCapacity:line];
187 }
188 else if([line hasPrefix:@"kerning first"]) {
189 [self parseKerningEntry:line];
190 }
191 }
192 // Finished with lines so release it
193 [lines release];
194}
195
196-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile
197{
198 NSString *propertyValue = nil;
199
200 // Break the values for this line up using =
201 NSArray *values = [line componentsSeparatedByString:@"="];
202
203 // Get the enumerator for the array of components which has been created
204 NSEnumerator *nse = [values objectEnumerator];
205
206 // We need to move past the first entry in the array before we start assigning values
207 [nse nextObject];
208
209 // page ID. Sanity check
210 propertyValue = [nse nextObject];
211 NSAssert( [propertyValue intValue] == 0, @"XXX: LabelBMFont only supports 1 page");
212
213 // file
214 propertyValue = [nse nextObject];
215 NSArray *array = [propertyValue componentsSeparatedByString:@"\""];
216 propertyValue = [array objectAtIndex:1];
217 NSAssert(propertyValue,@"LabelBMFont file could not be found");
218
219 // Supports subdirectories
220 NSString *dir = [fntFile stringByDeletingLastPathComponent];
221 atlasName_ = [dir stringByAppendingPathComponent:propertyValue];
222
223 [atlasName_ retain];
224}
225
226-(void) parseInfoArguments:(NSString*)line
227{
228 //
229 // possible lines to parse:
230 // info face="Script" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,4,3,2 spacing=0,0 outline=0
231 // info face="Cracked" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1
232 //
233 NSArray *values = [line componentsSeparatedByString:@"="];
234 NSEnumerator *nse = [values objectEnumerator];
235 NSString *propertyValue = nil;
236
237 // We need to move past the first entry in the array before we start assigning values
238 [nse nextObject];
239
240 // face (ignore)
241 [nse nextObject];
242
243 // size (ignore)
244 [nse nextObject];
245
246 // bold (ignore)
247 [nse nextObject];
248
249 // italic (ignore)
250 [nse nextObject];
251
252 // charset (ignore)
253 [nse nextObject];
254
255 // unicode (ignore)
256 [nse nextObject];
257
258 // strechH (ignore)
259 [nse nextObject];
260
261 // smooth (ignore)
262 [nse nextObject];
263
264 // aa (ignore)
265 [nse nextObject];
266
267 // padding (ignore)
268 propertyValue = [nse nextObject];
269 {
270
271 NSArray *paddingValues = [propertyValue componentsSeparatedByString:@","];
272 NSEnumerator *paddingEnum = [paddingValues objectEnumerator];
273 // padding top
274 propertyValue = [paddingEnum nextObject];
275 padding_.top = [propertyValue intValue];
276
277 // padding right
278 propertyValue = [paddingEnum nextObject];
279 padding_.right = [propertyValue intValue];
280
281 // padding bottom
282 propertyValue = [paddingEnum nextObject];
283 padding_.bottom = [propertyValue intValue];
284
285 // padding left
286 propertyValue = [paddingEnum nextObject];
287 padding_.left = [propertyValue intValue];
288
289 CCLOG(@"cocos2d: padding: %d,%d,%d,%d", padding_.left, padding_.top, padding_.right, padding_.bottom);
290 }
291
292 // spacing (ignore)
293 [nse nextObject];
294}
295
296-(void) parseCommonArguments:(NSString*)line
297{
298 //
299 // line to parse:
300 // common lineHeight=104 base=26 scaleW=1024 scaleH=512 pages=1 packed=0
301 //
302 NSArray *values = [line componentsSeparatedByString:@"="];
303 NSEnumerator *nse = [values objectEnumerator];
304 NSString *propertyValue = nil;
305
306 // We need to move past the first entry in the array before we start assigning values
307 [nse nextObject];
308
309 // Character ID
310 propertyValue = [nse nextObject];
311 commonHeight_ = [propertyValue intValue];
312
313 // base (ignore)
314 [nse nextObject];
315
316
317 // scaleW. sanity check
318 propertyValue = [nse nextObject];
319 NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported");
320
321 // scaleH. sanity check
322 propertyValue = [nse nextObject];
323 NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported");
324
325 // pages. sanity check
326 propertyValue = [nse nextObject];
327 NSAssert( [propertyValue intValue] == 1, @"CCBitfontAtlas: only supports 1 page");
328
329 // packed (ignore) What does this mean ??
330}
331- (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition
332{
333 // Break the values for this line up using =
334 NSArray *values = [line componentsSeparatedByString:@"="];
335 NSEnumerator *nse = [values objectEnumerator];
336 NSString *propertyValue;
337
338 // We need to move past the first entry in the array before we start assigning values
339 [nse nextObject];
340
341 // Character ID
342 propertyValue = [nse nextObject];
343 propertyValue = [propertyValue substringToIndex: [propertyValue rangeOfString: @" "].location];
344 characterDefinition->charID = [propertyValue intValue];
345 NSAssert(characterDefinition->charID < kCCBMFontMaxChars, @"BitmpaFontAtlas: CharID bigger than supported");
346
347 // Character x
348 propertyValue = [nse nextObject];
349 characterDefinition->rect.origin.x = [propertyValue intValue];
350 // Character y
351 propertyValue = [nse nextObject];
352 characterDefinition->rect.origin.y = [propertyValue intValue];
353 // Character width
354 propertyValue = [nse nextObject];
355 characterDefinition->rect.size.width = [propertyValue intValue];
356 // Character height
357 propertyValue = [nse nextObject];
358 characterDefinition->rect.size.height = [propertyValue intValue];
359 // Character xoffset
360 propertyValue = [nse nextObject];
361 characterDefinition->xOffset = [propertyValue intValue];
362 // Character yoffset
363 propertyValue = [nse nextObject];
364 characterDefinition->yOffset = [propertyValue intValue];
365 // Character xadvance
366 propertyValue = [nse nextObject];
367 characterDefinition->xAdvance = [propertyValue intValue];
368}
369
370-(void) parseKerningCapacity:(NSString*) line
371{
372 // When using uthash there is not need to parse the capacity.
373
374// NSAssert(!kerningDictionary, @"dictionary already initialized");
375//
376// // Break the values for this line up using =
377// NSArray *values = [line componentsSeparatedByString:@"="];
378// NSEnumerator *nse = [values objectEnumerator];
379// NSString *propertyValue;
380//
381// // We need to move past the first entry in the array before we start assigning values
382// [nse nextObject];
383//
384// // count
385// propertyValue = [nse nextObject];
386// int capacity = [propertyValue intValue];
387//
388// if( capacity != -1 )
389// kerningDictionary = ccHashSetNew(capacity, targetSetEql);
390}
391
392-(void) parseKerningEntry:(NSString*) line
393{
394 NSArray *values = [line componentsSeparatedByString:@"="];
395 NSEnumerator *nse = [values objectEnumerator];
396 NSString *propertyValue;
397
398 // We need to move past the first entry in the array before we start assigning values
399 [nse nextObject];
400
401 // first
402 propertyValue = [nse nextObject];
403 int first = [propertyValue intValue];
404
405 // second
406 propertyValue = [nse nextObject];
407 int second = [propertyValue intValue];
408
409 // second
410 propertyValue = [nse nextObject];
411 int amount = [propertyValue intValue];
412
413 tKerningHashElement *element = calloc( sizeof( *element ), 1 );
414 element->amount = amount;
415 element->key = (first<<16) | (second&0xffff);
416 HASH_ADD_INT(kerningDictionary_,key, element);
417}
418
419@end
420
421#pragma mark -
422#pragma mark CCLabelBMFont
423
424@interface CCLabelBMFont (Private)
425-(NSString*) atlasNameFromFntFile:(NSString*)fntFile;
426
427-(int) kerningAmountForFirst:(unichar)first second:(unichar)second;
428
429@end
430
431@implementation CCLabelBMFont
432
433@synthesize opacity = opacity_, color = color_;
434
435#pragma mark LabelBMFont - Purge Cache
436+(void) purgeCachedData
437{
438 FNTConfigRemoveCache();
439}
440
441#pragma mark LabelBMFont - Creation & Init
442
443+(id) labelWithString:(NSString *)string fntFile:(NSString *)fntFile
444{
445 return [[[self alloc] initWithString:string fntFile:fntFile] autorelease];
446}
447
448// XXX - deprecated - Will be removed in 1.0.1
449+(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile
450{
451 return [self labelWithString:string fntFile:fntFile];
452}
453
454-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile
455{
456
457 [configuration_ release]; // allow re-init
458
459 configuration_ = FNTConfigLoadFile(fntFile);
460 [configuration_ retain];
461
462 NSAssert( configuration_, @"Error creating config for LabelBMFont");
463
464
465 if ((self=[super initWithFile:configuration_->atlasName_ capacity:[theString length]])) {
466
467 opacity_ = 255;
468 color_ = ccWHITE;
469
470 contentSize_ = CGSizeZero;
471
472 opacityModifyRGB_ = [[textureAtlas_ texture] hasPremultipliedAlpha];
473
474 anchorPoint_ = ccp(0.5f, 0.5f);
475
476 [self setString:theString];
477 }
478
479 return self;
480}
481
482-(void) dealloc
483{
484 [string_ release];
485 [configuration_ release];
486 [super dealloc];
487}
488
489#pragma mark LabelBMFont - Atlas generation
490
491-(int) kerningAmountForFirst:(unichar)first second:(unichar)second
492{
493 int ret = 0;
494 unsigned int key = (first<<16) | (second & 0xffff);
495
496 if( configuration_->kerningDictionary_ ) {
497 tKerningHashElement *element = NULL;
498 HASH_FIND_INT(configuration_->kerningDictionary_, &key, element);
499 if(element)
500 ret = element->amount;
501 }
502
503 return ret;
504}
505
506-(void) createFontChars
507{
508 NSInteger nextFontPositionX = 0;
509 NSInteger nextFontPositionY = 0;
510 unichar prev = -1;
511 NSInteger kerningAmount = 0;
512
513 CGSize tmpSize = CGSizeZero;
514
515 NSInteger longestLine = 0;
516 NSUInteger totalHeight = 0;
517
518 NSUInteger quantityOfLines = 1;
519
520 NSUInteger stringLen = [string_ length];
521 if( ! stringLen )
522 return;
523
524 // quantity of lines NEEDS to be calculated before parsing the lines,
525 // since the Y position needs to be calcualted before hand
526 for(NSUInteger i=0; i < stringLen-1;i++) {
527 unichar c = [string_ characterAtIndex:i];
528 if( c=='\n')
529 quantityOfLines++;
530 }
531
532 totalHeight = configuration_->commonHeight_ * quantityOfLines;
533 nextFontPositionY = -(configuration_->commonHeight_ - configuration_->commonHeight_*quantityOfLines);
534
535 for(NSUInteger i=0; i<stringLen; i++) {
536 unichar c = [string_ characterAtIndex:i];
537 NSAssert( c < kCCBMFontMaxChars, @"LabelBMFont: character outside bounds");
538
539 if (c == '\n') {
540 nextFontPositionX = 0;
541 nextFontPositionY -= configuration_->commonHeight_;
542 continue;
543 }
544
545 kerningAmount = [self kerningAmountForFirst:prev second:c];
546
547 ccBMFontDef fontDef = configuration_->BMFontArray_[c];
548
549 CGRect rect = fontDef.rect;
550
551 CCSprite *fontChar;
552
553 fontChar = (CCSprite*) [self getChildByTag:i];
554 if( ! fontChar ) {
555 fontChar = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
556 [self addChild:fontChar z:0 tag:i];
557 [fontChar release];
558 }
559 else {
560 // reusing fonts
561 [fontChar setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size];
562
563 // restore to default in case they were modified
564 fontChar.visible = YES;
565 fontChar.opacity = 255;
566 }
567
568 float yOffset = configuration_->commonHeight_ - fontDef.yOffset;
569 fontChar.positionInPixels = ccp( (float)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount,
570 (float)nextFontPositionY + yOffset - rect.size.height*0.5f );
571
572 // update kerning
573 nextFontPositionX += configuration_->BMFontArray_[c].xAdvance + kerningAmount;
574 prev = c;
575
576 // Apply label properties
577 [fontChar setOpacityModifyRGB:opacityModifyRGB_];
578 // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on
579 [fontChar setColor:color_];
580
581 // only apply opacity if it is different than 255 )
582 // to prevent modifying the color too (issue #610)
583 if( opacity_ != 255 )
584 [fontChar setOpacity: opacity_];
585
586 if (longestLine < nextFontPositionX)
587 longestLine = nextFontPositionX;
588 }
589
590 tmpSize.width = longestLine;
591 tmpSize.height = totalHeight;
592
593 [self setContentSizeInPixels:tmpSize];
594}
595
596#pragma mark LabelBMFont - CCLabelProtocol protocol
597- (void) setString:(NSString*) newString
598{
599 [string_ release];
600 string_ = [newString copy];
601
602 CCNode *child;
603 CCARRAY_FOREACH(children_, child)
604 child.visible = NO;
605
606 [self createFontChars];
607}
608
609-(NSString*) string
610{
611 return string_;
612}
613
614-(void) setCString:(char*)label
615{
616 [self setString:[NSString stringWithUTF8String:label]];
617}
618
619#pragma mark LabelBMFont - CCRGBAProtocol protocol
620
621-(void) setColor:(ccColor3B)color
622{
623 color_ = color;
624
625 CCSprite *child;
626 CCARRAY_FOREACH(children_, child)
627 [child setColor:color_];
628}
629
630-(void) setOpacity:(GLubyte)opacity
631{
632 opacity_ = opacity;
633
634 id<CCRGBAProtocol> child;
635 CCARRAY_FOREACH(children_, child)
636 [child setOpacity:opacity_];
637}
638-(void) setOpacityModifyRGB:(BOOL)modify
639{
640 opacityModifyRGB_ = modify;
641
642 id<CCRGBAProtocol> child;
643 CCARRAY_FOREACH(children_, child)
644 [child setOpacityModifyRGB:modify];
645}
646
647-(BOOL) doesOpacityModifyRGB
648{
649 return opacityModifyRGB_;
650}
651
652#pragma mark LabelBMFont - AnchorPoint
653-(void) setAnchorPoint:(CGPoint)point
654{
655 if( ! CGPointEqualToPoint(point, anchorPoint_) ) {
656 [super setAnchorPoint:point];
657 [self createFontChars];
658 }
659}
660
661#pragma mark LabelBMFont - Debug draw
662#if CC_LABELBMFONT_DEBUG_DRAW
663-(void) draw
664{
665 [super draw];
666
667 CGSize s = [self contentSize];
668 CGPoint vertices[4]={
669 ccp(0,0),ccp(s.width,0),
670 ccp(s.width,s.height),ccp(0,s.height),
671 };
672 ccDrawPoly(vertices, 4, YES);
673}
674#endif // CC_LABELBMFONT_DEBUG_DRAW
675@end
diff --git a/libs/cocos2d/CCLabelTTF.h b/libs/cocos2d/CCLabelTTF.h new file mode 100755 index 0000000..8e48ce1 --- /dev/null +++ b/libs/cocos2d/CCLabelTTF.h
@@ -0,0 +1,78 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCTexture2D.h"
29#import "CCSprite.h"
30#import "Platforms/CCNS.h"
31
32
33/** CCLabel is a subclass of CCTextureNode that knows how to render text labels
34 *
35 * All features from CCTextureNode are valid in CCLabel
36 *
37 * CCLabel objects are slow. Consider using CCLabelAtlas or CCLabelBMFont instead.
38 */
39
40@interface CCLabelTTF : CCSprite <CCLabelProtocol>
41{
42 CGSize dimensions_;
43 CCTextAlignment alignment_;
44 NSString * fontName_;
45 CGFloat fontSize_;
46 CCLineBreakMode lineBreakMode_;
47 NSString *string_;
48}
49
50/** creates a CCLabel from a fontname, alignment, dimension in points, line break mode, and font size in points.
51 Supported lineBreakModes:
52 - iOS: all UILineBreakMode supported modes
53 - Mac: Only NSLineBreakByWordWrapping is supported.
54 @since v1.0
55 */
56+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size;
57/** creates a CCLabel from a fontname, alignment, dimension in points and font size in points*/
58+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size;
59/** creates a CCLabel from a fontname and font size in points*/
60+ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size;
61/** initializes the CCLabel with a font name, alignment, dimension in points, line brea mode and font size in points.
62 Supported lineBreakModes:
63 - iOS: all UILineBreakMode supported modes
64 - Mac: Only NSLineBreakByWordWrapping is supported.
65 @since v1.0
66 */
67- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size;
68/** initializes the CCLabel with a font name, alignment, dimension in points and font size in points */
69- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size;
70/** initializes the CCLabel with a font name and font size in points */
71- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size;
72
73/** changes the string to render
74 * @warning Changing the string is as expensive as creating a new CCLabel. To obtain better performance use CCLabelAtlas
75 */
76- (void) setString:(NSString*)str;
77
78@end
diff --git a/libs/cocos2d/CCLabelTTF.m b/libs/cocos2d/CCLabelTTF.m new file mode 100755 index 0000000..24602ec --- /dev/null +++ b/libs/cocos2d/CCLabelTTF.m
@@ -0,0 +1,138 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Availability.h>
29
30#import "CCLabelTTF.h"
31#import "Support/CGPointExtension.h"
32#import "ccMacros.h"
33
34#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
35#import "Platforms/iOS/CCDirectorIOS.h"
36#endif
37
38@implementation CCLabelTTF
39
40- (id) init
41{
42 NSAssert(NO, @"CCLabelTTF: Init not supported. Use initWithString");
43 [self release];
44 return nil;
45}
46
47+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size;
48{
49 return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment lineBreakMode:lineBreakMode fontName:name fontSize:size]autorelease];
50}
51
52+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
53{
54 return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment fontName:name fontSize:size]autorelease];
55}
56
57+ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size
58{
59 return [[[self alloc] initWithString: string fontName:name fontSize:size]autorelease];
60}
61
62
63- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size
64{
65 if( (self=[super init]) ) {
66
67 dimensions_ = CGSizeMake( dimensions.width * CC_CONTENT_SCALE_FACTOR(), dimensions.height * CC_CONTENT_SCALE_FACTOR() );
68 alignment_ = alignment;
69 fontName_ = [name retain];
70 fontSize_ = size * CC_CONTENT_SCALE_FACTOR();
71 lineBreakMode_ = lineBreakMode;
72
73 [self setString:str];
74 }
75 return self;
76}
77
78- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
79{
80 return [self initWithString:str dimensions:dimensions alignment:alignment lineBreakMode:CCLineBreakModeWordWrap fontName:name fontSize:size];
81}
82
83- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size
84{
85 if( (self=[super init]) ) {
86
87 dimensions_ = CGSizeZero;
88 fontName_ = [name retain];
89 fontSize_ = size * CC_CONTENT_SCALE_FACTOR();
90
91 [self setString:str];
92 }
93 return self;
94}
95
96- (void) setString:(NSString*)str
97{
98 [string_ release];
99 string_ = [str copy];
100
101 CCTexture2D *tex;
102 if( CGSizeEqualToSize( dimensions_, CGSizeZero ) )
103 tex = [[CCTexture2D alloc] initWithString:str
104 fontName:fontName_
105 fontSize:fontSize_];
106 else
107 tex = [[CCTexture2D alloc] initWithString:str
108 dimensions:dimensions_
109 alignment:alignment_
110 lineBreakMode:lineBreakMode_
111 fontName:fontName_
112 fontSize:fontSize_];
113
114 [self setTexture:tex];
115 [tex release];
116
117 CGRect rect = CGRectZero;
118 rect.size = [texture_ contentSize];
119 [self setTextureRect: rect];
120}
121
122-(NSString*) string
123{
124 return string_;
125}
126
127- (void) dealloc
128{
129 [string_ release];
130 [fontName_ release];
131 [super dealloc];
132}
133
134- (NSString*) description
135{
136 return [NSString stringWithFormat:@"<%@ = %08X | Label = %@, FontName = %@, FontSize = %.1f>", [self class], self, string_, fontName_, fontSize_];
137}
138@end
diff --git a/libs/cocos2d/CCLayer.h b/libs/cocos2d/CCLayer.h new file mode 100755 index 0000000..f4c9860 --- /dev/null +++ b/libs/cocos2d/CCLayer.h
@@ -0,0 +1,293 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import <Availability.h>
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31#import <UIKit/UIKit.h> // Needed for UIAccelerometerDelegate
32#import "Platforms/iOS/CCTouchDelegateProtocol.h" // Touches only supported on iOS
33#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
34#import "Platforms/Mac/CCEventDispatcher.h"
35#endif
36
37#import "CCProtocols.h"
38#import "CCNode.h"
39
40#pragma mark -
41#pragma mark CCLayer
42
43/** CCLayer is a subclass of CCNode that implements the TouchEventsDelegate protocol.
44
45 All features from CCNode are valid, plus the following new features:
46 - It can receive iPhone Touches
47 - It can receive Accelerometer input
48*/
49#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
50@interface CCLayer : CCNode <UIAccelerometerDelegate, CCStandardTouchDelegate, CCTargetedTouchDelegate>
51{
52 BOOL isTouchEnabled_;
53 BOOL isAccelerometerEnabled_;
54}
55/** If isTouchEnabled, this method is called onEnter. Override it to change the
56 way CCLayer receives touch events.
57 ( Default: [[TouchDispatcher sharedDispatcher] addStandardDelegate:self priority:0] )
58 Example:
59 -(void) registerWithTouchDispatcher
60 {
61 [[TouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
62 }
63
64 Valid only on iOS. Not valid on Mac.
65
66 @since v0.8.0
67 */
68-(void) registerWithTouchDispatcher;
69
70/** whether or not it will receive Touch events.
71 You can enable / disable touch events with this property.
72 Only the touches of this node will be affected. This "method" is not propagated to it's children.
73
74 Valid on iOS and Mac OS X v10.6 and later.
75
76 @since v0.8.1
77 */
78@property(nonatomic,assign) BOOL isTouchEnabled;
79/** whether or not it will receive Accelerometer events
80 You can enable / disable accelerometer events with this property.
81
82 Valid only on iOS. Not valid on Mac.
83
84 @since v0.8.1
85 */
86@property(nonatomic,assign) BOOL isAccelerometerEnabled;
87
88#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
89
90
91@interface CCLayer : CCNode <CCKeyboardEventDelegate, CCMouseEventDelegate, CCTouchEventDelegate>
92{
93 BOOL isMouseEnabled_;
94 BOOL isKeyboardEnabled_;
95 BOOL isTouchEnabled_;
96}
97
98/** whether or not it will receive mouse events.
99
100 Valind only Mac. Not valid on iOS
101 */
102@property (nonatomic, readwrite) BOOL isMouseEnabled;
103
104/** whether or not it will receive keyboard events.
105
106 Valind only Mac. Not valid on iOS
107 */
108@property (nonatomic, readwrite) BOOL isKeyboardEnabled;
109
110/** whether or not it will receive touch events.
111
112 Valid on iOS and Mac OS X v10.6 and later.
113 */
114@property (nonatomic, readwrite) BOOL isTouchEnabled;
115
116/** priority of the mouse event delegate.
117 Default 0.
118 Override this method to set another priority.
119
120 Valind only Mac. Not valid on iOS
121 */
122-(NSInteger) mouseDelegatePriority;
123
124/** priority of the keyboard event delegate.
125 Default 0.
126 Override this method to set another priority.
127
128 Valind only Mac. Not valid on iOS
129 */
130-(NSInteger) keyboardDelegatePriority;
131
132/** priority of the touch event delegate.
133 Default 0.
134 Override this method to set another priority.
135
136 Valind only Mac. Not valid on iOS
137 */
138-(NSInteger) touchDelegatePriority;
139
140#endif // mac
141
142
143@end
144
145#pragma mark -
146#pragma mark CCLayerColor
147
148/** CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.
149
150 All features from CCLayer are valid, plus the following new features:
151 - opacity
152 - RGB colors
153 */
154@interface CCLayerColor : CCLayer <CCRGBAProtocol, CCBlendProtocol>
155{
156 GLubyte opacity_;
157 ccColor3B color_;
158 ccVertex2F squareVertices_[4];
159 ccColor4B squareColors_[4];
160
161 ccBlendFunc blendFunc_;
162}
163
164/** creates a CCLayer with color, width and height in Points*/
165+ (id) layerWithColor: (ccColor4B)color width:(GLfloat)w height:(GLfloat)h;
166/** creates a CCLayer with color. Width and height are the window size. */
167+ (id) layerWithColor: (ccColor4B)color;
168
169/** initializes a CCLayer with color, width and height in Points */
170- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat)h;
171/** initializes a CCLayer with color. Width and height are the window size. */
172- (id) initWithColor:(ccColor4B)color;
173
174/** change width in Points */
175-(void) changeWidth: (GLfloat)w;
176/** change height in Points */
177-(void) changeHeight: (GLfloat)h;
178/** change width and height in Points
179 @since v0.8
180 */
181-(void) changeWidth:(GLfloat)w height:(GLfloat)h;
182
183/** Opacity: conforms to CCRGBAProtocol protocol */
184@property (nonatomic,readonly) GLubyte opacity;
185/** Opacity: conforms to CCRGBAProtocol protocol */
186@property (nonatomic,readonly) ccColor3B color;
187/** BlendFunction. Conforms to CCBlendProtocol protocol */
188@property (nonatomic,readwrite) ccBlendFunc blendFunc;
189@end
190
191/** CCColorLayer
192 It is the same as CCLayerColor.
193
194 @deprecated Use CCLayerColor instead. This class will be removed in v1.0.1
195 */
196DEPRECATED_ATTRIBUTE @interface CCColorLayer : CCLayerColor
197@end
198
199#pragma mark -
200#pragma mark CCLayerGradient
201
202/** CCLayerGradient is a subclass of CCLayerColor that draws gradients across
203the background.
204
205 All features from CCLayerColor are valid, plus the following new features:
206 - direction
207 - final color
208 - interpolation mode
209
210 Color is interpolated between the startColor and endColor along the given
211 vector (starting at the origin, ending at the terminus). If no vector is
212 supplied, it defaults to (0, -1) -- a fade from top to bottom.
213
214 If 'compressedInterpolation' is disabled, you will not see either the start or end color for
215 non-cardinal vectors; a smooth gradient implying both end points will be still
216 be drawn, however.
217
218 If ' compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
219
220 @since v0.99.5
221 */
222@interface CCLayerGradient : CCLayerColor
223{
224 ccColor3B endColor_;
225 GLubyte startOpacity_;
226 GLubyte endOpacity_;
227 CGPoint vector_;
228 BOOL compressedInterpolation_;
229}
230
231/** Creates a full-screen CCLayer with a gradient between start and end. */
232+ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end;
233/** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */
234+ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v;
235
236/** Initializes the CCLayer with a gradient between start and end. */
237- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end;
238/** Initializes the CCLayer with a gradient between start and end in the direction of v. */
239- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v;
240
241/** The starting color. */
242@property (nonatomic, readwrite) ccColor3B startColor;
243/** The ending color. */
244@property (nonatomic, readwrite) ccColor3B endColor;
245/** The starting opacity. */
246@property (nonatomic, readwrite) GLubyte startOpacity;
247/** The ending color. */
248@property (nonatomic, readwrite) GLubyte endOpacity;
249/** The vector along which to fade color. */
250@property (nonatomic, readwrite) CGPoint vector;
251/** Whether or not the interpolation will be compressed in order to display all the colors of the gradient both in canonical and non canonical vectors
252 Default: YES
253 */
254@property (nonatomic, readwrite) BOOL compressedInterpolation;
255
256@end
257
258#pragma mark -
259#pragma mark CCLayerMultiplex
260
261/** CCLayerMultiplex is a CCLayer with the ability to multiplex it's children.
262 Features:
263 - It supports one or more children
264 - Only one children will be active a time
265 */
266@interface CCLayerMultiplex : CCLayer
267{
268 unsigned int enabledLayer_;
269 NSMutableArray *layers_;
270}
271
272/** creates a CCMultiplexLayer with one or more layers using a variable argument list. */
273+(id) layerWithLayers: (CCLayer*) layer, ... NS_REQUIRES_NIL_TERMINATION;
274/** initializes a MultiplexLayer with one or more layers using a variable argument list. */
275-(id) initWithLayers: (CCLayer*) layer vaList:(va_list) params;
276/** switches to a certain layer indexed by n.
277 The current (old) layer will be removed from it's parent with 'cleanup:YES'.
278 */
279-(void) switchTo: (unsigned int) n;
280/** release the current layer and switches to another layer indexed by n.
281 The current (old) layer will be removed from it's parent with 'cleanup:YES'.
282 */
283-(void) switchToAndReleaseMe: (unsigned int) n;
284@end
285
286/** CCMultiplexLayer
287 It is the same as CCLayerMultiplex.
288
289 @deprecated Use CCLayerMultiplex instead. This class will be removed in v1.0.1
290 */
291DEPRECATED_ATTRIBUTE @interface CCMultiplexLayer : CCLayerMultiplex
292@end
293
diff --git a/libs/cocos2d/CCLayer.m b/libs/cocos2d/CCLayer.m new file mode 100755 index 0000000..fe5a72d --- /dev/null +++ b/libs/cocos2d/CCLayer.m
@@ -0,0 +1,621 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <stdarg.h>
29
30#import "Platforms/CCGL.h"
31
32#import "CCLayer.h"
33#import "CCDirector.h"
34#import "ccMacros.h"
35#import "Support/CGPointExtension.h"
36
37#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
38#import "Platforms/iOS/CCTouchDispatcher.h"
39#import "Platforms/iOS/CCDirectorIOS.h"
40#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
41#import "Platforms/Mac/CCEventDispatcher.h"
42#endif
43
44#pragma mark -
45#pragma mark Layer
46
47@implementation CCLayer
48
49#pragma mark Layer - Init
50-(id) init
51{
52 if( (self=[super init]) ) {
53
54 CGSize s = [[CCDirector sharedDirector] winSize];
55 anchorPoint_ = ccp(0.5f, 0.5f);
56 [self setContentSize:s];
57 self.isRelativeAnchorPoint = NO;
58
59 isTouchEnabled_ = NO;
60
61#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
62 isAccelerometerEnabled_ = NO;
63#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
64 isMouseEnabled_ = NO;
65 isKeyboardEnabled_ = NO;
66#endif
67 }
68
69 return self;
70}
71
72#pragma mark Layer - Touch and Accelerometer related
73
74#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
75-(void) registerWithTouchDispatcher
76{
77 [[CCTouchDispatcher sharedDispatcher] addStandardDelegate:self priority:0];
78}
79
80-(BOOL) isAccelerometerEnabled
81{
82 return isAccelerometerEnabled_;
83}
84
85-(void) setIsAccelerometerEnabled:(BOOL)enabled
86{
87 if( enabled != isAccelerometerEnabled_ ) {
88 isAccelerometerEnabled_ = enabled;
89 if( isRunning_ ) {
90 if( enabled )
91 [[UIAccelerometer sharedAccelerometer] setDelegate:self];
92 else
93 [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
94 }
95 }
96}
97
98-(BOOL) isTouchEnabled
99{
100 return isTouchEnabled_;
101}
102
103-(void) setIsTouchEnabled:(BOOL)enabled
104{
105 if( isTouchEnabled_ != enabled ) {
106 isTouchEnabled_ = enabled;
107 if( isRunning_ ) {
108 if( enabled )
109 [self registerWithTouchDispatcher];
110 else
111 [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
112 }
113 }
114}
115
116#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
117
118#pragma mark CCLayer - Mouse, Keyboard & Touch events
119
120-(NSInteger) mouseDelegatePriority
121{
122 return 0;
123}
124
125-(BOOL) isMouseEnabled
126{
127 return isMouseEnabled_;
128}
129
130-(void) setIsMouseEnabled:(BOOL)enabled
131{
132 if( isMouseEnabled_ != enabled ) {
133 isMouseEnabled_ = enabled;
134
135 if( isRunning_ ) {
136 if( enabled )
137 [[CCEventDispatcher sharedDispatcher] addMouseDelegate:self priority:[self mouseDelegatePriority]];
138 else
139 [[CCEventDispatcher sharedDispatcher] removeMouseDelegate:self];
140 }
141 }
142}
143
144-(NSInteger) keyboardDelegatePriority
145{
146 return 0;
147}
148
149-(BOOL) isKeyboardEnabled
150{
151 return isKeyboardEnabled_;
152}
153
154-(void) setIsKeyboardEnabled:(BOOL)enabled
155{
156 if( isKeyboardEnabled_ != enabled ) {
157 isKeyboardEnabled_ = enabled;
158
159 if( isRunning_ ) {
160 if( enabled )
161 [[CCEventDispatcher sharedDispatcher] addKeyboardDelegate:self priority:[self keyboardDelegatePriority] ];
162 else
163 [[CCEventDispatcher sharedDispatcher] removeKeyboardDelegate:self];
164 }
165 }
166}
167
168-(NSInteger) touchDelegatePriority
169{
170 return 0;
171}
172
173-(BOOL) isTouchEnabled
174{
175 return isTouchEnabled_;
176}
177
178-(void) setIsTouchEnabled:(BOOL)enabled
179{
180 if( isTouchEnabled_ != enabled ) {
181 isTouchEnabled_ = enabled;
182 if( isRunning_ ) {
183 if( enabled )
184 [[CCEventDispatcher sharedDispatcher] addTouchDelegate:self priority:[self touchDelegatePriority]];
185 else
186 [[CCEventDispatcher sharedDispatcher] removeTouchDelegate:self];
187 }
188 }
189}
190
191
192#endif // Mac
193
194
195#pragma mark Layer - Callbacks
196-(void) onEnter
197{
198#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
199 // register 'parent' nodes first
200 // since events are propagated in reverse order
201 if (isTouchEnabled_)
202 [self registerWithTouchDispatcher];
203
204#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
205 if( isMouseEnabled_ )
206 [[CCEventDispatcher sharedDispatcher] addMouseDelegate:self priority:[self mouseDelegatePriority]];
207
208 if( isKeyboardEnabled_)
209 [[CCEventDispatcher sharedDispatcher] addKeyboardDelegate:self priority:[self keyboardDelegatePriority]];
210
211 if( isTouchEnabled_)
212 [[CCEventDispatcher sharedDispatcher] addTouchDelegate:self priority:[self touchDelegatePriority]];
213
214#endif
215
216 // then iterate over all the children
217 [super onEnter];
218}
219
220// issue #624.
221// Can't register mouse, touches here because of #issue #1018, and #1021
222-(void) onEnterTransitionDidFinish
223{
224#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
225 if( isAccelerometerEnabled_ )
226 [[UIAccelerometer sharedAccelerometer] setDelegate:self];
227#endif
228
229 [super onEnterTransitionDidFinish];
230}
231
232
233-(void) onExit
234{
235#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
236 if( isTouchEnabled_ )
237 [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
238
239 if( isAccelerometerEnabled_ )
240 [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
241
242#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
243 if( isMouseEnabled_ )
244 [[CCEventDispatcher sharedDispatcher] removeMouseDelegate:self];
245
246 if( isKeyboardEnabled_ )
247 [[CCEventDispatcher sharedDispatcher] removeKeyboardDelegate:self];
248
249 if( isTouchEnabled_ )
250 [[CCEventDispatcher sharedDispatcher] removeTouchDelegate:self];
251
252#endif
253
254 [super onExit];
255}
256
257#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
258-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
259{
260 NSAssert(NO, @"Layer#ccTouchBegan override me");
261 return YES;
262}
263#endif
264@end
265
266#pragma mark -
267#pragma mark LayerColor
268
269@interface CCLayerColor (Private)
270-(void) updateColor;
271@end
272
273@implementation CCLayerColor
274
275// Opacity and RGB color protocol
276@synthesize opacity = opacity_, color = color_;
277@synthesize blendFunc = blendFunc_;
278
279
280+ (id) layerWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h
281{
282 return [[[self alloc] initWithColor:color width:w height:h] autorelease];
283}
284
285+ (id) layerWithColor:(ccColor4B)color
286{
287 return [[(CCLayerColor*)[self alloc] initWithColor:color] autorelease];
288}
289
290- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h
291{
292 if( (self=[super init]) ) {
293
294 // default blend function
295 blendFunc_ = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST };
296
297 color_.r = color.r;
298 color_.g = color.g;
299 color_.b = color.b;
300 opacity_ = color.a;
301
302 for (NSUInteger i = 0; i<sizeof(squareVertices_) / sizeof( squareVertices_[0]); i++ ) {
303 squareVertices_[i].x = 0.0f;
304 squareVertices_[i].y = 0.0f;
305 }
306
307 [self updateColor];
308 [self setContentSize:CGSizeMake(w, h) ];
309 }
310 return self;
311}
312
313- (id) initWithColor:(ccColor4B)color
314{
315 CGSize s = [[CCDirector sharedDirector] winSize];
316 return [self initWithColor:color width:s.width height:s.height];
317}
318
319// override contentSize
320-(void) setContentSize: (CGSize) size
321{
322 squareVertices_[1].x = size.width * CC_CONTENT_SCALE_FACTOR();
323 squareVertices_[2].y = size.height * CC_CONTENT_SCALE_FACTOR();
324 squareVertices_[3].x = size.width * CC_CONTENT_SCALE_FACTOR();
325 squareVertices_[3].y = size.height * CC_CONTENT_SCALE_FACTOR();
326
327 [super setContentSize:size];
328}
329
330- (void) changeWidth: (GLfloat) w height:(GLfloat) h
331{
332 [self setContentSize:CGSizeMake(w, h)];
333}
334
335-(void) changeWidth: (GLfloat) w
336{
337 [self setContentSize:CGSizeMake(w, contentSize_.height)];
338}
339
340-(void) changeHeight: (GLfloat) h
341{
342 [self setContentSize:CGSizeMake(contentSize_.width, h)];
343}
344
345- (void) updateColor
346{
347 for( NSUInteger i = 0; i < 4; i++ )
348 {
349 squareColors_[i].r = color_.r;
350 squareColors_[i].g = color_.g;
351 squareColors_[i].b = color_.b;
352 squareColors_[i].a = opacity_;
353 }
354}
355
356- (void)draw
357{
358 [super draw];
359
360 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
361 // Needed states: GL_VERTEX_ARRAY, GL_COLOR_ARRAY
362 // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY
363 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
364 glDisable(GL_TEXTURE_2D);
365
366 glVertexPointer(2, GL_FLOAT, 0, squareVertices_);
367 glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors_);
368
369
370 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
371 if( newBlend )
372 glBlendFunc( blendFunc_.src, blendFunc_.dst );
373
374 else if( opacity_ != 255 ) {
375 newBlend = YES;
376 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
377 }
378
379 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
380
381 if( newBlend )
382 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
383
384 // restore default GL state
385 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
386 glEnable(GL_TEXTURE_2D);
387}
388
389#pragma mark Protocols
390// Color Protocol
391
392-(void) setColor:(ccColor3B)color
393{
394 color_ = color;
395 [self updateColor];
396}
397
398-(void) setOpacity: (GLubyte) o
399{
400 opacity_ = o;
401 [self updateColor];
402}
403@end
404
405// XXX Deprecated
406@implementation CCColorLayer
407@end
408
409
410#pragma mark -
411#pragma mark LayerGradient
412
413@implementation CCLayerGradient
414
415@synthesize startOpacity = startOpacity_;
416@synthesize endColor = endColor_, endOpacity = endOpacity_;
417@synthesize vector = vector_;
418
419+ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end
420{
421 return [[[self alloc] initWithColor:start fadingTo:end] autorelease];
422}
423
424+ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v
425{
426 return [[[self alloc] initWithColor:start fadingTo:end alongVector:v] autorelease];
427}
428
429- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end
430{
431 return [self initWithColor:start fadingTo:end alongVector:ccp(0, -1)];
432}
433
434- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v
435{
436 endColor_.r = end.r;
437 endColor_.g = end.g;
438 endColor_.b = end.b;
439
440 endOpacity_ = end.a;
441 startOpacity_ = start.a;
442 vector_ = v;
443
444 start.a = 255;
445 compressedInterpolation_ = YES;
446
447 return [super initWithColor:start];
448}
449
450- (void) updateColor
451{
452 [super updateColor];
453
454 float h = ccpLength(vector_);
455 if (h == 0)
456 return;
457
458 double c = sqrt(2);
459 CGPoint u = ccp(vector_.x / h, vector_.y / h);
460
461 // Compressed Interpolation mode
462 if( compressedInterpolation_ ) {
463 float h2 = 1 / ( fabsf(u.x) + fabsf(u.y) );
464 u = ccpMult(u, h2 * (float)c);
465 }
466
467 float opacityf = (float)opacity_/255.0f;
468
469 ccColor4B S = {
470 color_.r,
471 color_.g,
472 color_.b,
473 startOpacity_*opacityf
474 };
475
476 ccColor4B E = {
477 endColor_.r,
478 endColor_.g,
479 endColor_.b,
480 endOpacity_*opacityf
481 };
482
483
484 // (-1, -1)
485 squareColors_[0].r = E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c));
486 squareColors_[0].g = E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c));
487 squareColors_[0].b = E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c));
488 squareColors_[0].a = E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c));
489 // (1, -1)
490 squareColors_[1].r = E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c));
491 squareColors_[1].g = E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c));
492 squareColors_[1].b = E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c));
493 squareColors_[1].a = E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c));
494 // (-1, 1)
495 squareColors_[2].r = E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c));
496 squareColors_[2].g = E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c));
497 squareColors_[2].b = E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c));
498 squareColors_[2].a = E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c));
499 // (1, 1)
500 squareColors_[3].r = E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c));
501 squareColors_[3].g = E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c));
502 squareColors_[3].b = E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c));
503 squareColors_[3].a = E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c));
504}
505
506-(ccColor3B) startColor
507{
508 return color_;
509}
510
511-(void) setStartColor:(ccColor3B)colors
512{
513 [self setColor:colors];
514}
515
516-(void) setEndColor:(ccColor3B)colors
517{
518 endColor_ = colors;
519 [self updateColor];
520}
521
522-(void) setStartOpacity: (GLubyte) o
523{
524 startOpacity_ = o;
525 [self updateColor];
526}
527
528-(void) setEndOpacity: (GLubyte) o
529{
530 endOpacity_ = o;
531 [self updateColor];
532}
533
534-(void) setVector: (CGPoint) v
535{
536 vector_ = v;
537 [self updateColor];
538}
539
540-(BOOL) compressedInterpolation
541{
542 return compressedInterpolation_;
543}
544
545-(void) setCompressedInterpolation:(BOOL)compress
546{
547 compressedInterpolation_ = compress;
548 [self updateColor];
549}
550@end
551
552#pragma mark -
553#pragma mark MultiplexLayer
554
555@implementation CCLayerMultiplex
556+(id) layerWithLayers: (CCLayer*) layer, ...
557{
558 va_list args;
559 va_start(args,layer);
560
561 id s = [[[self alloc] initWithLayers: layer vaList:args] autorelease];
562
563 va_end(args);
564 return s;
565}
566
567-(id) initWithLayers: (CCLayer*) layer vaList:(va_list) params
568{
569 if( (self=[super init]) ) {
570
571 layers_ = [[NSMutableArray arrayWithCapacity:5] retain];
572
573 [layers_ addObject: layer];
574
575 CCLayer *l = va_arg(params,CCLayer*);
576 while( l ) {
577 [layers_ addObject: l];
578 l = va_arg(params,CCLayer*);
579 }
580
581 enabledLayer_ = 0;
582 [self addChild: [layers_ objectAtIndex: enabledLayer_]];
583 }
584
585 return self;
586}
587
588-(void) dealloc
589{
590 [layers_ release];
591 [super dealloc];
592}
593
594-(void) switchTo: (unsigned int) n
595{
596 NSAssert( n < [layers_ count], @"Invalid index in MultiplexLayer switchTo message" );
597
598 [self removeChild: [layers_ objectAtIndex:enabledLayer_] cleanup:YES];
599
600 enabledLayer_ = n;
601
602 [self addChild: [layers_ objectAtIndex:n]];
603}
604
605-(void) switchToAndReleaseMe: (unsigned int) n
606{
607 NSAssert( n < [layers_ count], @"Invalid index in MultiplexLayer switchTo message" );
608
609 [self removeChild: [layers_ objectAtIndex:enabledLayer_] cleanup:YES];
610
611 [layers_ replaceObjectAtIndex:enabledLayer_ withObject:[NSNull null]];
612
613 enabledLayer_ = n;
614
615 [self addChild: [layers_ objectAtIndex:n]];
616}
617@end
618
619// XXX Deprecated
620@implementation CCMultiplexLayer
621@end
diff --git a/libs/cocos2d/CCMenu.h b/libs/cocos2d/CCMenu.h new file mode 100755 index 0000000..ef22343 --- /dev/null +++ b/libs/cocos2d/CCMenu.h
@@ -0,0 +1,93 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCMenuItem.h"
29#import "CCLayer.h"
30
31typedef enum {
32 kCCMenuStateWaiting,
33 kCCMenuStateTrackingTouch
34} tCCMenuState;
35
36enum {
37 //* priority used by the menu for the touches
38 kCCMenuTouchPriority = -128,
39
40 //* priority used by the menu for the mouse
41 kCCMenuMousePriority = -128,
42};
43
44/** A CCMenu
45 *
46 * Features and Limitation:
47 * - You can add MenuItem objects in runtime using addChild:
48 * - But the only accecpted children are MenuItem objects
49 */
50@interface CCMenu : CCLayer <CCRGBAProtocol>
51{
52 tCCMenuState state_;
53 CCMenuItem *selectedItem_;
54 GLubyte opacity_;
55 ccColor3B color_;
56}
57
58/** creates a CCMenu with it's items */
59+ (id) menuWithItems: (CCMenuItem*) item, ... NS_REQUIRES_NIL_TERMINATION;
60
61/** initializes a CCMenu with it's items */
62- (id) initWithItems: (CCMenuItem*) item vaList: (va_list) args;
63
64/** align items vertically */
65-(void) alignItemsVertically;
66/** align items vertically with padding
67 @since v0.7.2
68 */
69-(void) alignItemsVerticallyWithPadding:(float) padding;
70
71/** align items horizontally */
72-(void) alignItemsHorizontally;
73/** align items horizontally with padding
74 @since v0.7.2
75 */
76-(void) alignItemsHorizontallyWithPadding: (float) padding;
77
78
79/** align items in rows of columns */
80-(void) alignItemsInColumns: (NSNumber *) columns, ... NS_REQUIRES_NIL_TERMINATION;
81-(void) alignItemsInColumns: (NSNumber *) columns vaList: (va_list) args;
82
83/** align items in columns of rows */
84-(void) alignItemsInRows: (NSNumber *) rows, ... NS_REQUIRES_NIL_TERMINATION;
85-(void) alignItemsInRows: (NSNumber *) rows vaList: (va_list) args;
86
87
88/** conforms to CCRGBAProtocol protocol */
89@property (nonatomic,readonly) GLubyte opacity;
90/** conforms to CCRGBAProtocol protocol */
91@property (nonatomic,readonly) ccColor3B color;
92
93@end
diff --git a/libs/cocos2d/CCMenu.m b/libs/cocos2d/CCMenu.m new file mode 100755 index 0000000..c3cb8f2 --- /dev/null +++ b/libs/cocos2d/CCMenu.m
@@ -0,0 +1,523 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import "CCMenu.h"
30#import "CCDirector.h"
31#import "Support/CGPointExtension.h"
32#import "ccMacros.h"
33
34#import <Availability.h>
35#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
36#import "Platforms/iOS/CCDirectorIOS.h"
37#import "Platforms/iOS/CCTouchDispatcher.h"
38#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
39#import "Platforms/Mac/MacGLView.h"
40#import "Platforms/Mac/CCDirectorMac.h"
41#endif
42
43enum {
44 kDefaultPadding = 5,
45};
46
47@implementation CCMenu
48
49@synthesize opacity = opacity_, color = color_;
50
51- (id) init
52{
53 NSAssert(NO, @"CCMenu: Init not supported.");
54 [self release];
55 return nil;
56}
57
58+(id) menuWithItems: (CCMenuItem*) item, ...
59{
60 va_list args;
61 va_start(args,item);
62
63 id s = [[[self alloc] initWithItems: item vaList:args] autorelease];
64
65 va_end(args);
66 return s;
67}
68
69-(id) initWithItems: (CCMenuItem*) item vaList: (va_list) args
70{
71 if( (self=[super init]) ) {
72
73#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
74 self.isTouchEnabled = YES;
75#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
76 self.isMouseEnabled = YES;
77#endif
78
79 // menu in the center of the screen
80 CGSize s = [[CCDirector sharedDirector] winSize];
81
82 self.isRelativeAnchorPoint = NO;
83 anchorPoint_ = ccp(0.5f, 0.5f);
84 [self setContentSize:s];
85
86 // XXX: in v0.7, winSize should return the visible size
87 // XXX: so the bar calculation should be done there
88#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
89 CGRect r = [[UIApplication sharedApplication] statusBarFrame];
90 ccDeviceOrientation orientation = [[CCDirector sharedDirector] deviceOrientation];
91 if( orientation == CCDeviceOrientationLandscapeLeft || orientation == CCDeviceOrientationLandscapeRight )
92 s.height -= r.size.width;
93 else
94 s.height -= r.size.height;
95#endif
96 self.position = ccp(s.width/2, s.height/2);
97
98 int z=0;
99
100 if (item) {
101 [self addChild: item z:z];
102 CCMenuItem *i = va_arg(args, CCMenuItem*);
103 while(i) {
104 z++;
105 [self addChild: i z:z];
106 i = va_arg(args, CCMenuItem*);
107 }
108 }
109 // [self alignItemsVertically];
110
111 selectedItem_ = nil;
112 state_ = kCCMenuStateWaiting;
113 }
114
115 return self;
116}
117
118-(void) dealloc
119{
120 [super dealloc];
121}
122
123/*
124 * override add:
125 */
126-(void) addChild:(CCMenuItem*)child z:(NSInteger)z tag:(NSInteger) aTag
127{
128 NSAssert( [child isKindOfClass:[CCMenuItem class]], @"Menu only supports MenuItem objects as children");
129 [super addChild:child z:z tag:aTag];
130}
131
132- (void) onExit
133{
134 if(state_ == kCCMenuStateTrackingTouch)
135 {
136 [selectedItem_ unselected];
137 state_ = kCCMenuStateWaiting;
138 selectedItem_ = nil;
139 }
140 [super onExit];
141}
142
143#pragma mark Menu - Touches
144
145#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
146-(void) registerWithTouchDispatcher
147{
148 [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority swallowsTouches:YES];
149}
150
151-(CCMenuItem *) itemForTouch: (UITouch *) touch
152{
153 CGPoint touchLocation = [touch locationInView: [touch view]];
154 touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
155
156 CCMenuItem* item;
157 CCARRAY_FOREACH(children_, item){
158 // ignore invisible and disabled items: issue #779, #866
159 if ( [item visible] && [item isEnabled] ) {
160
161 CGPoint local = [item convertToNodeSpace:touchLocation];
162 CGRect r = [item rect];
163 r.origin = CGPointZero;
164
165 if( CGRectContainsPoint( r, local ) )
166 return item;
167 }
168 }
169 return nil;
170}
171
172-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
173{
174 if( state_ != kCCMenuStateWaiting || !visible_ )
175 return NO;
176
177 selectedItem_ = [self itemForTouch:touch];
178 [selectedItem_ selected];
179
180 if( selectedItem_ ) {
181 state_ = kCCMenuStateTrackingTouch;
182 return YES;
183 }
184 return NO;
185}
186
187-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
188{
189 NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchEnded] -- invalid state");
190
191 [selectedItem_ unselected];
192 [selectedItem_ activate];
193
194 state_ = kCCMenuStateWaiting;
195}
196
197-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event
198{
199 NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchCancelled] -- invalid state");
200
201 [selectedItem_ unselected];
202
203 state_ = kCCMenuStateWaiting;
204}
205
206-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
207{
208 NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchMoved] -- invalid state");
209
210 CCMenuItem *currentItem = [self itemForTouch:touch];
211
212 if (currentItem != selectedItem_) {
213 [selectedItem_ unselected];
214 selectedItem_ = currentItem;
215 [selectedItem_ selected];
216 }
217}
218
219#pragma mark Menu - Mouse
220
221#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
222
223-(NSInteger) mouseDelegatePriority
224{
225 return kCCMenuMousePriority+1;
226}
227
228-(CCMenuItem *) itemForMouseEvent: (NSEvent *) event
229{
230 CGPoint location = [(CCDirectorMac*)[CCDirector sharedDirector] convertEventToGL:event];
231
232 CCMenuItem* item;
233 CCARRAY_FOREACH(children_, item){
234 // ignore invisible and disabled items: issue #779, #866
235 if ( [item visible] && [item isEnabled] ) {
236
237 CGPoint local = [item convertToNodeSpace:location];
238
239 CGRect r = [item rect];
240 r.origin = CGPointZero;
241
242 if( CGRectContainsPoint( r, local ) )
243 return item;
244 }
245 }
246 return nil;
247}
248
249-(BOOL) ccMouseUp:(NSEvent *)event
250{
251 if( ! visible_ )
252 return NO;
253
254 if(state_ == kCCMenuStateTrackingTouch) {
255 if( selectedItem_ ) {
256 [selectedItem_ unselected];
257 [selectedItem_ activate];
258 }
259 state_ = kCCMenuStateWaiting;
260
261 return YES;
262 }
263 return NO;
264}
265
266-(BOOL) ccMouseDown:(NSEvent *)event
267{
268 if( ! visible_ )
269 return NO;
270
271 selectedItem_ = [self itemForMouseEvent:event];
272 [selectedItem_ selected];
273
274 if( selectedItem_ ) {
275 state_ = kCCMenuStateTrackingTouch;
276 return YES;
277 }
278
279 return NO;
280}
281
282-(BOOL) ccMouseDragged:(NSEvent *)event
283{
284 if( ! visible_ )
285 return NO;
286
287 if(state_ == kCCMenuStateTrackingTouch) {
288 CCMenuItem *currentItem = [self itemForMouseEvent:event];
289
290 if (currentItem != selectedItem_) {
291 [selectedItem_ unselected];
292 selectedItem_ = currentItem;
293 [selectedItem_ selected];
294 }
295
296 return YES;
297 }
298 return NO;
299}
300
301#endif // Mac Mouse support
302
303#pragma mark Menu - Alignment
304-(void) alignItemsVertically
305{
306 [self alignItemsVerticallyWithPadding:kDefaultPadding];
307}
308-(void) alignItemsVerticallyWithPadding:(float)padding
309{
310 float height = -padding;
311
312 CCMenuItem *item;
313 CCARRAY_FOREACH(children_, item)
314 height += item.contentSize.height * item.scaleY + padding;
315
316 float y = height / 2.0f;
317
318 CCARRAY_FOREACH(children_, item) {
319 CGSize itemSize = item.contentSize;
320 [item setPosition:ccp(0, y - itemSize.height * item.scaleY / 2.0f)];
321 y -= itemSize.height * item.scaleY + padding;
322 }
323}
324
325-(void) alignItemsHorizontally
326{
327 [self alignItemsHorizontallyWithPadding:kDefaultPadding];
328}
329
330-(void) alignItemsHorizontallyWithPadding:(float)padding
331{
332
333 float width = -padding;
334 CCMenuItem *item;
335 CCARRAY_FOREACH(children_, item)
336 width += item.contentSize.width * item.scaleX + padding;
337
338 float x = -width / 2.0f;
339
340 CCARRAY_FOREACH(children_, item){
341 CGSize itemSize = item.contentSize;
342 [item setPosition:ccp(x + itemSize.width * item.scaleX / 2.0f, 0)];
343 x += itemSize.width * item.scaleX + padding;
344 }
345}
346
347-(void) alignItemsInColumns: (NSNumber *) columns, ...
348{
349 va_list args;
350 va_start(args, columns);
351
352 [self alignItemsInColumns:columns vaList:args];
353
354 va_end(args);
355}
356
357-(void) alignItemsInColumns: (NSNumber *) columns vaList: (va_list) args
358{
359 NSMutableArray *rows = [[NSMutableArray alloc] initWithObjects:columns, nil];
360 columns = va_arg(args, NSNumber*);
361 while(columns) {
362 [rows addObject:columns];
363 columns = va_arg(args, NSNumber*);
364 }
365
366 int height = -5;
367 NSUInteger row = 0, rowHeight = 0, columnsOccupied = 0, rowColumns;
368 CCMenuItem *item;
369 CCARRAY_FOREACH(children_, item){
370 NSAssert( row < [rows count], @"Too many menu items for the amount of rows/columns.");
371
372 rowColumns = [(NSNumber *) [rows objectAtIndex:row] unsignedIntegerValue];
373 NSAssert( rowColumns, @"Can't have zero columns on a row");
374
375 rowHeight = fmaxf(rowHeight, item.contentSize.height);
376 ++columnsOccupied;
377
378 if(columnsOccupied >= rowColumns) {
379 height += rowHeight + 5;
380
381 columnsOccupied = 0;
382 rowHeight = 0;
383 ++row;
384 }
385 }
386 NSAssert( !columnsOccupied, @"Too many rows/columns for available menu items." );
387
388 CGSize winSize = [[CCDirector sharedDirector] winSize];
389
390 row = 0; rowHeight = 0; rowColumns = 0;
391 float w, x, y = height / 2;
392 CCARRAY_FOREACH(children_, item) {
393 if(rowColumns == 0) {
394 rowColumns = [(NSNumber *) [rows objectAtIndex:row] unsignedIntegerValue];
395 w = winSize.width / (1 + rowColumns);
396 x = w;
397 }
398
399 CGSize itemSize = item.contentSize;
400 rowHeight = fmaxf(rowHeight, itemSize.height);
401 [item setPosition:ccp(x - winSize.width / 2,
402 y - itemSize.height / 2)];
403
404 x += w;
405 ++columnsOccupied;
406
407 if(columnsOccupied >= rowColumns) {
408 y -= rowHeight + 5;
409
410 columnsOccupied = 0;
411 rowColumns = 0;
412 rowHeight = 0;
413 ++row;
414 }
415 }
416
417 [rows release];
418}
419
420-(void) alignItemsInRows: (NSNumber *) rows, ...
421{
422 va_list args;
423 va_start(args, rows);
424
425 [self alignItemsInRows:rows vaList:args];
426
427 va_end(args);
428}
429
430-(void) alignItemsInRows: (NSNumber *) rows vaList: (va_list) args
431{
432 NSMutableArray *columns = [[NSMutableArray alloc] initWithObjects:rows, nil];
433 rows = va_arg(args, NSNumber*);
434 while(rows) {
435 [columns addObject:rows];
436 rows = va_arg(args, NSNumber*);
437 }
438
439 NSMutableArray *columnWidths = [[NSMutableArray alloc] init];
440 NSMutableArray *columnHeights = [[NSMutableArray alloc] init];
441
442 int width = -10, columnHeight = -5;
443 NSUInteger column = 0, columnWidth = 0, rowsOccupied = 0, columnRows;
444 CCMenuItem *item;
445 CCARRAY_FOREACH(children_, item){
446 NSAssert( column < [columns count], @"Too many menu items for the amount of rows/columns.");
447
448 columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue];
449 NSAssert( columnRows, @"Can't have zero rows on a column");
450
451 CGSize itemSize = item.contentSize;
452 columnWidth = fmaxf(columnWidth, itemSize.width);
453 columnHeight += itemSize.height + 5;
454 ++rowsOccupied;
455
456 if(rowsOccupied >= columnRows) {
457 [columnWidths addObject:[NSNumber numberWithUnsignedInteger:columnWidth]];
458 [columnHeights addObject:[NSNumber numberWithUnsignedInteger:columnHeight]];
459 width += columnWidth + 10;
460
461 rowsOccupied = 0;
462 columnWidth = 0;
463 columnHeight = -5;
464 ++column;
465 }
466 }
467 NSAssert( !rowsOccupied, @"Too many rows/columns for available menu items.");
468
469 CGSize winSize = [[CCDirector sharedDirector] winSize];
470
471 column = 0; columnWidth = 0; columnRows = 0;
472 float x = -width / 2, y;
473
474 CCARRAY_FOREACH(children_, item){
475 if(columnRows == 0) {
476 columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue];
477 y = ([(NSNumber *) [columnHeights objectAtIndex:column] intValue] + winSize.height) / 2;
478 }
479
480 CGSize itemSize = item.contentSize;
481 columnWidth = fmaxf(columnWidth, itemSize.width);
482 [item setPosition:ccp(x + [(NSNumber *) [columnWidths objectAtIndex:column] unsignedIntegerValue] / 2,
483 y - winSize.height / 2)];
484
485 y -= itemSize.height + 10;
486 ++rowsOccupied;
487
488 if(rowsOccupied >= columnRows) {
489 x += columnWidth + 5;
490
491 rowsOccupied = 0;
492 columnRows = 0;
493 columnWidth = 0;
494 ++column;
495 }
496 }
497
498 [columns release];
499 [columnWidths release];
500 [columnHeights release];
501}
502
503#pragma mark Menu - Opacity Protocol
504
505/** Override synthesized setOpacity to recurse items */
506- (void) setOpacity:(GLubyte)newOpacity
507{
508 opacity_ = newOpacity;
509
510 id<CCRGBAProtocol> item;
511 CCARRAY_FOREACH(children_, item)
512 [item setOpacity:opacity_];
513}
514
515-(void) setColor:(ccColor3B)color
516{
517 color_ = color;
518
519 id<CCRGBAProtocol> item;
520 CCARRAY_FOREACH(children_, item)
521 [item setColor:color_];
522}
523@end
diff --git a/libs/cocos2d/CCMenuItem.h b/libs/cocos2d/CCMenuItem.h new file mode 100755 index 0000000..2437394 --- /dev/null +++ b/libs/cocos2d/CCMenuItem.h
@@ -0,0 +1,377 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCBlockSupport.h"
28
29#import "CCNode.h"
30#import "CCProtocols.h"
31
32@class CCSprite;
33
34#define kCCItemSize 32
35
36#pragma mark -
37#pragma mark CCMenuItem
38/** CCMenuItem base class
39 *
40 * Subclass CCMenuItem (or any subclass) to create your custom CCMenuItem objects.
41 */
42@interface CCMenuItem : CCNode
43{
44 NSInvocation *invocation_;
45#if NS_BLOCKS_AVAILABLE
46 // used for menu items using a block
47 void (^block_)(id sender);
48#endif
49
50 BOOL isEnabled_;
51 BOOL isSelected_;
52}
53
54/** returns whether or not the item is selected
55@since v0.8.2
56*/
57@property (nonatomic,readonly) BOOL isSelected;
58
59/** Creates a CCMenuItem with a target/selector */
60+(id) itemWithTarget:(id)target selector:(SEL)selector;
61
62/** Initializes a CCMenuItem with a target/selector */
63-(id) initWithTarget:(id)target selector:(SEL)selector;
64
65#if NS_BLOCKS_AVAILABLE
66/** Creates a CCMenuItem with the specified block.
67 The block will be "copied".
68 */
69+(id) itemWithBlock:(void(^)(id sender))block;
70
71/** Initializes a CCMenuItem with the specified block.
72 The block will be "copied".
73*/
74-(id) initWithBlock:(void(^)(id sender))block;
75#endif
76
77/** Returns the outside box in points */
78-(CGRect) rect;
79
80/** Activate the item */
81-(void) activate;
82
83/** The item was selected (not activated), similar to "mouse-over" */
84-(void) selected;
85
86/** The item was unselected */
87-(void) unselected;
88
89/** Enable or disabled the CCMenuItem */
90-(void) setIsEnabled:(BOOL)enabled;
91/** Returns whether or not the CCMenuItem is enabled */
92-(BOOL) isEnabled;
93@end
94
95#pragma mark -
96#pragma mark CCMenuItemLabel
97
98/** An abstract class for "label" CCMenuItemLabel items
99 Any CCNode that supports the CCLabelProtocol protocol can be added.
100 Supported nodes:
101 - CCLabelBMFont
102 - CCLabelAtlas
103 - CCLabelTTF
104 */
105@interface CCMenuItemLabel : CCMenuItem <CCRGBAProtocol>
106{
107 CCNode<CCLabelProtocol, CCRGBAProtocol> *label_;
108 ccColor3B colorBackup;
109 ccColor3B disabledColor_;
110 float originalScale_;
111}
112
113/** the color that will be used to disable the item */
114@property (nonatomic,readwrite) ccColor3B disabledColor;
115
116/** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */
117@property (nonatomic,readwrite,assign) CCNode<CCLabelProtocol, CCRGBAProtocol>* label;
118
119/** creates a CCMenuItemLabel with a Label. Target and selector will be nill */
120+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label;
121
122/** creates a CCMenuItemLabel with a Label, target and selector */
123+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector;
124
125/** initializes a CCMenuItemLabel with a Label, target and selector */
126-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector;
127
128#if NS_BLOCKS_AVAILABLE
129/** creates a CCMenuItemLabel with a Label and a block to execute.
130 The block will be "copied".
131 */
132+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block;
133
134/** initializes a CCMenuItemLabel with a Label and a block to execute.
135 The block will be "copied".
136 */
137-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block;
138#endif
139
140/** sets a new string to the inner label */
141-(void) setString:(NSString*)label;
142
143/** Enable or disabled the CCMenuItemFont
144 @warning setIsEnabled changes the RGB color of the font
145 */
146-(void) setIsEnabled: (BOOL)enabled;
147@end
148
149#pragma mark -
150#pragma mark CCMenuItemAtlasFont
151
152/** A CCMenuItemAtlasFont
153 Helper class that creates a MenuItemLabel class with a LabelAtlas
154 */
155@interface CCMenuItemAtlasFont : CCMenuItemLabel
156{
157}
158
159/** creates a menu item from a string and atlas with a target/selector */
160+(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap;
161
162/** creates a menu item from a string and atlas. Use it with MenuItemToggle */
163+(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb;
164
165/** initializes a menu item from a string and atlas with a target/selector */
166-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb;
167
168#if NS_BLOCKS_AVAILABLE
169/** creates a menu item from a string and atlas. Use it with MenuItemToggle.
170 The block will be "copied".
171 */
172+(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block;
173
174/** initializes a menu item from a string and atlas with a block.
175 The block will be "copied".
176 */
177-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block;
178#endif
179
180@end
181
182#pragma mark -
183#pragma mark CCMenuItemFont
184
185/** A CCMenuItemFont
186 Helper class that creates a CCMenuItemLabel class with a Label
187 */
188@interface CCMenuItemFont : CCMenuItemLabel
189{
190 NSUInteger fontSize_;
191 NSString *fontName_;
192}
193/** set default font size */
194+(void) setFontSize: (NSUInteger) s;
195
196/** get default font size */
197+(NSUInteger) fontSize;
198
199/** set default font name */
200+(void) setFontName: (NSString*) n;
201
202/** get default font name */
203+(NSString*) fontName;
204
205/** creates a menu item from a string without target/selector. To be used with CCMenuItemToggle */
206+(id) itemFromString: (NSString*) value;
207
208/** creates a menu item from a string with a target/selector */
209+(id) itemFromString: (NSString*) value target:(id) r selector:(SEL) s;
210
211/** initializes a menu item from a string with a target/selector */
212-(id) initFromString: (NSString*) value target:(id) r selector:(SEL) s;
213
214/** set font size */
215-(void) setFontSize: (NSUInteger) s;
216
217/** get font size */
218-(NSUInteger) fontSize;
219
220/** set the font name */
221-(void) setFontName: (NSString*) n;
222
223/** get the font name */
224-(NSString*) fontName;
225
226#if NS_BLOCKS_AVAILABLE
227/** creates a menu item from a string with the specified block.
228 The block will be "copied".
229 */
230+(id) itemFromString: (NSString*) value block:(void(^)(id sender))block;
231
232/** initializes a menu item from a string with the specified block.
233 The block will be "copied".
234 */
235-(id) initFromString: (NSString*) value block:(void(^)(id sender))block;
236#endif
237@end
238
239#pragma mark -
240#pragma mark CCMenuItemSprite
241
242/** CCMenuItemSprite accepts CCNode<CCRGBAProtocol> objects as items.
243 The images has 3 different states:
244 - unselected image
245 - selected image
246 - disabled image
247
248 @since v0.8.0
249 */
250@interface CCMenuItemSprite : CCMenuItem <CCRGBAProtocol>
251{
252 CCNode<CCRGBAProtocol> *normalImage_, *selectedImage_, *disabledImage_;
253}
254
255// weak references
256
257/** the image used when the item is not selected */
258@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *normalImage;
259/** the image used when the item is selected */
260@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *selectedImage;
261/** the image used when the item is disabled */
262@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *disabledImage;
263
264/** creates a menu item with a normal and selected image*/
265+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite;
266/** creates a menu item with a normal and selected image with target/selector */
267+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite target:(id)target selector:(SEL)selector;
268/** creates a menu item with a normal,selected and disabled image with target/selector */
269+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector;
270/** initializes a menu item with a normal, selected and disabled image with target/selector */
271-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector;
272
273#if NS_BLOCKS_AVAILABLE
274/** creates a menu item with a normal and selected image with a block.
275 The block will be "copied".
276 */
277+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite block:(void(^)(id sender))block;
278/** creates a menu item with a normal,selected and disabled image with a block.
279 The block will be "copied".
280 */
281+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite block:(void(^)(id sender))block;
282/** initializes a menu item with a normal, selected and disabled image with a block.
283 The block will be "copied".
284 */
285-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite block:(void(^)(id sender))block;
286#endif
287
288@end
289
290#pragma mark -
291#pragma mark CCMenuItemImage
292
293/** CCMenuItemImage accepts images as items.
294 The images has 3 different states:
295 - unselected image
296 - selected image
297 - disabled image
298
299 For best results try that all images are of the same size
300 */
301@interface CCMenuItemImage : CCMenuItemSprite
302{
303}
304
305/** creates a menu item with a normal and selected image*/
306+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2;
307/** creates a menu item with a normal and selected image with target/selector */
308+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) r selector:(SEL) s;
309/** creates a menu item with a normal,selected and disabled image with target/selector */
310+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s;
311/** initializes a menu item with a normal, selected and disabled image with target/selector */
312-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s;
313#if NS_BLOCKS_AVAILABLE
314/** creates a menu item with a normal and selected image with a block.
315 The block will be "copied".
316 */
317+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block;
318/** creates a menu item with a normal,selected and disabled image with a block.
319 The block will be "copied".
320*/
321+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block;
322/** initializes a menu item with a normal, selected and disabled image with a block.
323 The block will be "copied".
324*/
325-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block;
326#endif
327@end
328
329#pragma mark -
330#pragma mark CCMenuItemToggle
331
332/** A CCMenuItemToggle
333 A simple container class that "toggles" it's inner items
334 The inner itmes can be any MenuItem
335 */
336@interface CCMenuItemToggle : CCMenuItem <CCRGBAProtocol>
337{
338 NSUInteger selectedIndex_;
339 NSMutableArray* subItems_;
340 GLubyte opacity_;
341 ccColor3B color_;
342}
343
344/** conforms with CCRGBAProtocol protocol */
345@property (nonatomic,readonly) GLubyte opacity;
346/** conforms with CCRGBAProtocol protocol */
347@property (nonatomic,readonly) ccColor3B color;
348
349/** returns the selected item */
350@property (nonatomic,readwrite) NSUInteger selectedIndex;
351/** NSMutableArray that contains the subitems. You can add/remove items in runtime, and you can replace the array with a new one.
352 @since v0.7.2
353 */
354@property (nonatomic,readwrite,retain) NSMutableArray *subItems;
355
356/** creates a menu item from a list of items with a target/selector */
357+(id) itemWithTarget:(id)t selector:(SEL)s items:(CCMenuItem*) item, ... NS_REQUIRES_NIL_TERMINATION;
358
359/** initializes a menu item from a list of items with a target selector */
360-(id) initWithTarget:(id)t selector:(SEL)s items:(CCMenuItem*) item vaList:(va_list) args;
361
362#if NS_BLOCKS_AVAILABLE
363/** creates a menu item from a list of items and executes the given block when the item is selected.
364 The block will be "copied".
365 */
366+(id) itemWithBlock:(void(^)(id sender))block items:(CCMenuItem*)item, ... NS_REQUIRES_NIL_TERMINATION;
367
368/** initializes a menu item from a list of items with a block.
369 The block will be "copied".
370 */
371-(id) initWithBlock:(void (^)(id))block items:(CCMenuItem*)item vaList:(va_list)args;
372#endif
373
374/** return the selected item */
375-(CCMenuItem*) selectedItem;
376@end
377
diff --git a/libs/cocos2d/CCMenuItem.m b/libs/cocos2d/CCMenuItem.m new file mode 100755 index 0000000..f88c0e0 --- /dev/null +++ b/libs/cocos2d/CCMenuItem.m
@@ -0,0 +1,795 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCMenuItem.h"
28#import "CCLabelTTF.h"
29#import "CCLabelAtlas.h"
30#import "CCActionInterval.h"
31#import "CCSprite.h"
32#import "Support/CGPointExtension.h"
33#import "CCBlockSupport.h"
34
35 static NSUInteger _fontSize = kCCItemSize;
36static NSString *_fontName = @"Marker Felt";
37static BOOL _fontNameRelease = NO;
38
39
40const uint32_t kCurrentItem = 0xc0c05001;
41const uint32_t kZoomActionTag = 0xc0c05002;
42
43
44#pragma mark -
45#pragma mark CCMenuItem
46
47@implementation CCMenuItem
48
49@synthesize isSelected=isSelected_;
50-(id) init
51{
52 NSAssert(NO, @"MenuItemInit: Init not supported.");
53 [self release];
54 return nil;
55}
56
57+(id) itemWithTarget:(id) r selector:(SEL) s
58{
59 return [[[self alloc] initWithTarget:r selector:s] autorelease];
60}
61
62-(id) initWithTarget:(id) rec selector:(SEL) cb
63{
64 if((self=[super init]) ) {
65
66 anchorPoint_ = ccp(0.5f, 0.5f);
67 NSMethodSignature * sig = nil;
68
69 if( rec && cb ) {
70 sig = [rec methodSignatureForSelector:cb];
71
72 invocation_ = nil;
73 invocation_ = [NSInvocation invocationWithMethodSignature:sig];
74 [invocation_ setTarget:rec];
75 [invocation_ setSelector:cb];
76#if NS_BLOCKS_AVAILABLE
77 if ([sig numberOfArguments] == 3)
78#endif
79 [invocation_ setArgument:&self atIndex:2];
80
81 [invocation_ retain];
82 }
83
84 isEnabled_ = YES;
85 isSelected_ = NO;
86 }
87
88 return self;
89}
90
91#if NS_BLOCKS_AVAILABLE
92
93+(id) itemWithBlock:(void(^)(id sender))block {
94 return [[[self alloc] initWithBlock:block] autorelease];
95}
96
97-(id) initWithBlock:(void(^)(id sender))block {
98 block_ = [block copy];
99 return [self initWithTarget:block_ selector:@selector(ccCallbackBlockWithSender:)];
100}
101
102#endif // NS_BLOCKS_AVAILABLE
103
104-(void) dealloc
105{
106 [invocation_ release];
107
108#if NS_BLOCKS_AVAILABLE
109 [block_ release];
110#endif
111
112 [super dealloc];
113}
114
115-(void) selected
116{
117 isSelected_ = YES;
118}
119
120-(void) unselected
121{
122 isSelected_ = NO;
123}
124
125-(void) activate
126{
127 if(isEnabled_)
128 [invocation_ invoke];
129}
130
131-(void) setIsEnabled: (BOOL)enabled
132{
133 isEnabled_ = enabled;
134}
135
136-(BOOL) isEnabled
137{
138 return isEnabled_;
139}
140
141-(CGRect) rect
142{
143 return CGRectMake( position_.x - contentSize_.width*anchorPoint_.x,
144 position_.y - contentSize_.height*anchorPoint_.y,
145 contentSize_.width, contentSize_.height);
146}
147
148@end
149
150
151#pragma mark -
152#pragma mark CCMenuItemLabel
153
154@implementation CCMenuItemLabel
155
156@synthesize disabledColor = disabledColor_;
157
158+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector
159{
160 return [[[self alloc] initWithLabel:label target:target selector:selector] autorelease];
161}
162
163+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label
164{
165 return [[[self alloc] initWithLabel:label target:nil selector:NULL] autorelease];
166}
167
168-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector
169{
170 if( (self=[super initWithTarget:target selector:selector]) ) {
171 originalScale_ = 1;
172 colorBackup = ccWHITE;
173 disabledColor_ = ccc3( 126,126,126);
174 self.label = label;
175
176 }
177 return self;
178}
179
180#if NS_BLOCKS_AVAILABLE
181
182+(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block {
183 return [[[self alloc] initWithLabel:label block:block] autorelease];
184}
185
186-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block {
187 block_ = [block copy];
188 return [self initWithLabel:label target:block_ selector:@selector(ccCallbackBlockWithSender:)];
189}
190
191#endif // NS_BLOCKS_AVAILABLE
192
193-(CCNode<CCLabelProtocol, CCRGBAProtocol>*) label
194{
195 return label_;
196}
197-(void) setLabel:(CCNode<CCLabelProtocol, CCRGBAProtocol>*) label
198{
199 if( label != label_ ) {
200 [self removeChild:label_ cleanup:YES];
201 [self addChild:label];
202
203 label_ = label;
204 label_.anchorPoint = ccp(0,0);
205
206 [self setContentSize:[label_ contentSize]];
207 }
208}
209
210-(void) setString:(NSString *)string
211{
212 [label_ setString:string];
213 [self setContentSize: [label_ contentSize]];
214}
215
216-(void) activate {
217 if(isEnabled_) {
218 [self stopAllActions];
219
220 self.scale = originalScale_;
221
222 [super activate];
223 }
224}
225
226-(void) selected
227{
228 // subclass to change the default action
229 if(isEnabled_) {
230 [super selected];
231
232 CCAction *action = [self getActionByTag:kZoomActionTag];
233 if( action )
234 [self stopAction:action];
235 else
236 originalScale_ = self.scale;
237
238 CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:originalScale_ * 1.2f];
239 zoomAction.tag = kZoomActionTag;
240 [self runAction:zoomAction];
241 }
242}
243
244-(void) unselected
245{
246 // subclass to change the default action
247 if(isEnabled_) {
248 [super unselected];
249 [self stopActionByTag:kZoomActionTag];
250 CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:originalScale_];
251 zoomAction.tag = kZoomActionTag;
252 [self runAction:zoomAction];
253 }
254}
255
256-(void) setIsEnabled: (BOOL)enabled
257{
258 if( isEnabled_ != enabled ) {
259 if(enabled == NO) {
260 colorBackup = [label_ color];
261 [label_ setColor: disabledColor_];
262 }
263 else
264 [label_ setColor:colorBackup];
265 }
266
267 [super setIsEnabled:enabled];
268}
269
270- (void) setOpacity: (GLubyte)opacity
271{
272 [label_ setOpacity:opacity];
273}
274-(GLubyte) opacity
275{
276 return [label_ opacity];
277}
278-(void) setColor:(ccColor3B)color
279{
280 [label_ setColor:color];
281}
282-(ccColor3B) color
283{
284 return [label_ color];
285}
286@end
287
288#pragma mark -
289#pragma mark CCMenuItemAtlasFont
290
291@implementation CCMenuItemAtlasFont
292
293+(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap
294{
295 return [CCMenuItemAtlasFont itemFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:nil selector:nil];
296}
297
298+(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb
299{
300 return [[[self alloc] initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:rec selector:cb] autorelease];
301}
302
303-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb
304{
305 NSAssert( [value length] != 0, @"value length must be greater than 0");
306
307 CCLabelAtlas *label = [[CCLabelAtlas alloc] initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap];
308 [label autorelease];
309
310 if((self=[super initWithLabel:label target:rec selector:cb]) ) {
311 // do something ?
312 }
313
314 return self;
315}
316
317#if NS_BLOCKS_AVAILABLE
318+(id) itemFromString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block {
319 return [[[self alloc] initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap block:block] autorelease];
320}
321
322-(id) initFromString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block {
323 block_ = [block copy];
324 return [self initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:block_ selector:@selector(ccCallbackBlockWithSender:)];
325}
326#endif // NS_BLOCKS_AVAILABLE
327
328-(void) dealloc
329{
330 [super dealloc];
331}
332@end
333
334
335#pragma mark -
336#pragma mark CCMenuItemFont
337
338@implementation CCMenuItemFont
339
340+(void) setFontSize: (NSUInteger) s
341{
342 _fontSize = s;
343}
344
345+(NSUInteger) fontSize
346{
347 return _fontSize;
348}
349
350+(void) setFontName: (NSString*) n
351{
352 if( _fontNameRelease )
353 [_fontName release];
354
355 _fontName = [n retain];
356 _fontNameRelease = YES;
357}
358
359+(NSString*) fontName
360{
361 return _fontName;
362}
363
364+(id) itemFromString: (NSString*) value target:(id) r selector:(SEL) s
365{
366 return [[[self alloc] initFromString: value target:r selector:s] autorelease];
367}
368
369+(id) itemFromString: (NSString*) value
370{
371 return [[[self alloc] initFromString: value target:nil selector:nil] autorelease];
372}
373
374-(id) initFromString: (NSString*) value target:(id) rec selector:(SEL) cb
375{
376 NSAssert( [value length] != 0, @"Value length must be greater than 0");
377
378 fontName_ = [_fontName copy];
379 fontSize_ = _fontSize;
380
381 CCLabelTTF *label = [CCLabelTTF labelWithString:value fontName:fontName_ fontSize:fontSize_];
382
383 if((self=[super initWithLabel:label target:rec selector:cb]) ) {
384 // do something ?
385 }
386
387 return self;
388}
389
390-(void) recreateLabel
391{
392 CCLabelTTF *label = [CCLabelTTF labelWithString:[label_ string] fontName:fontName_ fontSize:fontSize_];
393 self.label = label;
394}
395
396-(void) setFontSize: (NSUInteger) size
397{
398 fontSize_ = size;
399 [self recreateLabel];
400}
401
402-(NSUInteger) fontSize
403{
404 return fontSize_;
405}
406
407-(void) setFontName: (NSString*) fontName
408{
409 if (fontName_)
410 [fontName_ release];
411
412 fontName_ = [fontName copy];
413 [self recreateLabel];
414}
415
416-(NSString*) fontName
417{
418 return fontName_;
419}
420
421#if NS_BLOCKS_AVAILABLE
422+(id) itemFromString: (NSString*) value block:(void(^)(id sender))block
423{
424 return [[[self alloc] initFromString:value block:block] autorelease];
425}
426
427-(id) initFromString: (NSString*) value block:(void(^)(id sender))block
428{
429 block_ = [block copy];
430 return [self initFromString:value target:block_ selector:@selector(ccCallbackBlockWithSender:)];
431}
432#endif // NS_BLOCKS_AVAILABLE
433
434@end
435
436#pragma mark -
437#pragma mark CCMenuItemSprite
438@implementation CCMenuItemSprite
439
440@synthesize normalImage=normalImage_, selectedImage=selectedImage_, disabledImage=disabledImage_;
441
442+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite
443{
444 return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:nil selector:nil];
445}
446+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite target:(id)target selector:(SEL)selector
447{
448 return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:target selector:selector];
449}
450+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector
451{
452 return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:target selector:selector] autorelease];
453}
454-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector
455{
456 if( (self=[super initWithTarget:target selector:selector]) ) {
457
458 self.normalImage = normalSprite;
459 self.selectedImage = selectedSprite;
460 self.disabledImage = disabledSprite;
461
462 [self setContentSize: [normalImage_ contentSize]];
463 }
464 return self;
465}
466
467#if NS_BLOCKS_AVAILABLE
468+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite block:(void(^)(id sender))block {
469 return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil block:block];
470}
471
472+(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite block:(void(^)(id sender))block {
473 return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite block:block] autorelease];
474}
475
476-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite block:(void(^)(id sender))block {
477 block_ = [block copy];
478 return [self initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:block_ selector:@selector(ccCallbackBlockWithSender:)];
479}
480#endif // NS_BLOCKS_AVAILABLE
481
482
483-(void) setNormalImage:(CCNode <CCRGBAProtocol>*)image
484{
485 if( image != normalImage_ ) {
486 image.anchorPoint = ccp(0,0);
487 image.visible = YES;
488
489 [self removeChild:normalImage_ cleanup:YES];
490 [self addChild:image];
491
492 normalImage_ = image;
493 }
494}
495
496-(void) setSelectedImage:(CCNode <CCRGBAProtocol>*)image
497{
498 if( image != selectedImage_ ) {
499 image.anchorPoint = ccp(0,0);
500 image.visible = NO;
501
502 [self removeChild:selectedImage_ cleanup:YES];
503 [self addChild:image];
504
505 selectedImage_ = image;
506 }
507}
508
509-(void) setDisabledImage:(CCNode <CCRGBAProtocol>*)image
510{
511 if( image != disabledImage_ ) {
512 image.anchorPoint = ccp(0,0);
513 image.visible = NO;
514
515 [self removeChild:disabledImage_ cleanup:YES];
516 [self addChild:image];
517
518 disabledImage_ = image;
519 }
520}
521
522#pragma mark CCMenuItemImage - CCRGBAProtocol protocol
523- (void) setOpacity: (GLubyte)opacity
524{
525 [normalImage_ setOpacity:opacity];
526 [selectedImage_ setOpacity:opacity];
527 [disabledImage_ setOpacity:opacity];
528}
529
530-(void) setColor:(ccColor3B)color
531{
532 [normalImage_ setColor:color];
533 [selectedImage_ setColor:color];
534 [disabledImage_ setColor:color];
535}
536
537-(GLubyte) opacity
538{
539 return [normalImage_ opacity];
540}
541
542-(ccColor3B) color
543{
544 return [normalImage_ color];
545}
546
547-(void) selected
548{
549 [super selected];
550
551 if( selectedImage_ ) {
552 [normalImage_ setVisible:NO];
553 [selectedImage_ setVisible:YES];
554 [disabledImage_ setVisible:NO];
555
556 } else { // there is not selected image
557
558 [normalImage_ setVisible:YES];
559 [selectedImage_ setVisible:NO];
560 [disabledImage_ setVisible:NO];
561 }
562}
563
564-(void) unselected
565{
566 [super unselected];
567 [normalImage_ setVisible:YES];
568 [selectedImage_ setVisible:NO];
569 [disabledImage_ setVisible:NO];
570}
571
572-(void) setIsEnabled:(BOOL)enabled
573{
574 [super setIsEnabled:enabled];
575
576 if( enabled ) {
577 [normalImage_ setVisible:YES];
578 [selectedImage_ setVisible:NO];
579 [disabledImage_ setVisible:NO];
580
581 } else {
582 if( disabledImage_ ) {
583 [normalImage_ setVisible:NO];
584 [selectedImage_ setVisible:NO];
585 [disabledImage_ setVisible:YES];
586 } else {
587 [normalImage_ setVisible:YES];
588 [selectedImage_ setVisible:NO];
589 [disabledImage_ setVisible:NO];
590 }
591 }
592}
593
594@end
595
596#pragma mark -
597#pragma mark CCMenuItemImage
598
599@implementation CCMenuItemImage
600
601+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2
602{
603 return [self itemFromNormalImage:value selectedImage:value2 disabledImage: nil target:nil selector:nil];
604}
605
606+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) t selector:(SEL) s
607{
608 return [self itemFromNormalImage:value selectedImage:value2 disabledImage: nil target:t selector:s];
609}
610
611+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3
612{
613 return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:nil selector:nil] autorelease];
614}
615
616+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3 target:(id) t selector:(SEL) s
617{
618 return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:t selector:s] autorelease];
619}
620
621-(id) initFromNormalImage: (NSString*) normalI selectedImage:(NSString*)selectedI disabledImage: (NSString*) disabledI target:(id)t selector:(SEL)sel
622{
623 CCNode<CCRGBAProtocol> *normalImage = [CCSprite spriteWithFile:normalI];
624 CCNode<CCRGBAProtocol> *selectedImage = nil;
625 CCNode<CCRGBAProtocol> *disabledImage = nil;
626
627 if( selectedI )
628 selectedImage = [CCSprite spriteWithFile:selectedI];
629 if(disabledI)
630 disabledImage = [CCSprite spriteWithFile:disabledI];
631
632 return [self initFromNormalSprite:normalImage selectedSprite:selectedImage disabledSprite:disabledImage target:t selector:sel];
633}
634
635#if NS_BLOCKS_AVAILABLE
636
637+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block {
638 return [self itemFromNormalImage:value selectedImage:value2 disabledImage:nil block:block];
639}
640
641+(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block {
642 return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 block:block] autorelease];
643}
644
645-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block {
646 block_ = [block copy];
647 return [self initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:block_ selector:@selector(ccCallbackBlockWithSender:)];
648}
649
650#endif // NS_BLOCKS_AVAILABLE
651
652@end
653
654#pragma mark -
655#pragma mark CCMenuItemToggle
656
657//
658// MenuItemToggle
659//
660@implementation CCMenuItemToggle
661
662@synthesize subItems = subItems_;
663@synthesize opacity = opacity_, color = color_;
664
665+(id) itemWithTarget: (id)t selector: (SEL)sel items: (CCMenuItem*) item, ...
666{
667 va_list args;
668 va_start(args, item);
669
670 id s = [[[self alloc] initWithTarget: t selector:sel items: item vaList:args] autorelease];
671
672 va_end(args);
673 return s;
674}
675
676-(id) initWithTarget: (id)t selector: (SEL)sel items:(CCMenuItem*) item vaList: (va_list) args
677{
678 if( (self=[super initWithTarget:t selector:sel]) ) {
679
680 self.subItems = [NSMutableArray arrayWithCapacity:2];
681
682 int z = 0;
683 CCMenuItem *i = item;
684 while(i) {
685 z++;
686 [subItems_ addObject:i];
687 i = va_arg(args, CCMenuItem*);
688 }
689
690 selectedIndex_ = NSUIntegerMax;
691 [self setSelectedIndex:0];
692 }
693
694 return self;
695}
696
697#if NS_BLOCKS_AVAILABLE
698
699+(id) itemWithBlock:(void(^)(id sender))block items:(CCMenuItem*)item, ... {
700 va_list args;
701 va_start(args, item);
702
703 id s = [[[self alloc] initWithBlock:block items:item vaList:args] autorelease];
704
705 va_end(args);
706 return s;
707}
708
709-(id) initWithBlock:(void (^)(id))block items:(CCMenuItem*)item vaList:(va_list)args {
710 block_ = [block copy];
711 return [self initWithTarget:block_ selector:@selector(ccCallbackBlockWithSender:) items:item vaList:args];
712}
713
714#endif // NS_BLOCKS_AVAILABLE
715
716-(void) dealloc
717{
718 [subItems_ release];
719 [super dealloc];
720}
721
722-(void)setSelectedIndex:(NSUInteger)index
723{
724 if( index != selectedIndex_ ) {
725 selectedIndex_=index;
726 [self removeChildByTag:kCurrentItem cleanup:NO];
727
728 CCMenuItem *item = [subItems_ objectAtIndex:selectedIndex_];
729 [self addChild:item z:0 tag:kCurrentItem];
730
731 CGSize s = [item contentSize];
732 [self setContentSize: s];
733 item.position = ccp( s.width/2, s.height/2 );
734 }
735}
736
737-(NSUInteger) selectedIndex
738{
739 return selectedIndex_;
740}
741
742
743-(void) selected
744{
745 [super selected];
746 [[subItems_ objectAtIndex:selectedIndex_] selected];
747}
748
749-(void) unselected
750{
751 [super unselected];
752 [[subItems_ objectAtIndex:selectedIndex_] unselected];
753}
754
755-(void) activate
756{
757 // update index
758 if( isEnabled_ ) {
759 NSUInteger newIndex = (selectedIndex_ + 1) % [subItems_ count];
760 [self setSelectedIndex:newIndex];
761
762 }
763
764 [super activate];
765}
766
767-(void) setIsEnabled: (BOOL)enabled
768{
769 [super setIsEnabled:enabled];
770 for(CCMenuItem* item in subItems_)
771 [item setIsEnabled:enabled];
772}
773
774-(CCMenuItem*) selectedItem
775{
776 return [subItems_ objectAtIndex:selectedIndex_];
777}
778
779#pragma mark CCMenuItemToggle - CCRGBAProtocol protocol
780
781- (void) setOpacity: (GLubyte)opacity
782{
783 opacity_ = opacity;
784 for(CCMenuItem<CCRGBAProtocol>* item in subItems_)
785 [item setOpacity:opacity];
786}
787
788- (void) setColor:(ccColor3B)color
789{
790 color_ = color;
791 for(CCMenuItem<CCRGBAProtocol>* item in subItems_)
792 [item setColor:color];
793}
794
795@end
diff --git a/libs/cocos2d/CCMotionStreak.h b/libs/cocos2d/CCMotionStreak.h new file mode 100755 index 0000000..e017124 --- /dev/null +++ b/libs/cocos2d/CCMotionStreak.h
@@ -0,0 +1,67 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008, 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Foundation/Foundation.h>
27#import "CCNode.h"
28#import "CCRibbon.h"
29
30/**
31 * CCMotionStreak manages a Ribbon based on it's motion in absolute space.
32 * You construct it with a fadeTime, minimum segment size, texture path, texture
33 * length and color. The fadeTime controls how long it takes each vertex in
34 * the streak to fade out, the minimum segment size it how many pixels the
35 * streak will move before adding a new ribbon segement, and the texture
36 * length is the how many pixels the texture is stretched across. The texture
37 * is vertically aligned along the streak segemnts.
38 *
39 * Limitations:
40 * CCMotionStreak, by default, will use the GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA blending function.
41 * This blending function might not be the correct one for certain textures.
42 * But you can change it by using:
43 * [obj setBlendFunc: (ccBlendfunc) {new_src_blend_func, new_dst_blend_func}];
44 *
45 * @since v0.8.1
46 */
47@interface CCMotionStreak : CCNode <CCTextureProtocol>
48{
49 CCRibbon* ribbon_;
50 float segThreshold_;
51 float width_;
52 CGPoint lastLocation_;
53}
54
55/** Ribbon used by MotionStreak (weak reference) */
56@property (nonatomic,readonly) CCRibbon *ribbon;
57
58/** creates the a MotionStreak. The image will be loaded using the TextureMgr. */
59+(id)streakWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color;
60
61/** initializes a MotionStreak. The file will be loaded using the TextureMgr. */
62-(id)initWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color;
63
64/** polling function */
65-(void)update:(ccTime)delta;
66
67@end
diff --git a/libs/cocos2d/CCMotionStreak.m b/libs/cocos2d/CCMotionStreak.m new file mode 100755 index 0000000..42737b9 --- /dev/null +++ b/libs/cocos2d/CCMotionStreak.m
@@ -0,0 +1,104 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008, 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 *
25 *********************************************************
26 *
27 * Motion Streak manages a Ribbon based on it's motion in absolute space.
28 * You construct it with a fadeTime, minimum segment size, texture path, texture
29 * length and color. The fadeTime controls how long it takes each vertex in
30 * the streak to fade out, the minimum segment size it how many pixels the
31 * streak will move before adding a new ribbon segement, and the texture
32 * length is the how many pixels the texture is stretched across. The texture
33 * is vertically aligned along the streak segemnts.
34 */
35
36#import "CCMotionStreak.h"
37#import "Support/CGPointExtension.h"
38
39@implementation CCMotionStreak
40
41@synthesize ribbon = ribbon_;
42
43+(id)streakWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color
44{
45 return [[[self alloc] initWithFade:(float)fade minSeg:seg image:path width:width length:length color:color] autorelease];
46}
47
48-(id)initWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color
49{
50 if( (self=[super init])) {
51 segThreshold_ = seg;
52 width_ = width;
53 lastLocation_ = CGPointZero;
54 ribbon_ = [CCRibbon ribbonWithWidth:width_ image:path length:length color:color fade:fade];
55 [self addChild:ribbon_];
56
57 // update ribbon position. Use schedule:interval and not scheduleUpdated. issue #1075
58 [self schedule:@selector(update:) interval:0];
59 }
60 return self;
61}
62
63-(void)update:(ccTime)delta
64{
65 CGPoint location = [self convertToWorldSpace:CGPointZero];
66 [ribbon_ setPosition:ccp(-1*location.x, -1*location.y)];
67 float len = ccpLength(ccpSub(lastLocation_, location));
68 if (len > segThreshold_)
69 {
70 [ribbon_ addPointAt:location width:width_];
71 lastLocation_ = location;
72 }
73 [ribbon_ update:delta];
74}
75
76
77-(void)dealloc
78{
79 [super dealloc];
80}
81
82#pragma mark MotionStreak - CocosNodeTexture protocol
83
84-(void) setTexture:(CCTexture2D*) texture
85{
86 [ribbon_ setTexture: texture];
87}
88
89-(CCTexture2D*) texture
90{
91 return [ribbon_ texture];
92}
93
94-(ccBlendFunc) blendFunc
95{
96 return [ribbon_ blendFunc];
97}
98
99-(void) setBlendFunc:(ccBlendFunc)blendFunc
100{
101 [ribbon_ setBlendFunc:blendFunc];
102}
103
104@end
diff --git a/libs/cocos2d/CCNode.h b/libs/cocos2d/CCNode.h new file mode 100755 index 0000000..64acdc5 --- /dev/null +++ b/libs/cocos2d/CCNode.h
@@ -0,0 +1,529 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#import <Availability.h>
29
30#import "Platforms/CCGL.h"
31#import "CCAction.h"
32#import "ccTypes.h"
33#import "CCTexture2D.h"
34#import "CCProtocols.h"
35#import "ccConfig.h"
36#import "Support/CCArray.h"
37
38enum {
39 kCCNodeTagInvalid = -1,
40};
41
42@class CCCamera;
43@class CCGridBase;
44
45/** CCNode is the main element. Anything thats gets drawn or contains things that get drawn is a CCNode.
46 The most popular CCNodes are: CCScene, CCLayer, CCSprite, CCMenu.
47
48 The main features of a CCNode are:
49 - They can contain other CCNode nodes (addChild, getChildByTag, removeChild, etc)
50 - They can schedule periodic callback (schedule, unschedule, etc)
51 - They can execute actions (runAction, stopAction, etc)
52
53 Some CCNode nodes provide extra functionality for them or their children.
54
55 Subclassing a CCNode usually means (one/all) of:
56 - overriding init to initialize resources and schedule callbacks
57 - create callbacks to handle the advancement of time
58 - overriding draw to render the node
59
60 Features of CCNode:
61 - position
62 - scale (x, y)
63 - rotation (in degrees, clockwise)
64 - CCCamera (an interface to gluLookAt )
65 - CCGridBase (to do mesh transformations)
66 - anchor point
67 - size
68 - visible
69 - z-order
70 - openGL z position
71
72 Default values:
73 - rotation: 0
74 - position: (x=0,y=0)
75 - scale: (x=1,y=1)
76 - contentSize: (x=0,y=0)
77 - anchorPoint: (x=0,y=0)
78
79 Limitations:
80 - A CCNode is a "void" object. It doesn't have a texture
81
82 Order in transformations with grid disabled
83 -# The node will be translated (position)
84 -# The node will be rotated (rotation)
85 -# The node will be scaled (scale)
86 -# The node will be moved according to the camera values (camera)
87
88 Order in transformations with grid enabled
89 -# The node will be translated (position)
90 -# The node will be rotated (rotation)
91 -# The node will be scaled (scale)
92 -# The grid will capture the screen
93 -# The node will be moved according to the camera values (camera)
94 -# The grid will render the captured screen
95
96 Camera:
97 - Each node has a camera. By default it points to the center of the CCNode.
98 */
99@interface CCNode : NSObject
100{
101 // rotation angle
102 float rotation_;
103
104 // scaling factors
105 float scaleX_, scaleY_;
106
107 // position of the node
108 CGPoint position_;
109 CGPoint positionInPixels_;
110
111 // skew angles
112 float skewX_, skewY_;
113
114 // is visible
115 BOOL visible_;
116
117 // anchor point in pixels
118 CGPoint anchorPointInPixels_;
119 // anchor point normalized
120 CGPoint anchorPoint_;
121 // If YES the transformtions will be relative to (-transform.x, -transform.y).
122 // Sprites, Labels and any other "small" object uses it.
123 // Scenes, Layers and other "whole screen" object don't use it.
124 BOOL isRelativeAnchorPoint_;
125
126 // untransformed size of the node
127 CGSize contentSize_;
128 CGSize contentSizeInPixels_;
129
130 // transform
131 CGAffineTransform transform_, inverse_;
132#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
133 GLfloat transformGL_[16];
134#endif
135
136 // openGL real Z vertex
137 float vertexZ_;
138
139 // a Camera
140 CCCamera *camera_;
141
142 // a Grid
143 CCGridBase *grid_;
144
145 // z-order value
146 NSInteger zOrder_;
147
148 // array of children
149 CCArray *children_;
150
151 // weakref to parent
152 CCNode *parent_;
153
154 // a tag. any number you want to assign to the node
155 NSInteger tag_;
156
157 // user data field
158 void *userData_;
159
160 // Is running
161 BOOL isRunning_;
162
163 // To reduce memory, place BOOLs that are not properties here:
164 BOOL isTransformDirty_:1;
165 BOOL isInverseDirty_:1;
166#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
167 BOOL isTransformGLDirty_:1;
168#endif
169}
170
171/** The z order of the node relative to it's "brothers": children of the same parent */
172@property(nonatomic,readonly) NSInteger zOrder;
173/** The real openGL Z vertex.
174 Differences between openGL Z vertex and cocos2d Z order:
175 - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children
176 - OpenGL Z might require to set 2D projection
177 - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0
178 @warning: Use it at your own risk since it might break the cocos2d parent-children z order
179 @since v0.8
180 */
181@property (nonatomic,readwrite) float vertexZ;
182
183/** The X skew angle of the node in degrees.
184 This angle describes the shear distortion in the X direction.
185 Thus, it is the angle between the Y axis and the left edge of the shape
186 The default skewX angle is 0. Positive values distort the node in a CW direction.
187 */
188@property(nonatomic,readwrite,assign) float skewX;
189
190/** The Y skew angle of the node in degrees.
191 This angle describes the shear distortion in the Y direction.
192 Thus, it is the angle between the X axis and the bottom edge of the shape
193 The default skewY angle is 0. Positive values distort the node in a CCW direction.
194 */
195@property(nonatomic,readwrite,assign) float skewY;
196/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. */
197@property(nonatomic,readwrite,assign) float rotation;
198/** The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. */
199@property(nonatomic,readwrite,assign) float scale;
200/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the X scale factor. */
201@property(nonatomic,readwrite,assign) float scaleX;
202/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the Y scale factor. */
203@property(nonatomic,readwrite,assign) float scaleY;
204/** Position (x,y) of the node in points. (0,0) is the left-bottom corner. */
205@property(nonatomic,readwrite,assign) CGPoint position;
206/** Position (x,y) of the node in points. (0,0) is the left-bottom corner. */
207@property(nonatomic,readwrite,assign) CGPoint positionInPixels;
208/** A CCCamera object that lets you move the node using a gluLookAt
209*/
210@property(nonatomic,readonly) CCCamera* camera;
211/** Array of children */
212@property(nonatomic,readonly) CCArray *children;
213/** A CCGrid object that is used when applying effects */
214@property(nonatomic,readwrite,retain) CCGridBase* grid;
215/** Whether of not the node is visible. Default is YES */
216@property(nonatomic,readwrite,assign) BOOL visible;
217/** anchorPoint is the point around which all transformations and positioning manipulations take place.
218 It's like a pin in the node where it is "attached" to its parent.
219 The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
220 But you can use values higher than (1,1) and lower than (0,0) too.
221 The default anchorPoint is (0,0). It starts in the bottom-left corner. CCSprite and other subclasses have a different default anchorPoint.
222 @since v0.8
223 */
224@property(nonatomic,readwrite) CGPoint anchorPoint;
225/** The anchorPoint in absolute pixels.
226 Since v0.8 you can only read it. If you wish to modify it, use anchorPoint instead
227 */
228@property(nonatomic,readonly) CGPoint anchorPointInPixels;
229
230/** The untransformed size of the node in Points
231 The contentSize remains the same no matter the node is scaled or rotated.
232 All nodes has a size. Layer and Scene has the same size of the screen.
233 @since v0.8
234 */
235@property (nonatomic,readwrite) CGSize contentSize;
236
237/** The untransformed size of the node in Pixels
238 The contentSize remains the same no matter the node is scaled or rotated.
239 All nodes has a size. Layer and Scene has the same size of the screen.
240 @since v0.8
241 */
242@property (nonatomic,readwrite) CGSize contentSizeInPixels;
243
244/** whether or not the node is running */
245@property(nonatomic,readonly) BOOL isRunning;
246/** A weak reference to the parent */
247@property(nonatomic,readwrite,assign) CCNode* parent;
248/** If YES the transformtions will be relative to it's anchor point.
249 * Sprites, Labels and any other sizeble object use it have it enabled by default.
250 * Scenes, Layers and other "whole screen" object don't use it, have it disabled by default.
251 */
252@property(nonatomic,readwrite,assign) BOOL isRelativeAnchorPoint;
253/** A tag used to identify the node easily */
254@property(nonatomic,readwrite,assign) NSInteger tag;
255/** A custom user data pointer */
256@property(nonatomic,readwrite,assign) void *userData;
257
258// initializators
259/** allocates and initializes a node.
260 The node will be created as "autorelease".
261 */
262+(id) node;
263/** initializes the node */
264-(id) init;
265
266
267// scene managment
268
269/** callback that is called every time the CCNode enters the 'stage'.
270 If the CCNode enters the 'stage' with a transition, this callback is called when the transition starts.
271 During onEnter you can't a "sister/brother" node.
272 */
273-(void) onEnter;
274/** callback that is called when the CCNode enters in the 'stage'.
275 If the CCNode enters the 'stage' with a transition, this callback is called when the transition finishes.
276 @since v0.8
277 */
278-(void) onEnterTransitionDidFinish;
279/** callback that is called every time the CCNode leaves the 'stage'.
280 If the CCNode leaves the 'stage' with a transition, this callback is called when the transition finishes.
281 During onExit you can't access a sibling node.
282 */
283-(void) onExit;
284
285
286// composition: ADD
287
288/** Adds a child to the container with z-order as 0.
289 If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.
290 @since v0.7.1
291 */
292-(void) addChild: (CCNode*)node;
293
294/** Adds a child to the container with a z-order.
295 If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.
296 @since v0.7.1
297 */
298-(void) addChild: (CCNode*)node z:(NSInteger)z;
299
300/** Adds a child to the container with z order and tag.
301 If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.
302 @since v0.7.1
303 */
304-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag;
305
306// composition: REMOVE
307
308/** Remove itself from its parent node. If cleanup is YES, then also remove all actions and callbacks.
309 If the node orphan, then nothing happens.
310 @since v0.99.3
311 */
312-(void) removeFromParentAndCleanup:(BOOL)cleanup;
313
314/** Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter.
315 @since v0.7.1
316 */
317-(void) removeChild: (CCNode*)node cleanup:(BOOL)cleanup;
318
319/** Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter
320 @since v0.7.1
321 */
322-(void) removeChildByTag:(NSInteger) tag cleanup:(BOOL)cleanup;
323
324/** Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
325 @since v0.7.1
326 */
327-(void) removeAllChildrenWithCleanup:(BOOL)cleanup;
328
329// composition: GET
330/** Gets a child from the container given its tag
331 @return returns a CCNode object
332 @since v0.7.1
333 */
334-(CCNode*) getChildByTag:(NSInteger) tag;
335
336/** Reorders a child according to a new z value.
337 * The child MUST be already added.
338 */
339-(void) reorderChild:(CCNode*)child z:(NSInteger)zOrder;
340
341/** Stops all running actions and schedulers
342 @since v0.8
343 */
344-(void) cleanup;
345
346// draw
347
348/** Override this method to draw your own node.
349 The following GL states will be enabled by default:
350 - glEnableClientState(GL_VERTEX_ARRAY);
351 - glEnableClientState(GL_COLOR_ARRAY);
352 - glEnableClientState(GL_TEXTURE_COORD_ARRAY);
353 - glEnable(GL_TEXTURE_2D);
354
355 AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE
356
357 But if you enable any other GL state, you should disable it after drawing your node.
358 */
359-(void) draw;
360/** recursive method that visit its children and draw them */
361-(void) visit;
362
363// transformations
364
365/** performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes. */
366-(void) transform;
367
368/** performs OpenGL view-matrix transformation of it's ancestors.
369 Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO)
370 it's necessary to transform the ancestors again.
371 @since v0.7.2
372 */
373-(void) transformAncestors;
374
375/** returns a "local" axis aligned bounding box of the node in points.
376 The returned box is relative only to its parent.
377 The returned box is in Points.
378
379 @since v0.8.2
380 */
381- (CGRect) boundingBox;
382
383/** returns a "local" axis aligned bounding box of the node in pixels.
384 The returned box is relative only to its parent.
385 The returned box is in Points.
386
387 @since v0.99.5
388 */
389- (CGRect) boundingBoxInPixels;
390
391
392// actions
393
394/** Executes an action, and returns the action that is executed.
395 The node becomes the action's target.
396 @warning Starting from v0.8 actions don't retain their target anymore.
397 @since v0.7.1
398 @return An Action pointer
399 */
400-(CCAction*) runAction: (CCAction*) action;
401/** Removes all actions from the running action list */
402-(void) stopAllActions;
403/** Removes an action from the running action list */
404-(void) stopAction: (CCAction*) action;
405/** Removes an action from the running action list given its tag
406 @since v0.7.1
407*/
408-(void) stopActionByTag:(NSInteger) tag;
409/** Gets an action from the running action list given its tag
410 @since v0.7.1
411 @return the Action the with the given tag
412 */
413-(CCAction*) getActionByTag:(NSInteger) tag;
414/** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).
415 * Composable actions are counted as 1 action. Example:
416 * If you are running 1 Sequence of 7 actions, it will return 1.
417 * If you are running 7 Sequences of 2 actions, it will return 7.
418 */
419-(NSUInteger) numberOfRunningActions;
420
421// timers
422
423/** check whether a selector is scheduled. */
424//-(BOOL) isScheduled: (SEL) selector;
425
426/** schedules the "update" method. It will use the order number 0. This method will be called every frame.
427 Scheduled methods with a lower order value will be called before the ones that have a higher order value.
428 Only one "udpate" method could be scheduled per node.
429
430 @since v0.99.3
431 */
432-(void) scheduleUpdate;
433
434/** schedules the "update" selector with a custom priority. This selector will be called every frame.
435 Scheduled selectors with a lower priority will be called before the ones that have a higher value.
436 Only one "udpate" selector could be scheduled per node (You can't have 2 'update' selectors).
437
438 @since v0.99.3
439 */
440-(void) scheduleUpdateWithPriority:(NSInteger)priority;
441
442/* unschedules the "update" method.
443
444 @since v0.99.3
445 */
446-(void) unscheduleUpdate;
447
448
449/** schedules a selector.
450 The scheduled selector will be ticked every frame
451 */
452-(void) schedule: (SEL) s;
453/** schedules a custom selector with an interval time in seconds.
454 If time is 0 it will be ticked every frame.
455 If time is 0, it is recommended to use 'scheduleUpdate' instead.
456
457 If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.
458 */
459-(void) schedule: (SEL) s interval:(ccTime)seconds;
460/** unschedules a custom selector.*/
461-(void) unschedule: (SEL) s;
462
463/** unschedule all scheduled selectors: custom selectors, and the 'update' selector.
464 Actions are not affected by this method.
465@since v0.99.3
466 */
467-(void) unscheduleAllSelectors;
468
469/** resumes all scheduled selectors and actions.
470 Called internally by onEnter
471 */
472-(void) resumeSchedulerAndActions;
473/** pauses all scheduled selectors and actions.
474 Called internally by onExit
475 */
476-(void) pauseSchedulerAndActions;
477
478
479// transformation methods
480
481/** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
482 The matrix is in Pixels.
483 @since v0.7.1
484 */
485- (CGAffineTransform)nodeToParentTransform;
486/** Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.
487 The matrix is in Pixels.
488 @since v0.7.1
489 */
490- (CGAffineTransform)parentToNodeTransform;
491/** Retrusn the world affine transform matrix. The matrix is in Pixels.
492 @since v0.7.1
493 */
494- (CGAffineTransform)nodeToWorldTransform;
495/** Returns the inverse world affine transform matrix. The matrix is in Pixels.
496 @since v0.7.1
497 */
498- (CGAffineTransform)worldToNodeTransform;
499/** Converts a Point to node (local) space coordinates. The result is in Points.
500 @since v0.7.1
501 */
502- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint;
503/** Converts a Point to world space coordinates. The result is in Points.
504 @since v0.7.1
505 */
506- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint;
507/** Converts a Point to node (local) space coordinates. The result is in Points.
508 treating the returned/received node point as anchor relative.
509 @since v0.7.1
510 */
511- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint;
512/** Converts a local Point to world space coordinates.The result is in Points.
513 treating the returned/received node point as anchor relative.
514 @since v0.7.1
515 */
516- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint;
517
518#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
519/** Converts a UITouch to node (local) space coordinates. The result is in Points.
520 @since v0.7.1
521 */
522- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch;
523/** Converts a UITouch to node (local) space coordinates. The result is in Points.
524 This method is AR (Anchor Relative)..
525 @since v0.7.1
526 */
527- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch;
528#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
529@end
diff --git a/libs/cocos2d/CCNode.m b/libs/cocos2d/CCNode.m new file mode 100755 index 0000000..569cb22 --- /dev/null +++ b/libs/cocos2d/CCNode.m
@@ -0,0 +1,921 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#import "CCNode.h"
29#import "CCGrid.h"
30#import "CCDirector.h"
31#import "CCActionManager.h"
32#import "CCCamera.h"
33#import "CCScheduler.h"
34#import "ccConfig.h"
35#import "ccMacros.h"
36#import "Support/CGPointExtension.h"
37#import "Support/ccCArray.h"
38#import "Support/TransformUtils.h"
39#import "ccMacros.h"
40
41#import <Availability.h>
42#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
43#import "Platforms/iOS/CCDirectorIOS.h"
44#endif
45
46
47#if CC_COCOSNODE_RENDER_SUBPIXEL
48#define RENDER_IN_SUBPIXEL
49#else
50#define RENDER_IN_SUBPIXEL (NSInteger)
51#endif
52
53@interface CCNode ()
54// lazy allocs
55-(void) childrenAlloc;
56// helper that reorder a child
57-(void) insertChild:(CCNode*)child z:(NSInteger)z;
58// used internally to alter the zOrder variable. DON'T call this method manually
59-(void) _setZOrder:(NSInteger) z;
60-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup;
61@end
62
63@implementation CCNode
64
65@synthesize children = children_;
66@synthesize visible = visible_;
67@synthesize parent = parent_;
68@synthesize grid = grid_;
69@synthesize zOrder = zOrder_;
70@synthesize tag = tag_;
71@synthesize vertexZ = vertexZ_;
72@synthesize isRunning = isRunning_;
73@synthesize userData = userData_;
74
75#pragma mark CCNode - Transform related properties
76
77@synthesize rotation = rotation_, scaleX = scaleX_, scaleY = scaleY_;
78@synthesize skewX = skewX_, skewY = skewY_;
79@synthesize position = position_, positionInPixels = positionInPixels_;
80@synthesize anchorPoint = anchorPoint_, anchorPointInPixels = anchorPointInPixels_;
81@synthesize contentSize = contentSize_, contentSizeInPixels = contentSizeInPixels_;
82@synthesize isRelativeAnchorPoint = isRelativeAnchorPoint_;
83
84// getters synthesized, setters explicit
85
86-(void) setSkewX:(float)newSkewX
87{
88 skewX_ = newSkewX;
89 isTransformDirty_ = isInverseDirty_ = YES;
90#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
91 isTransformGLDirty_ = YES;
92#endif
93}
94
95-(void) setSkewY:(float)newSkewY
96{
97 skewY_ = newSkewY;
98 isTransformDirty_ = isInverseDirty_ = YES;
99#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
100 isTransformGLDirty_ = YES;
101#endif
102}
103
104-(void) setRotation: (float)newRotation
105{
106 rotation_ = newRotation;
107 isTransformDirty_ = isInverseDirty_ = YES;
108#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
109 isTransformGLDirty_ = YES;
110#endif
111}
112
113-(void) setScaleX: (float)newScaleX
114{
115 scaleX_ = newScaleX;
116 isTransformDirty_ = isInverseDirty_ = YES;
117#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
118 isTransformGLDirty_ = YES;
119#endif
120}
121
122-(void) setScaleY: (float)newScaleY
123{
124 scaleY_ = newScaleY;
125 isTransformDirty_ = isInverseDirty_ = YES;
126#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
127 isTransformGLDirty_ = YES;
128#endif
129}
130
131-(void) setPosition: (CGPoint)newPosition
132{
133 position_ = newPosition;
134 if( CC_CONTENT_SCALE_FACTOR() == 1 )
135 positionInPixels_ = position_;
136 else
137 positionInPixels_ = ccpMult( newPosition, CC_CONTENT_SCALE_FACTOR() );
138
139 isTransformDirty_ = isInverseDirty_ = YES;
140#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
141 isTransformGLDirty_ = YES;
142#endif
143}
144
145-(void) setPositionInPixels:(CGPoint)newPosition
146{
147 positionInPixels_ = newPosition;
148
149 if( CC_CONTENT_SCALE_FACTOR() == 1 )
150 position_ = positionInPixels_;
151 else
152 position_ = ccpMult( newPosition, 1/CC_CONTENT_SCALE_FACTOR() );
153
154 isTransformDirty_ = isInverseDirty_ = YES;
155#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
156 isTransformGLDirty_ = YES;
157#endif
158}
159
160-(void) setIsRelativeAnchorPoint: (BOOL)newValue
161{
162 isRelativeAnchorPoint_ = newValue;
163 isTransformDirty_ = isInverseDirty_ = YES;
164#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
165 isTransformGLDirty_ = YES;
166#endif
167}
168
169-(void) setAnchorPoint:(CGPoint)point
170{
171 if( ! CGPointEqualToPoint(point, anchorPoint_) ) {
172 anchorPoint_ = point;
173 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
174 isTransformDirty_ = isInverseDirty_ = YES;
175#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
176 isTransformGLDirty_ = YES;
177#endif
178 }
179}
180
181-(void) setContentSize:(CGSize)size
182{
183 if( ! CGSizeEqualToSize(size, contentSize_) ) {
184 contentSize_ = size;
185
186 if( CC_CONTENT_SCALE_FACTOR() == 1 )
187 contentSizeInPixels_ = contentSize_;
188 else
189 contentSizeInPixels_ = CGSizeMake( size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
190
191 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
192 isTransformDirty_ = isInverseDirty_ = YES;
193#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
194 isTransformGLDirty_ = YES;
195#endif
196 }
197}
198
199-(void) setContentSizeInPixels:(CGSize)size
200{
201 if( ! CGSizeEqualToSize(size, contentSizeInPixels_) ) {
202 contentSizeInPixels_ = size;
203
204 if( CC_CONTENT_SCALE_FACTOR() == 1 )
205 contentSize_ = contentSizeInPixels_;
206 else
207 contentSize_ = CGSizeMake( size.width / CC_CONTENT_SCALE_FACTOR(), size.height / CC_CONTENT_SCALE_FACTOR() );
208
209 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
210 isTransformDirty_ = isInverseDirty_ = YES;
211#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
212 isTransformGLDirty_ = YES;
213#endif
214 }
215}
216
217- (CGRect) boundingBox
218{
219 CGRect ret = [self boundingBoxInPixels];
220 return CC_RECT_PIXELS_TO_POINTS( ret );
221}
222
223- (CGRect) boundingBoxInPixels
224{
225 CGRect rect = CGRectMake(0, 0, contentSizeInPixels_.width, contentSizeInPixels_.height);
226 return CGRectApplyAffineTransform(rect, [self nodeToParentTransform]);
227}
228
229-(void) setVertexZ:(float)vertexZ
230{
231 vertexZ_ = vertexZ * CC_CONTENT_SCALE_FACTOR();
232}
233
234-(float) scale
235{
236 NSAssert( scaleX_ == scaleY_, @"CCNode#scale. ScaleX != ScaleY. Don't know which one to return");
237 return scaleX_;
238}
239
240-(void) setScale:(float) s
241{
242 scaleX_ = scaleY_ = s;
243 isTransformDirty_ = isInverseDirty_ = YES;
244#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
245 isTransformGLDirty_ = YES;
246#endif
247}
248
249#pragma mark CCNode - Init & cleanup
250
251+(id) node
252{
253 return [[[self alloc] init] autorelease];
254}
255
256-(id) init
257{
258 if ((self=[super init]) ) {
259
260 isRunning_ = NO;
261
262 skewX_ = skewY_ = 0.0f;
263 rotation_ = 0.0f;
264 scaleX_ = scaleY_ = 1.0f;
265 positionInPixels_ = position_ = CGPointZero;
266 anchorPointInPixels_ = anchorPoint_ = CGPointZero;
267 contentSizeInPixels_ = contentSize_ = CGSizeZero;
268
269
270 // "whole screen" objects. like Scenes and Layers, should set isRelativeAnchorPoint to NO
271 isRelativeAnchorPoint_ = YES;
272
273 isTransformDirty_ = isInverseDirty_ = YES;
274#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
275 isTransformGLDirty_ = YES;
276#endif
277
278 vertexZ_ = 0;
279
280 grid_ = nil;
281
282 visible_ = YES;
283
284 tag_ = kCCNodeTagInvalid;
285
286 zOrder_ = 0;
287
288 // lazy alloc
289 camera_ = nil;
290
291 // children (lazy allocs)
292 children_ = nil;
293
294 // userData is always inited as nil
295 userData_ = nil;
296
297 //initialize parent to nil
298 parent_ = nil;
299 }
300
301 return self;
302}
303
304- (void)cleanup
305{
306 // actions
307 [self stopAllActions];
308 [self unscheduleAllSelectors];
309
310 // timers
311 [children_ makeObjectsPerformSelector:@selector(cleanup)];
312}
313
314- (NSString*) description
315{
316 return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_];
317}
318
319- (void) dealloc
320{
321 CCLOGINFO( @"cocos2d: deallocing %@", self);
322
323 // attributes
324 [camera_ release];
325
326 [grid_ release];
327
328 // children
329 CCNode *child;
330 CCARRAY_FOREACH(children_, child)
331 child.parent = nil;
332
333 [children_ release];
334
335 [super dealloc];
336}
337
338#pragma mark CCNode Composition
339
340-(void) childrenAlloc
341{
342 children_ = [[CCArray alloc] initWithCapacity:4];
343}
344
345// camera: lazy alloc
346-(CCCamera*) camera
347{
348 if( ! camera_ ) {
349 camera_ = [[CCCamera alloc] init];
350
351 // by default, center camera at the Sprite's anchor point
352 // [camera_ setCenterX:anchorPointInPixels_.x centerY:anchorPointInPixels_.y centerZ:0];
353 // [camera_ setEyeX:anchorPointInPixels_.x eyeY:anchorPointInPixels_.y eyeZ:1];
354
355 // [camera_ setCenterX:0 centerY:0 centerZ:0];
356 // [camera_ setEyeX:0 eyeY:0 eyeZ:1];
357
358 }
359
360 return camera_;
361}
362
363-(CCNode*) getChildByTag:(NSInteger) aTag
364{
365 NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag");
366
367 CCNode *node;
368 CCARRAY_FOREACH(children_, node){
369 if( node.tag == aTag )
370 return node;
371 }
372 // not found
373 return nil;
374}
375
376/* "add" logic MUST only be on this method
377 * If a class want's to extend the 'addChild' behaviour it only needs
378 * to override this method
379 */
380-(void) addChild: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag
381{
382 NSAssert( child != nil, @"Argument must be non-nil");
383 NSAssert( child.parent == nil, @"child already added. It can't be added again");
384
385 if( ! children_ )
386 [self childrenAlloc];
387
388 [self insertChild:child z:z];
389
390 child.tag = aTag;
391
392 [child setParent: self];
393
394 if( isRunning_ ) {
395 [child onEnter];
396 [child onEnterTransitionDidFinish];
397 }
398}
399
400-(void) addChild: (CCNode*) child z:(NSInteger)z
401{
402 NSAssert( child != nil, @"Argument must be non-nil");
403 [self addChild:child z:z tag:child.tag];
404}
405
406-(void) addChild: (CCNode*) child
407{
408 NSAssert( child != nil, @"Argument must be non-nil");
409 [self addChild:child z:child.zOrder tag:child.tag];
410}
411
412-(void) removeFromParentAndCleanup:(BOOL)cleanup
413{
414 [parent_ removeChild:self cleanup:cleanup];
415}
416
417/* "remove" logic MUST only be on this method
418 * If a class want's to extend the 'removeChild' behavior it only needs
419 * to override this method
420 */
421-(void) removeChild: (CCNode*)child cleanup:(BOOL)cleanup
422{
423 // explicit nil handling
424 if (child == nil)
425 return;
426
427 if ( [children_ containsObject:child] )
428 [self detachChild:child cleanup:cleanup];
429}
430
431-(void) removeChildByTag:(NSInteger)aTag cleanup:(BOOL)cleanup
432{
433 NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag");
434
435 CCNode *child = [self getChildByTag:aTag];
436
437 if (child == nil)
438 CCLOG(@"cocos2d: removeChildByTag: child not found!");
439 else
440 [self removeChild:child cleanup:cleanup];
441}
442
443-(void) removeAllChildrenWithCleanup:(BOOL)cleanup
444{
445 // not using detachChild improves speed here
446 CCNode *c;
447 CCARRAY_FOREACH(children_, c)
448 {
449 // IMPORTANT:
450 // -1st do onExit
451 // -2nd cleanup
452 if (isRunning_)
453 [c onExit];
454
455 if (cleanup)
456 [c cleanup];
457
458 // set parent nil at the end (issue #476)
459 [c setParent:nil];
460 }
461
462 [children_ removeAllObjects];
463}
464
465-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup
466{
467 // IMPORTANT:
468 // -1st do onExit
469 // -2nd cleanup
470 if (isRunning_)
471 [child onExit];
472
473 // If you don't do cleanup, the child's actions will not get removed and the
474 // its scheduledSelectors_ dict will not get released!
475 if (doCleanup)
476 [child cleanup];
477
478 // set parent nil at the end (issue #476)
479 [child setParent:nil];
480
481 [children_ removeObject:child];
482}
483
484// used internally to alter the zOrder variable. DON'T call this method manually
485-(void) _setZOrder:(NSInteger) z
486{
487 zOrder_ = z;
488}
489
490// helper used by reorderChild & add
491-(void) insertChild:(CCNode*)child z:(NSInteger)z
492{
493 NSUInteger index=0;
494 CCNode *a = [children_ lastObject];
495
496 // quick comparison to improve performance
497 if (!a || a.zOrder <= z)
498 [children_ addObject:child];
499
500 else
501 {
502 CCARRAY_FOREACH(children_, a) {
503 if ( a.zOrder > z ) {
504 [children_ insertObject:child atIndex:index];
505 break;
506 }
507 index++;
508 }
509 }
510
511 [child _setZOrder:z];
512}
513
514-(void) reorderChild:(CCNode*) child z:(NSInteger)z
515{
516 NSAssert( child != nil, @"Child must be non-nil");
517
518 [child retain];
519 [children_ removeObject:child];
520
521 [self insertChild:child z:z];
522
523 [child release];
524}
525
526#pragma mark CCNode Draw
527
528-(void) draw
529{
530 // override me
531 // Only use this function to draw your staff.
532 // DON'T draw your stuff outside this method
533}
534
535-(void) visit
536{
537 // quick return if not visible
538 if (!visible_)
539 return;
540
541 glPushMatrix();
542
543 if ( grid_ && grid_.active) {
544 [grid_ beforeDraw];
545 [self transformAncestors];
546 }
547
548 [self transform];
549
550 if(children_) {
551 ccArray *arrayData = children_->data;
552 NSUInteger i = 0;
553
554 // draw children zOrder < 0
555 for( ; i < arrayData->num; i++ ) {
556 CCNode *child = arrayData->arr[i];
557 if ( [child zOrder] < 0 )
558 [child visit];
559 else
560 break;
561 }
562
563 // self draw
564 [self draw];
565
566 // draw children zOrder >= 0
567 for( ; i < arrayData->num; i++ ) {
568 CCNode *child = arrayData->arr[i];
569 [child visit];
570 }
571
572 } else
573 [self draw];
574
575 if ( grid_ && grid_.active)
576 [grid_ afterDraw:self];
577
578 glPopMatrix();
579}
580
581#pragma mark CCNode - Transformations
582
583-(void) transformAncestors
584{
585 if( parent_ ) {
586 [parent_ transformAncestors];
587 [parent_ transform];
588 }
589}
590
591-(void) transform
592{
593 // transformations
594
595#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
596 // BEGIN alternative -- using cached transform
597 //
598 if( isTransformGLDirty_ ) {
599 CGAffineTransform t = [self nodeToParentTransform];
600 CGAffineToGL(&t, transformGL_);
601 isTransformGLDirty_ = NO;
602 }
603
604 glMultMatrixf(transformGL_);
605 if( vertexZ_ )
606 glTranslatef(0, 0, vertexZ_);
607
608 // XXX: Expensive calls. Camera should be integrated into the cached affine matrix
609 if ( camera_ && !(grid_ && grid_.active) )
610 {
611 BOOL translate = (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f);
612
613 if( translate )
614 ccglTranslate(RENDER_IN_SUBPIXEL(anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(anchorPointInPixels_.y), 0);
615
616 [camera_ locate];
617
618 if( translate )
619 ccglTranslate(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
620 }
621
622
623 // END alternative
624
625#else
626 // BEGIN original implementation
627 //
628 // translate
629 if ( isRelativeAnchorPoint_ && (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0 ) )
630 glTranslatef( RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
631
632 if (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0)
633 glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x + anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y + anchorPointInPixels_.y), vertexZ_);
634 else if ( positionInPixels_.x !=0 || positionInPixels_.y !=0 || vertexZ_ != 0)
635 glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y), vertexZ_ );
636
637 // rotate
638 if (rotation_ != 0.0f )
639 glRotatef( -rotation_, 0.0f, 0.0f, 1.0f );
640
641 // skew
642 if ( (skewX_ != 0.0f) || (skewY_ != 0.0f) ) {
643 CGAffineTransform skewMatrix = CGAffineTransformMake( 1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f );
644 GLfloat glMatrix[16];
645 CGAffineToGL(&skewMatrix, glMatrix);
646 glMultMatrixf(glMatrix);
647 }
648
649 // scale
650 if (scaleX_ != 1.0f || scaleY_ != 1.0f)
651 glScalef( scaleX_, scaleY_, 1.0f );
652
653 if ( camera_ && !(grid_ && grid_.active) )
654 [camera_ locate];
655
656 // restore and re-position point
657 if (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f)
658 glTranslatef(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
659
660 //
661 // END original implementation
662#endif
663
664}
665
666#pragma mark CCNode SceneManagement
667
668-(void) onEnter
669{
670 [children_ makeObjectsPerformSelector:@selector(onEnter)];
671 [self resumeSchedulerAndActions];
672
673 isRunning_ = YES;
674}
675
676-(void) onEnterTransitionDidFinish
677{
678 [children_ makeObjectsPerformSelector:@selector(onEnterTransitionDidFinish)];
679}
680
681-(void) onExit
682{
683 [self pauseSchedulerAndActions];
684 isRunning_ = NO;
685
686 [children_ makeObjectsPerformSelector:@selector(onExit)];
687}
688
689#pragma mark CCNode Actions
690
691-(CCAction*) runAction:(CCAction*) action
692{
693 NSAssert( action != nil, @"Argument must be non-nil");
694
695 [[CCActionManager sharedManager] addAction:action target:self paused:!isRunning_];
696 return action;
697}
698
699-(void) stopAllActions
700{
701 [[CCActionManager sharedManager] removeAllActionsFromTarget:self];
702}
703
704-(void) stopAction: (CCAction*) action
705{
706 [[CCActionManager sharedManager] removeAction:action];
707}
708
709-(void) stopActionByTag:(NSInteger)aTag
710{
711 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
712 [[CCActionManager sharedManager] removeActionByTag:aTag target:self];
713}
714
715-(CCAction*) getActionByTag:(NSInteger) aTag
716{
717 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
718 return [[CCActionManager sharedManager] getActionByTag:aTag target:self];
719}
720
721-(NSUInteger) numberOfRunningActions
722{
723 return [[CCActionManager sharedManager] numberOfRunningActionsInTarget:self];
724}
725
726#pragma mark CCNode - Scheduler
727
728-(void) scheduleUpdate
729{
730 [self scheduleUpdateWithPriority:0];
731}
732
733-(void) scheduleUpdateWithPriority:(NSInteger)priority
734{
735 [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:priority paused:!isRunning_];
736}
737
738-(void) unscheduleUpdate
739{
740 [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
741}
742
743-(void) schedule:(SEL)selector
744{
745 [self schedule:selector interval:0];
746}
747
748-(void) schedule:(SEL)selector interval:(ccTime)interval
749{
750 NSAssert( selector != nil, @"Argument must be non-nil");
751 NSAssert( interval >=0, @"Arguemnt must be positive");
752
753 [[CCScheduler sharedScheduler] scheduleSelector:selector forTarget:self interval:interval paused:!isRunning_];
754}
755
756-(void) unschedule:(SEL)selector
757{
758 // explicit nil handling
759 if (selector == nil)
760 return;
761
762 [[CCScheduler sharedScheduler] unscheduleSelector:selector forTarget:self];
763}
764
765-(void) unscheduleAllSelectors
766{
767 [[CCScheduler sharedScheduler] unscheduleAllSelectorsForTarget:self];
768}
769- (void) resumeSchedulerAndActions
770{
771 [[CCScheduler sharedScheduler] resumeTarget:self];
772 [[CCActionManager sharedManager] resumeTarget:self];
773}
774
775- (void) pauseSchedulerAndActions
776{
777 [[CCScheduler sharedScheduler] pauseTarget:self];
778 [[CCActionManager sharedManager] pauseTarget:self];
779}
780
781#pragma mark CCNode Transform
782
783- (CGAffineTransform)nodeToParentTransform
784{
785 if ( isTransformDirty_ ) {
786
787 transform_ = CGAffineTransformIdentity;
788
789 if ( !isRelativeAnchorPoint_ && !CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
790 transform_ = CGAffineTransformTranslate(transform_, anchorPointInPixels_.x, anchorPointInPixels_.y);
791
792 if( ! CGPointEqualToPoint(positionInPixels_, CGPointZero) )
793 transform_ = CGAffineTransformTranslate(transform_, positionInPixels_.x, positionInPixels_.y);
794
795 if( rotation_ != 0 )
796 transform_ = CGAffineTransformRotate(transform_, -CC_DEGREES_TO_RADIANS(rotation_));
797
798 if( skewX_ != 0 || skewY_ != 0 ) {
799 // create a skewed coordinate system
800 CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f);
801 // apply the skew to the transform
802 transform_ = CGAffineTransformConcat(skew, transform_);
803 }
804
805 if( ! (scaleX_ == 1 && scaleY_ == 1) )
806 transform_ = CGAffineTransformScale(transform_, scaleX_, scaleY_);
807
808 if( ! CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
809 transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
810
811 isTransformDirty_ = NO;
812 }
813
814 return transform_;
815}
816
817- (CGAffineTransform)parentToNodeTransform
818{
819 if ( isInverseDirty_ ) {
820 inverse_ = CGAffineTransformInvert([self nodeToParentTransform]);
821 isInverseDirty_ = NO;
822 }
823
824 return inverse_;
825}
826
827- (CGAffineTransform)nodeToWorldTransform
828{
829 CGAffineTransform t = [self nodeToParentTransform];
830
831 for (CCNode *p = parent_; p != nil; p = p.parent)
832 t = CGAffineTransformConcat(t, [p nodeToParentTransform]);
833
834 return t;
835}
836
837- (CGAffineTransform)worldToNodeTransform
838{
839 return CGAffineTransformInvert([self nodeToWorldTransform]);
840}
841
842- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint
843{
844 CGPoint ret;
845 if( CC_CONTENT_SCALE_FACTOR() == 1 )
846 ret = CGPointApplyAffineTransform(worldPoint, [self worldToNodeTransform]);
847 else {
848 ret = ccpMult( worldPoint, CC_CONTENT_SCALE_FACTOR() );
849 ret = CGPointApplyAffineTransform(ret, [self worldToNodeTransform]);
850 ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() );
851 }
852
853 return ret;
854}
855
856- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint
857{
858 CGPoint ret;
859 if( CC_CONTENT_SCALE_FACTOR() == 1 )
860 ret = CGPointApplyAffineTransform(nodePoint, [self nodeToWorldTransform]);
861 else {
862 ret = ccpMult( nodePoint, CC_CONTENT_SCALE_FACTOR() );
863 ret = CGPointApplyAffineTransform(ret, [self nodeToWorldTransform]);
864 ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() );
865 }
866
867 return ret;
868}
869
870- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint
871{
872 CGPoint nodePoint = [self convertToNodeSpace:worldPoint];
873 CGPoint anchorInPoints;
874 if( CC_CONTENT_SCALE_FACTOR() == 1 )
875 anchorInPoints = anchorPointInPixels_;
876 else
877 anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() );
878
879 return ccpSub(nodePoint, anchorInPoints);
880}
881
882- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint
883{
884 CGPoint anchorInPoints;
885 if( CC_CONTENT_SCALE_FACTOR() == 1 )
886 anchorInPoints = anchorPointInPixels_;
887 else
888 anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() );
889
890 nodePoint = ccpAdd(nodePoint, anchorInPoints);
891 return [self convertToWorldSpace:nodePoint];
892}
893
894- (CGPoint)convertToWindowSpace:(CGPoint)nodePoint
895{
896 CGPoint worldPoint = [self convertToWorldSpace:nodePoint];
897 return [[CCDirector sharedDirector] convertToUI:worldPoint];
898}
899
900// convenience methods which take a UITouch instead of CGPoint
901
902#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
903
904- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch
905{
906 CGPoint point = [touch locationInView: [touch view]];
907 point = [[CCDirector sharedDirector] convertToGL: point];
908 return [self convertToNodeSpace:point];
909}
910
911- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch
912{
913 CGPoint point = [touch locationInView: [touch view]];
914 point = [[CCDirector sharedDirector] convertToGL: point];
915 return [self convertToNodeSpaceAR:point];
916}
917
918#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
919
920
921@end
diff --git a/libs/cocos2d/CCParallaxNode.h b/libs/cocos2d/CCParallaxNode.h new file mode 100755 index 0000000..5728eb1 --- /dev/null +++ b/libs/cocos2d/CCParallaxNode.h
@@ -0,0 +1,50 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCNode.h"
28#import "Support/ccCArray.h"
29
30/** CCParallaxNode: A node that simulates a parallax scroller
31
32 The children will be moved faster / slower than the parent according the the parallax ratio.
33
34 */
35@interface CCParallaxNode : CCNode
36{
37 ccArray *parallaxArray_;
38 CGPoint lastPosition;
39}
40
41/** array that holds the offset / ratio of the children */
42@property (nonatomic,readwrite) ccArray * parallaxArray;
43
44/** Adds a child to the container with a z-order, a parallax ratio and a position offset
45 It returns self, so you can chain several addChilds.
46 @since v0.8
47 */
48-(void) addChild: (CCNode*)node z:(NSInteger)z parallaxRatio:(CGPoint)c positionOffset:(CGPoint)positionOffset;
49
50@end
diff --git a/libs/cocos2d/CCParallaxNode.m b/libs/cocos2d/CCParallaxNode.m new file mode 100755 index 0000000..9d39cc8 --- /dev/null +++ b/libs/cocos2d/CCParallaxNode.m
@@ -0,0 +1,161 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCParallaxNode.h"
28#import "Support/CGPointExtension.h"
29#import "Support/ccCArray.h"
30
31@interface CGPointObject : NSObject
32{
33 CGPoint ratio_;
34 CGPoint offset_;
35 CCNode *child_; // weak ref
36}
37@property (readwrite) CGPoint ratio;
38@property (readwrite) CGPoint offset;
39@property (readwrite,assign) CCNode *child;
40+(id) pointWithCGPoint:(CGPoint)point offset:(CGPoint)offset;
41-(id) initWithCGPoint:(CGPoint)point offset:(CGPoint)offset;
42@end
43@implementation CGPointObject
44@synthesize ratio = ratio_;
45@synthesize offset = offset_;
46@synthesize child=child_;
47
48+(id) pointWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset
49{
50 return [[[self alloc] initWithCGPoint:ratio offset:offset] autorelease];
51}
52-(id) initWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset
53{
54 if( (self=[super init])) {
55 ratio_ = ratio;
56 offset_ = offset;
57 }
58 return self;
59}
60@end
61
62@implementation CCParallaxNode
63
64@synthesize parallaxArray = parallaxArray_;
65
66-(id) init
67{
68 if( (self=[super init]) ) {
69 parallaxArray_ = ccArrayNew(5);
70 lastPosition = CGPointMake(-100,-100);
71 }
72 return self;
73}
74
75- (void) dealloc
76{
77 if( parallaxArray_ ) {
78 ccArrayFree(parallaxArray_);
79 parallaxArray_ = nil;
80 }
81 [super dealloc];
82}
83
84-(void) addChild:(CCNode*)child z:(NSInteger)z tag:(NSInteger)tag
85{
86 NSAssert(NO,@"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead");
87}
88
89-(void) addChild: (CCNode*) child z:(NSInteger)z parallaxRatio:(CGPoint)ratio positionOffset:(CGPoint)offset
90{
91 NSAssert( child != nil, @"Argument must be non-nil");
92 CGPointObject *obj = [CGPointObject pointWithCGPoint:ratio offset:offset];
93 obj.child = child;
94 ccArrayAppendObjectWithResize(parallaxArray_, obj);
95
96 CGPoint pos = self.position;
97 pos.x = pos.x * ratio.x + offset.x;
98 pos.y = pos.y * ratio.y + offset.y;
99 child.position = pos;
100
101 [super addChild: child z:z tag:child.tag];
102}
103
104-(void) removeChild:(CCNode*)node cleanup:(BOOL)cleanup
105{
106 for( unsigned int i=0;i < parallaxArray_->num;i++) {
107 CGPointObject *point = parallaxArray_->arr[i];
108 if( [point.child isEqual:node] ) {
109 ccArrayRemoveObjectAtIndex(parallaxArray_, i);
110 break;
111 }
112 }
113 [super removeChild:node cleanup:cleanup];
114}
115
116-(void) removeAllChildrenWithCleanup:(BOOL)cleanup
117{
118 ccArrayRemoveAllObjects(parallaxArray_);
119 [super removeAllChildrenWithCleanup:cleanup];
120}
121
122-(CGPoint) absolutePosition_
123{
124 CGPoint ret = position_;
125
126 CCNode *cn = self;
127
128 while (cn.parent != nil) {
129 cn = cn.parent;
130 ret = ccpAdd( ret, cn.position );
131 }
132
133 return ret;
134}
135
136/*
137 The positions are updated at visit because:
138 - using a timer is not guaranteed that it will called after all the positions were updated
139 - overriding "draw" will only precise if the children have a z > 0
140*/
141-(void) visit
142{
143// CGPoint pos = position_;
144// CGPoint pos = [self convertToWorldSpace:CGPointZero];
145 CGPoint pos = [self absolutePosition_];
146 if( ! CGPointEqualToPoint(pos, lastPosition) ) {
147
148 for(unsigned int i=0; i < parallaxArray_->num; i++ ) {
149
150 CGPointObject *point = parallaxArray_->arr[i];
151 float x = -pos.x + pos.x * point.ratio.x + point.offset.x;
152 float y = -pos.y + pos.y * point.ratio.y + point.offset.y;
153 point.child.position = ccp(x,y);
154 }
155
156 lastPosition = pos;
157 }
158
159 [super visit];
160}
161@end
diff --git a/libs/cocos2d/CCParticleExamples.h b/libs/cocos2d/CCParticleExamples.h new file mode 100755 index 0000000..cd382c4 --- /dev/null +++ b/libs/cocos2d/CCParticleExamples.h
@@ -0,0 +1,111 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Availability.h>
29
30#import "CCParticleSystemPoint.h"
31#import "CCParticleSystemQuad.h"
32
33// build each architecture with the optimal particle system
34
35// ARMv7, Mac or Simulator use "Quad" particle
36#if defined(__ARM_NEON__) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || TARGET_IPHONE_SIMULATOR
37 #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemQuad
38
39// ARMv6 use "Point" particle
40#elif __arm__
41 #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemPoint
42#else
43 #error(unknown architecture)
44#endif
45
46
47//! A fire particle system
48@interface CCParticleFire: ARCH_OPTIMAL_PARTICLE_SYSTEM
49{
50}
51@end
52
53//! A fireworks particle system
54@interface CCParticleFireworks : ARCH_OPTIMAL_PARTICLE_SYSTEM
55{
56}
57@end
58
59//! A sun particle system
60@interface CCParticleSun : ARCH_OPTIMAL_PARTICLE_SYSTEM
61{
62}
63@end
64
65//! A galaxy particle system
66@interface CCParticleGalaxy : ARCH_OPTIMAL_PARTICLE_SYSTEM
67{
68}
69@end
70
71//! A flower particle system
72@interface CCParticleFlower : ARCH_OPTIMAL_PARTICLE_SYSTEM
73{
74}
75@end
76
77//! A meteor particle system
78@interface CCParticleMeteor : ARCH_OPTIMAL_PARTICLE_SYSTEM
79{
80}
81@end
82
83//! An spiral particle system
84@interface CCParticleSpiral : ARCH_OPTIMAL_PARTICLE_SYSTEM
85{
86}
87@end
88
89//! An explosion particle system
90@interface CCParticleExplosion : ARCH_OPTIMAL_PARTICLE_SYSTEM
91{
92}
93@end
94
95//! An smoke particle system
96@interface CCParticleSmoke : ARCH_OPTIMAL_PARTICLE_SYSTEM
97{
98}
99@end
100
101//! An snow particle system
102@interface CCParticleSnow : ARCH_OPTIMAL_PARTICLE_SYSTEM
103{
104}
105@end
106
107//! A rain particle system
108@interface CCParticleRain : ARCH_OPTIMAL_PARTICLE_SYSTEM
109{
110}
111@end
diff --git a/libs/cocos2d/CCParticleExamples.m b/libs/cocos2d/CCParticleExamples.m new file mode 100755 index 0000000..38c8b46 --- /dev/null +++ b/libs/cocos2d/CCParticleExamples.m
@@ -0,0 +1,926 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28// cocos2d
29#import "CCParticleExamples.h"
30#import "CCTextureCache.h"
31#import "CCDirector.h"
32#import "Support/CGPointExtension.h"
33
34//
35// ParticleFireworks
36//
37@implementation CCParticleFireworks
38-(id) init
39{
40 return [self initWithTotalParticles:1500];
41}
42
43-(id) initWithTotalParticles:(NSUInteger)p
44{
45 if( (self=[super initWithTotalParticles:p]) ) {
46 // duration
47 duration = kCCParticleDurationInfinity;
48
49 // Gravity Mode
50 self.emitterMode = kCCParticleModeGravity;
51
52 // Gravity Mode: gravity
53 self.gravity = ccp(0,-90);
54
55 // Gravity Mode: radial
56 self.radialAccel = 0;
57 self.radialAccelVar = 0;
58
59 // Gravity Mode: speed of particles
60 self.speed = 180;
61 self.speedVar = 50;
62
63 // emitter position
64 CGSize winSize = [[CCDirector sharedDirector] winSize];
65 self.position = ccp(winSize.width/2, winSize.height/2);
66
67 // angle
68 angle = 90;
69 angleVar = 20;
70
71 // life of particles
72 life = 3.5f;
73 lifeVar = 1;
74
75 // emits per frame
76 emissionRate = totalParticles/life;
77
78 // color of particles
79 startColor.r = 0.5f;
80 startColor.g = 0.5f;
81 startColor.b = 0.5f;
82 startColor.a = 1.0f;
83 startColorVar.r = 0.5f;
84 startColorVar.g = 0.5f;
85 startColorVar.b = 0.5f;
86 startColorVar.a = 0.1f;
87 endColor.r = 0.1f;
88 endColor.g = 0.1f;
89 endColor.b = 0.1f;
90 endColor.a = 0.2f;
91 endColorVar.r = 0.1f;
92 endColorVar.g = 0.1f;
93 endColorVar.b = 0.1f;
94 endColorVar.a = 0.2f;
95
96 // size, in pixels
97 startSize = 8.0f;
98 startSizeVar = 2.0f;
99 endSize = kCCParticleStartSizeEqualToEndSize;
100
101 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
102
103 // additive
104 self.blendAdditive = NO;
105 }
106
107 return self;
108}
109@end
110
111//
112// ParticleFire
113//
114@implementation CCParticleFire
115-(id) init
116{
117 return [self initWithTotalParticles:250];
118}
119
120-(id) initWithTotalParticles:(NSUInteger) p
121{
122 if( (self=[super initWithTotalParticles:p]) ) {
123
124 // duration
125 duration = kCCParticleDurationInfinity;
126
127 // Gravity Mode
128 self.emitterMode = kCCParticleModeGravity;
129
130 // Gravity Mode: gravity
131 self.gravity = ccp(0,0);
132
133 // Gravity Mode: radial acceleration
134 self.radialAccel = 0;
135 self.radialAccelVar = 0;
136
137 // Gravity Mode: speed of particles
138 self.speed = 60;
139 self.speedVar = 20;
140
141 // starting angle
142 angle = 90;
143 angleVar = 10;
144
145 // emitter position
146 CGSize winSize = [[CCDirector sharedDirector] winSize];
147 self.position = ccp(winSize.width/2, 60);
148 posVar = ccp(40, 20);
149
150 // life of particles
151 life = 3;
152 lifeVar = 0.25f;
153
154
155 // size, in pixels
156 startSize = 54.0f;
157 startSizeVar = 10.0f;
158 endSize = kCCParticleStartSizeEqualToEndSize;
159
160 // emits per frame
161 emissionRate = totalParticles/life;
162
163 // color of particles
164 startColor.r = 0.76f;
165 startColor.g = 0.25f;
166 startColor.b = 0.12f;
167 startColor.a = 1.0f;
168 startColorVar.r = 0.0f;
169 startColorVar.g = 0.0f;
170 startColorVar.b = 0.0f;
171 startColorVar.a = 0.0f;
172 endColor.r = 0.0f;
173 endColor.g = 0.0f;
174 endColor.b = 0.0f;
175 endColor.a = 1.0f;
176 endColorVar.r = 0.0f;
177 endColorVar.g = 0.0f;
178 endColorVar.b = 0.0f;
179 endColorVar.a = 0.0f;
180
181 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
182
183 // additive
184 self.blendAdditive = YES;
185 }
186
187 return self;
188}
189@end
190
191//
192// ParticleSun
193//
194@implementation CCParticleSun
195-(id) init
196{
197 return [self initWithTotalParticles:350];
198}
199
200-(id) initWithTotalParticles:(NSUInteger) p
201{
202 if( (self=[super initWithTotalParticles:p]) ) {
203
204 // additive
205 self.blendAdditive = YES;
206
207 // duration
208 duration = kCCParticleDurationInfinity;
209
210 // Gravity Mode
211 self.emitterMode = kCCParticleModeGravity;
212
213 // Gravity Mode: gravity
214 self.gravity = ccp(0,0);
215
216 // Gravity mode: radial acceleration
217 self.radialAccel = 0;
218 self.radialAccelVar = 0;
219
220 // Gravity mode: speed of particles
221 self.speed = 20;
222 self.speedVar = 5;
223
224
225 // angle
226 angle = 90;
227 angleVar = 360;
228
229 // emitter position
230 CGSize winSize = [[CCDirector sharedDirector] winSize];
231 self.position = ccp(winSize.width/2, winSize.height/2);
232 posVar = CGPointZero;
233
234 // life of particles
235 life = 1;
236 lifeVar = 0.5f;
237
238 // size, in pixels
239 startSize = 30.0f;
240 startSizeVar = 10.0f;
241 endSize = kCCParticleStartSizeEqualToEndSize;
242
243 // emits per seconds
244 emissionRate = totalParticles/life;
245
246 // color of particles
247 startColor.r = 0.76f;
248 startColor.g = 0.25f;
249 startColor.b = 0.12f;
250 startColor.a = 1.0f;
251 startColorVar.r = 0.0f;
252 startColorVar.g = 0.0f;
253 startColorVar.b = 0.0f;
254 startColorVar.a = 0.0f;
255 endColor.r = 0.0f;
256 endColor.g = 0.0f;
257 endColor.b = 0.0f;
258 endColor.a = 1.0f;
259 endColorVar.r = 0.0f;
260 endColorVar.g = 0.0f;
261 endColorVar.b = 0.0f;
262 endColorVar.a = 0.0f;
263
264 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
265 }
266
267 return self;
268}
269@end
270
271//
272// ParticleGalaxy
273//
274@implementation CCParticleGalaxy
275-(id) init
276{
277 return [self initWithTotalParticles:200];
278}
279
280-(id) initWithTotalParticles:(NSUInteger)p
281{
282 if( (self=[super initWithTotalParticles:p]) ) {
283
284 // duration
285 duration = kCCParticleDurationInfinity;
286
287 // Gravity Mode
288 self.emitterMode = kCCParticleModeGravity;
289
290 // Gravity Mode: gravity
291 self.gravity = ccp(0,0);
292
293 // Gravity Mode: speed of particles
294 self.speed = 60;
295 self.speedVar = 10;
296
297 // Gravity Mode: radial
298 self.radialAccel = -80;
299 self.radialAccelVar = 0;
300
301 // Gravity Mode: tagential
302 self.tangentialAccel = 80;
303 self.tangentialAccelVar = 0;
304
305 // angle
306 angle = 90;
307 angleVar = 360;
308
309 // emitter position
310 CGSize winSize = [[CCDirector sharedDirector] winSize];
311 self.position = ccp(winSize.width/2, winSize.height/2);
312 posVar = CGPointZero;
313
314 // life of particles
315 life = 4;
316 lifeVar = 1;
317
318 // size, in pixels
319 startSize = 37.0f;
320 startSizeVar = 10.0f;
321 endSize = kCCParticleStartSizeEqualToEndSize;
322
323 // emits per second
324 emissionRate = totalParticles/life;
325
326 // color of particles
327 startColor.r = 0.12f;
328 startColor.g = 0.25f;
329 startColor.b = 0.76f;
330 startColor.a = 1.0f;
331 startColorVar.r = 0.0f;
332 startColorVar.g = 0.0f;
333 startColorVar.b = 0.0f;
334 startColorVar.a = 0.0f;
335 endColor.r = 0.0f;
336 endColor.g = 0.0f;
337 endColor.b = 0.0f;
338 endColor.a = 1.0f;
339 endColorVar.r = 0.0f;
340 endColorVar.g = 0.0f;
341 endColorVar.b = 0.0f;
342 endColorVar.a = 0.0f;
343
344 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
345
346 // additive
347 self.blendAdditive = YES;
348 }
349
350 return self;
351}
352@end
353
354//
355// ParticleFlower
356//
357@implementation CCParticleFlower
358-(id) init
359{
360 return [self initWithTotalParticles:250];
361}
362
363-(id) initWithTotalParticles:(NSUInteger) p
364{
365 if( (self=[super initWithTotalParticles:p]) ) {
366
367 // duration
368 duration = kCCParticleDurationInfinity;
369
370 // Gravity Mode
371 self.emitterMode = kCCParticleModeGravity;
372
373 // Gravity Mode: gravity
374 self.gravity = ccp(0,0);
375
376 // Gravity Mode: speed of particles
377 self.speed = 80;
378 self.speedVar = 10;
379
380 // Gravity Mode: radial
381 self.radialAccel = -60;
382 self.radialAccelVar = 0;
383
384 // Gravity Mode: tagential
385 self.tangentialAccel = 15;
386 self.tangentialAccelVar = 0;
387
388 // angle
389 angle = 90;
390 angleVar = 360;
391
392 // emitter position
393 CGSize winSize = [[CCDirector sharedDirector] winSize];
394 self.position = ccp(winSize.width/2, winSize.height/2);
395 posVar = CGPointZero;
396
397 // life of particles
398 life = 4;
399 lifeVar = 1;
400
401 // size, in pixels
402 startSize = 30.0f;
403 startSizeVar = 10.0f;
404 endSize = kCCParticleStartSizeEqualToEndSize;
405
406 // emits per second
407 emissionRate = totalParticles/life;
408
409 // color of particles
410 startColor.r = 0.50f;
411 startColor.g = 0.50f;
412 startColor.b = 0.50f;
413 startColor.a = 1.0f;
414 startColorVar.r = 0.5f;
415 startColorVar.g = 0.5f;
416 startColorVar.b = 0.5f;
417 startColorVar.a = 0.5f;
418 endColor.r = 0.0f;
419 endColor.g = 0.0f;
420 endColor.b = 0.0f;
421 endColor.a = 1.0f;
422 endColorVar.r = 0.0f;
423 endColorVar.g = 0.0f;
424 endColorVar.b = 0.0f;
425 endColorVar.a = 0.0f;
426
427 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
428
429 // additive
430 self.blendAdditive = YES;
431 }
432
433 return self;
434}
435@end
436
437//
438// ParticleMeteor
439//
440@implementation CCParticleMeteor
441-(id) init
442{
443 return [self initWithTotalParticles:150];
444}
445
446-(id) initWithTotalParticles:(NSUInteger) p
447{
448 if( (self=[super initWithTotalParticles:p]) ) {
449
450 // duration
451 duration = kCCParticleDurationInfinity;
452
453 // Gravity Mode
454 self.emitterMode = kCCParticleModeGravity;
455
456 // Gravity Mode: gravity
457 self.gravity = ccp(-200,200);
458
459 // Gravity Mode: speed of particles
460 self.speed = 15;
461 self.speedVar = 5;
462
463 // Gravity Mode: radial
464 self.radialAccel = 0;
465 self.radialAccelVar = 0;
466
467 // Gravity Mode: tagential
468 self.tangentialAccel = 0;
469 self.tangentialAccelVar = 0;
470
471 // angle
472 angle = 90;
473 angleVar = 360;
474
475 // emitter position
476 CGSize winSize = [[CCDirector sharedDirector] winSize];
477 self.position = ccp(winSize.width/2, winSize.height/2);
478 posVar = CGPointZero;
479
480 // life of particles
481 life = 2;
482 lifeVar = 1;
483
484 // size, in pixels
485 startSize = 60.0f;
486 startSizeVar = 10.0f;
487 endSize = kCCParticleStartSizeEqualToEndSize;
488
489 // emits per second
490 emissionRate = totalParticles/life;
491
492 // color of particles
493 startColor.r = 0.2f;
494 startColor.g = 0.4f;
495 startColor.b = 0.7f;
496 startColor.a = 1.0f;
497 startColorVar.r = 0.0f;
498 startColorVar.g = 0.0f;
499 startColorVar.b = 0.2f;
500 startColorVar.a = 0.1f;
501 endColor.r = 0.0f;
502 endColor.g = 0.0f;
503 endColor.b = 0.0f;
504 endColor.a = 1.0f;
505 endColorVar.r = 0.0f;
506 endColorVar.g = 0.0f;
507 endColorVar.b = 0.0f;
508 endColorVar.a = 0.0f;
509
510 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
511
512 // additive
513 self.blendAdditive = YES;
514 }
515
516 return self;
517}
518@end
519
520//
521// ParticleSpiral
522//
523@implementation CCParticleSpiral
524-(id) init
525{
526 return [self initWithTotalParticles:500];
527}
528
529-(id) initWithTotalParticles:(NSUInteger) p
530{
531 if( (self=[super initWithTotalParticles:p]) ) {
532
533 // duration
534 duration = kCCParticleDurationInfinity;
535
536 // Gravity Mode
537 self.emitterMode = kCCParticleModeGravity;
538
539 // Gravity Mode: gravity
540 self.gravity = ccp(0,0);
541
542 // Gravity Mode: speed of particles
543 self.speed = 150;
544 self.speedVar = 0;
545
546 // Gravity Mode: radial
547 self.radialAccel = -380;
548 self.radialAccelVar = 0;
549
550 // Gravity Mode: tagential
551 self.tangentialAccel = 45;
552 self.tangentialAccelVar = 0;
553
554 // angle
555 angle = 90;
556 angleVar = 0;
557
558 // emitter position
559 CGSize winSize = [[CCDirector sharedDirector] winSize];
560 self.position = ccp(winSize.width/2, winSize.height/2);
561 posVar = CGPointZero;
562
563 // life of particles
564 life = 12;
565 lifeVar = 0;
566
567 // size, in pixels
568 startSize = 20.0f;
569 startSizeVar = 0.0f;
570 endSize = kCCParticleStartSizeEqualToEndSize;
571
572 // emits per second
573 emissionRate = totalParticles/life;
574
575 // color of particles
576 startColor.r = 0.5f;
577 startColor.g = 0.5f;
578 startColor.b = 0.5f;
579 startColor.a = 1.0f;
580 startColorVar.r = 0.5f;
581 startColorVar.g = 0.5f;
582 startColorVar.b = 0.5f;
583 startColorVar.a = 0.0f;
584 endColor.r = 0.5f;
585 endColor.g = 0.5f;
586 endColor.b = 0.5f;
587 endColor.a = 1.0f;
588 endColorVar.r = 0.5f;
589 endColorVar.g = 0.5f;
590 endColorVar.b = 0.5f;
591 endColorVar.a = 0.0f;
592
593 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
594
595 // additive
596 self.blendAdditive = NO;
597 }
598
599 return self;
600}
601@end
602
603//
604// ParticleExplosion
605//
606@implementation CCParticleExplosion
607-(id) init
608{
609 return [self initWithTotalParticles:700];
610}
611
612-(id) initWithTotalParticles:(NSUInteger)p
613{
614 if( (self=[super initWithTotalParticles:p]) ) {
615
616 // duration
617 duration = 0.1f;
618
619 self.emitterMode = kCCParticleModeGravity;
620
621 // Gravity Mode: gravity
622 self.gravity = ccp(0,0);
623
624 // Gravity Mode: speed of particles
625 self.speed = 70;
626 self.speedVar = 40;
627
628 // Gravity Mode: radial
629 self.radialAccel = 0;
630 self.radialAccelVar = 0;
631
632 // Gravity Mode: tagential
633 self.tangentialAccel = 0;
634 self.tangentialAccelVar = 0;
635
636 // angle
637 angle = 90;
638 angleVar = 360;
639
640 // emitter position
641 CGSize winSize = [[CCDirector sharedDirector] winSize];
642 self.position = ccp(winSize.width/2, winSize.height/2);
643 posVar = CGPointZero;
644
645 // life of particles
646 life = 5.0f;
647 lifeVar = 2;
648
649 // size, in pixels
650 startSize = 15.0f;
651 startSizeVar = 10.0f;
652 endSize = kCCParticleStartSizeEqualToEndSize;
653
654 // emits per second
655 emissionRate = totalParticles/duration;
656
657 // color of particles
658 startColor.r = 0.7f;
659 startColor.g = 0.1f;
660 startColor.b = 0.2f;
661 startColor.a = 1.0f;
662 startColorVar.r = 0.5f;
663 startColorVar.g = 0.5f;
664 startColorVar.b = 0.5f;
665 startColorVar.a = 0.0f;
666 endColor.r = 0.5f;
667 endColor.g = 0.5f;
668 endColor.b = 0.5f;
669 endColor.a = 0.0f;
670 endColorVar.r = 0.5f;
671 endColorVar.g = 0.5f;
672 endColorVar.b = 0.5f;
673 endColorVar.a = 0.0f;
674
675 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
676
677 // additive
678 self.blendAdditive = NO;
679 }
680
681 return self;
682}
683@end
684
685//
686// ParticleSmoke
687//
688@implementation CCParticleSmoke
689-(id) init
690{
691 return [self initWithTotalParticles:200];
692}
693
694-(id) initWithTotalParticles:(NSUInteger) p
695{
696 if( (self=[super initWithTotalParticles:p]) ) {
697
698 // duration
699 duration = kCCParticleDurationInfinity;
700
701 // Emitter mode: Gravity Mode
702 self.emitterMode = kCCParticleModeGravity;
703
704 // Gravity Mode: gravity
705 self.gravity = ccp(0,0);
706
707 // Gravity Mode: radial acceleration
708 self.radialAccel = 0;
709 self.radialAccelVar = 0;
710
711 // Gravity Mode: speed of particles
712 self.speed = 25;
713 self.speedVar = 10;
714
715 // angle
716 angle = 90;
717 angleVar = 5;
718
719 // emitter position
720 CGSize winSize = [[CCDirector sharedDirector] winSize];
721 self.position = ccp(winSize.width/2, 0);
722 posVar = ccp(20, 0);
723
724 // life of particles
725 life = 4;
726 lifeVar = 1;
727
728 // size, in pixels
729 startSize = 60.0f;
730 startSizeVar = 10.0f;
731 endSize = kCCParticleStartSizeEqualToEndSize;
732
733 // emits per frame
734 emissionRate = totalParticles/life;
735
736 // color of particles
737 startColor.r = 0.8f;
738 startColor.g = 0.8f;
739 startColor.b = 0.8f;
740 startColor.a = 1.0f;
741 startColorVar.r = 0.02f;
742 startColorVar.g = 0.02f;
743 startColorVar.b = 0.02f;
744 startColorVar.a = 0.0f;
745 endColor.r = 0.0f;
746 endColor.g = 0.0f;
747 endColor.b = 0.0f;
748 endColor.a = 1.0f;
749 endColorVar.r = 0.0f;
750 endColorVar.g = 0.0f;
751 endColorVar.b = 0.0f;
752 endColorVar.a = 0.0f;
753
754 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
755
756 // additive
757 self.blendAdditive = NO;
758 }
759
760 return self;
761}
762@end
763
764@implementation CCParticleSnow
765-(id) init
766{
767 return [self initWithTotalParticles:700];
768}
769
770-(id) initWithTotalParticles:(NSUInteger)p
771{
772 if( (self=[super initWithTotalParticles:p]) ) {
773
774 // duration
775 duration = kCCParticleDurationInfinity;
776
777 // set gravity mode.
778 self.emitterMode = kCCParticleModeGravity;
779
780 // Gravity Mode: gravity
781 self.gravity = ccp(0,-1);
782
783 // Gravity Mode: speed of particles
784 self.speed = 5;
785 self.speedVar = 1;
786
787 // Gravity Mode: radial
788 self.radialAccel = 0;
789 self.radialAccelVar = 1;
790
791 // Gravity mode: tagential
792 self.tangentialAccel = 0;
793 self.tangentialAccelVar = 1;
794
795 // emitter position
796 self.position = (CGPoint) {
797 [[CCDirector sharedDirector] winSize].width / 2,
798 [[CCDirector sharedDirector] winSize].height + 10
799 };
800 posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 );
801
802 // angle
803 angle = -90;
804 angleVar = 5;
805
806 // life of particles
807 life = 45;
808 lifeVar = 15;
809
810 // size, in pixels
811 startSize = 10.0f;
812 startSizeVar = 5.0f;
813 endSize = kCCParticleStartSizeEqualToEndSize;
814
815 // emits per second
816 emissionRate = 10;
817
818 // color of particles
819 startColor.r = 1.0f;
820 startColor.g = 1.0f;
821 startColor.b = 1.0f;
822 startColor.a = 1.0f;
823 startColorVar.r = 0.0f;
824 startColorVar.g = 0.0f;
825 startColorVar.b = 0.0f;
826 startColorVar.a = 0.0f;
827 endColor.r = 1.0f;
828 endColor.g = 1.0f;
829 endColor.b = 1.0f;
830 endColor.a = 0.0f;
831 endColorVar.r = 0.0f;
832 endColorVar.g = 0.0f;
833 endColorVar.b = 0.0f;
834 endColorVar.a = 0.0f;
835
836 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
837
838 // additive
839 self.blendAdditive = NO;
840 }
841
842 return self;
843}
844@end
845
846@implementation CCParticleRain
847-(id) init
848{
849 return [self initWithTotalParticles:1000];
850}
851
852-(id) initWithTotalParticles:(NSUInteger)p
853{
854 if( (self=[super initWithTotalParticles:p]) ) {
855
856 // duration
857 duration = kCCParticleDurationInfinity;
858
859 self.emitterMode = kCCParticleModeGravity;
860
861 // Gravity Mode: gravity
862 self.gravity = ccp(10,-10);
863
864 // Gravity Mode: radial
865 self.radialAccel = 0;
866 self.radialAccelVar = 1;
867
868 // Gravity Mode: tagential
869 self.tangentialAccel = 0;
870 self.tangentialAccelVar = 1;
871
872 // Gravity Mode: speed of particles
873 self.speed = 130;
874 self.speedVar = 30;
875
876 // angle
877 angle = -90;
878 angleVar = 5;
879
880
881 // emitter position
882 self.position = (CGPoint) {
883 [[CCDirector sharedDirector] winSize].width / 2,
884 [[CCDirector sharedDirector] winSize].height
885 };
886 posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 );
887
888 // life of particles
889 life = 4.5f;
890 lifeVar = 0;
891
892 // size, in pixels
893 startSize = 4.0f;
894 startSizeVar = 2.0f;
895 endSize = kCCParticleStartSizeEqualToEndSize;
896
897 // emits per second
898 emissionRate = 20;
899
900 // color of particles
901 startColor.r = 0.7f;
902 startColor.g = 0.8f;
903 startColor.b = 1.0f;
904 startColor.a = 1.0f;
905 startColorVar.r = 0.0f;
906 startColorVar.g = 0.0f;
907 startColorVar.b = 0.0f;
908 startColorVar.a = 0.0f;
909 endColor.r = 0.7f;
910 endColor.g = 0.8f;
911 endColor.b = 1.0f;
912 endColor.a = 0.5f;
913 endColorVar.r = 0.0f;
914 endColorVar.g = 0.0f;
915 endColorVar.b = 0.0f;
916 endColorVar.a = 0.0f;
917
918 self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
919
920 // additive
921 self.blendAdditive = NO;
922 }
923
924 return self;
925}
926@end
diff --git a/libs/cocos2d/CCParticleSystem.h b/libs/cocos2d/CCParticleSystem.h new file mode 100755 index 0000000..429e814 --- /dev/null +++ b/libs/cocos2d/CCParticleSystem.h
@@ -0,0 +1,445 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCProtocols.h"
29#import "CCNode.h"
30#import "ccTypes.h"
31#import "ccConfig.h"
32
33#if CC_ENABLE_PROFILERS
34@class CCProfilingTimer;
35#endif
36
37//* @enum
38enum {
39 /** The Particle emitter lives forever */
40 kCCParticleDurationInfinity = -1,
41
42 /** The starting size of the particle is equal to the ending size */
43 kCCParticleStartSizeEqualToEndSize = -1,
44
45 /** The starting radius of the particle is equal to the ending radius */
46 kCCParticleStartRadiusEqualToEndRadius = -1,
47
48 // backward compatible
49 kParticleStartSizeEqualToEndSize = kCCParticleStartSizeEqualToEndSize,
50 kParticleDurationInfinity = kCCParticleDurationInfinity,
51};
52
53//* @enum
54enum {
55 /** Gravity mode (A mode) */
56 kCCParticleModeGravity,
57
58 /** Radius mode (B mode) */
59 kCCParticleModeRadius,
60};
61
62
63/** @typedef tCCPositionType
64 possible types of particle positions
65 */
66typedef enum {
67 /** Living particles are attached to the world and are unaffected by emitter repositioning. */
68 kCCPositionTypeFree,
69
70 /** Living particles are attached to the world but will follow the emitter repositioning.
71 Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.
72 */
73 kCCPositionTypeRelative,
74
75 /** Living particles are attached to the emitter and are translated along with it. */
76 kCCPositionTypeGrouped,
77}tCCPositionType;
78
79// backward compatible
80enum {
81 kPositionTypeFree = kCCPositionTypeFree,
82 kPositionTypeGrouped = kCCPositionTypeGrouped,
83};
84
85/** @struct tCCParticle
86 Structure that contains the values of each particle
87 */
88typedef struct sCCParticle {
89 CGPoint pos;
90 CGPoint startPos;
91
92 ccColor4F color;
93 ccColor4F deltaColor;
94
95 float size;
96 float deltaSize;
97
98 float rotation;
99 float deltaRotation;
100
101 ccTime timeToLive;
102
103 union {
104 // Mode A: gravity, direction, radial accel, tangential accel
105 struct {
106 CGPoint dir;
107 float radialAccel;
108 float tangentialAccel;
109 } A;
110
111 // Mode B: radius mode
112 struct {
113 float angle;
114 float degreesPerSecond;
115 float radius;
116 float deltaRadius;
117 } B;
118 } mode;
119
120}tCCParticle;
121
122typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint);
123
124@class CCTexture2D;
125
126/** Particle System base class
127 Attributes of a Particle System:
128 - emmision rate of the particles
129 - Gravity Mode (Mode A):
130 - gravity
131 - direction
132 - speed +- variance
133 - tangential acceleration +- variance
134 - radial acceleration +- variance
135 - Radius Mode (Mode B):
136 - startRadius +- variance
137 - endRadius +- variance
138 - rotate +- variance
139 - Properties common to all modes:
140 - life +- life variance
141 - start spin +- variance
142 - end spin +- variance
143 - start size +- variance
144 - end size +- variance
145 - start color +- variance
146 - end color +- variance
147 - life +- variance
148 - blending function
149 - texture
150
151 cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/).
152 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
153 cocos2d uses a another approach, but the results are almost identical.
154
155 cocos2d supports all the variables used by Particle Designer plus a bit more:
156 - spinning particles (supported when using CCParticleSystemQuad)
157 - tangential acceleration (Gravity mode)
158 - radial acceleration (Gravity mode)
159 - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only)
160
161 It is possible to customize any of the above mentioned properties in runtime. Example:
162
163 @code
164 emitter.radialAccel = 15;
165 emitter.startSpin = 0;
166 @endcode
167
168 */
169@interface CCParticleSystem : CCNode <CCTextureProtocol>
170{
171 // is the particle system active ?
172 BOOL active;
173 // duration in seconds of the system. -1 is infinity
174 float duration;
175 // time elapsed since the start of the system (in seconds)
176 float elapsed;
177
178 // position is from "superclass" CocosNode
179 CGPoint sourcePosition;
180 // Position variance
181 CGPoint posVar;
182
183 // The angle (direction) of the particles measured in degrees
184 float angle;
185 // Angle variance measured in degrees;
186 float angleVar;
187
188 // Different modes
189
190 NSInteger emitterMode_;
191 union {
192 // Mode A:Gravity + Tangential Accel + Radial Accel
193 struct {
194 // gravity of the particles
195 CGPoint gravity;
196
197 // The speed the particles will have.
198 float speed;
199 // The speed variance
200 float speedVar;
201
202 // Tangential acceleration
203 float tangentialAccel;
204 // Tangential acceleration variance
205 float tangentialAccelVar;
206
207 // Radial acceleration
208 float radialAccel;
209 // Radial acceleration variance
210 float radialAccelVar;
211 } A;
212
213 // Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
214 struct {
215
216 // The starting radius of the particles
217 float startRadius;
218 // The starting radius variance of the particles
219 float startRadiusVar;
220 // The ending radius of the particles
221 float endRadius;
222 // The ending radius variance of the particles
223 float endRadiusVar;
224 // Number of degress to rotate a particle around the source pos per second
225 float rotatePerSecond;
226 // Variance in degrees for rotatePerSecond
227 float rotatePerSecondVar;
228 } B;
229 } mode;
230
231 // start ize of the particles
232 float startSize;
233 // start Size variance
234 float startSizeVar;
235 // End size of the particle
236 float endSize;
237 // end size of variance
238 float endSizeVar;
239
240 // How many seconds will the particle live
241 float life;
242 // Life variance
243 float lifeVar;
244
245 // Start color of the particles
246 ccColor4F startColor;
247 // Start color variance
248 ccColor4F startColorVar;
249 // End color of the particles
250 ccColor4F endColor;
251 // End color variance
252 ccColor4F endColorVar;
253
254 // start angle of the particles
255 float startSpin;
256 // start angle variance
257 float startSpinVar;
258 // End angle of the particle
259 float endSpin;
260 // end angle ariance
261 float endSpinVar;
262
263
264 // Array of particles
265 tCCParticle *particles;
266 // Maximum particles
267 NSUInteger totalParticles;
268 // Count of active particles
269 NSUInteger particleCount;
270
271 // color modulate
272// BOOL colorModulate;
273
274 // How many particles can be emitted per second
275 float emissionRate;
276 float emitCounter;
277
278 // Texture of the particles
279 CCTexture2D *texture_;
280 // blend function
281 ccBlendFunc blendFunc_;
282
283 // movment type: free or grouped
284 tCCPositionType positionType_;
285
286 // Whether or not the node will be auto-removed when there are not particles
287 BOOL autoRemoveOnFinish_;
288
289 // particle idx
290 NSUInteger particleIdx;
291
292 // Optimization
293 CC_UPDATE_PARTICLE_IMP updateParticleImp;
294 SEL updateParticleSel;
295
296// profiling
297#if CC_ENABLE_PROFILERS
298 CCProfilingTimer* _profilingTimer;
299#endif
300}
301
302/** Is the emitter active */
303@property (nonatomic,readonly) BOOL active;
304/** Quantity of particles that are being simulated at the moment */
305@property (nonatomic,readonly) NSUInteger particleCount;
306/** How many seconds the emitter wil run. -1 means 'forever' */
307@property (nonatomic,readwrite,assign) float duration;
308/** sourcePosition of the emitter */
309@property (nonatomic,readwrite,assign) CGPoint sourcePosition;
310/** Position variance of the emitter */
311@property (nonatomic,readwrite,assign) CGPoint posVar;
312/** life, and life variation of each particle */
313@property (nonatomic,readwrite,assign) float life;
314/** life variance of each particle */
315@property (nonatomic,readwrite,assign) float lifeVar;
316/** angle and angle variation of each particle */
317@property (nonatomic,readwrite,assign) float angle;
318/** angle variance of each particle */
319@property (nonatomic,readwrite,assign) float angleVar;
320
321/** Gravity value. Only available in 'Gravity' mode. */
322@property (nonatomic,readwrite,assign) CGPoint gravity;
323/** speed of each particle. Only available in 'Gravity' mode. */
324@property (nonatomic,readwrite,assign) float speed;
325/** speed variance of each particle. Only available in 'Gravity' mode. */
326@property (nonatomic,readwrite,assign) float speedVar;
327/** tangential acceleration of each particle. Only available in 'Gravity' mode. */
328@property (nonatomic,readwrite,assign) float tangentialAccel;
329/** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */
330@property (nonatomic,readwrite,assign) float tangentialAccelVar;
331/** radial acceleration of each particle. Only available in 'Gravity' mode. */
332@property (nonatomic,readwrite,assign) float radialAccel;
333/** radial acceleration variance of each particle. Only available in 'Gravity' mode. */
334@property (nonatomic,readwrite,assign) float radialAccelVar;
335
336/** The starting radius of the particles. Only available in 'Radius' mode. */
337@property (nonatomic,readwrite,assign) float startRadius;
338/** The starting radius variance of the particles. Only available in 'Radius' mode. */
339@property (nonatomic,readwrite,assign) float startRadiusVar;
340/** The ending radius of the particles. Only available in 'Radius' mode. */
341@property (nonatomic,readwrite,assign) float endRadius;
342/** The ending radius variance of the particles. Only available in 'Radius' mode. */
343@property (nonatomic,readwrite,assign) float endRadiusVar;
344/** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */
345@property (nonatomic,readwrite,assign) float rotatePerSecond;
346/** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */
347@property (nonatomic,readwrite,assign) float rotatePerSecondVar;
348
349/** start size in pixels of each particle */
350@property (nonatomic,readwrite,assign) float startSize;
351/** size variance in pixels of each particle */
352@property (nonatomic,readwrite,assign) float startSizeVar;
353/** end size in pixels of each particle */
354@property (nonatomic,readwrite,assign) float endSize;
355/** end size variance in pixels of each particle */
356@property (nonatomic,readwrite,assign) float endSizeVar;
357/** start color of each particle */
358@property (nonatomic,readwrite,assign) ccColor4F startColor;
359/** start color variance of each particle */
360@property (nonatomic,readwrite,assign) ccColor4F startColorVar;
361/** end color and end color variation of each particle */
362@property (nonatomic,readwrite,assign) ccColor4F endColor;
363/** end color variance of each particle */
364@property (nonatomic,readwrite,assign) ccColor4F endColorVar;
365//* initial angle of each particle
366@property (nonatomic,readwrite,assign) float startSpin;
367//* initial angle of each particle
368@property (nonatomic,readwrite,assign) float startSpinVar;
369//* initial angle of each particle
370@property (nonatomic,readwrite,assign) float endSpin;
371//* initial angle of each particle
372@property (nonatomic,readwrite,assign) float endSpinVar;
373/** emission rate of the particles */
374@property (nonatomic,readwrite,assign) float emissionRate;
375/** maximum particles of the system */
376@property (nonatomic,readwrite,assign) NSUInteger totalParticles;
377/** conforms to CocosNodeTexture protocol */
378@property (nonatomic,readwrite, retain) CCTexture2D * texture;
379/** conforms to CocosNodeTexture protocol */
380@property (nonatomic,readwrite) ccBlendFunc blendFunc;
381/** whether or not the particles are using blend additive.
382 If enabled, the following blending function will be used.
383 @code
384 source blend function = GL_SRC_ALPHA;
385 dest blend function = GL_ONE;
386 @endcode
387 */
388@property (nonatomic,readwrite) BOOL blendAdditive;
389/** particles movement type: Free or Grouped
390 @since v0.8
391 */
392@property (nonatomic,readwrite) tCCPositionType positionType;
393/** whether or not the node will be auto-removed when it has no particles left.
394 By default it is NO.
395 @since v0.8
396 */
397@property (nonatomic,readwrite) BOOL autoRemoveOnFinish;
398/** Switch between different kind of emitter modes:
399 - kCCParticleModeGravity: uses gravity, speed, radial and tangential acceleration
400 - kCCParticleModeRadius: uses radius movement + rotation
401 */
402@property (nonatomic,readwrite) NSInteger emitterMode;
403
404/** creates an initializes a CCParticleSystem from a plist file.
405 This plist files can be creted manually or with Particle Designer:
406 http://particledesigner.71squared.com/
407 @since v0.99.3
408 */
409+(id) particleWithFile:(NSString*)plistFile;
410
411/** initializes a CCParticleSystem from a plist file.
412 This plist files can be creted manually or with Particle Designer:
413 http://particledesigner.71squared.com/
414 @since v0.99.3
415 */
416-(id) initWithFile:(NSString*) plistFile;
417
418/** initializes a CCQuadParticleSystem from a NSDictionary.
419 @since v0.99.3
420 */
421-(id) initWithDictionary:(NSDictionary*)dictionary;
422
423//! Initializes a system with a fixed number of particles
424-(id) initWithTotalParticles:(NSUInteger) numberOfParticles;
425//! Add a particle to the emitter
426-(BOOL) addParticle;
427//! Initializes a particle
428-(void) initParticle: (tCCParticle*) particle;
429//! stop emitting particles. Running particles will continue to run until they die
430-(void) stopSystem;
431//! Kill all living particles.
432-(void) resetSystem;
433//! whether or not the system is full
434-(BOOL) isFull;
435
436//! should be overriden by subclasses
437-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos;
438//! should be overriden by subclasses
439-(void) postStep;
440
441//! called in every loop.
442-(void) update: (ccTime) dt;
443
444@end
445
diff --git a/libs/cocos2d/CCParticleSystem.m b/libs/cocos2d/CCParticleSystem.m new file mode 100755 index 0000000..742676e --- /dev/null +++ b/libs/cocos2d/CCParticleSystem.m
@@ -0,0 +1,808 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28// ideas taken from:
29// . The ocean spray in your face [Jeff Lander]
30// http://www.double.co.nz/dust/col0798.pdf
31// . Building an Advanced Particle System [John van der Burg]
32// http://www.gamasutra.com/features/20000623/vanderburg_01.htm
33// . LOVE game engine
34// http://love2d.org/
35//
36//
37// Radius mode support, from 71 squared
38// http://particledesigner.71squared.com/
39//
40// IMPORTANT: Particle Designer is supported by cocos2d, but
41// 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
42// cocos2d uses a another approach, but the results are almost identical.
43//
44
45// opengl
46#import "Platforms/CCGL.h"
47
48// cocos2d
49#import "ccConfig.h"
50#if CC_ENABLE_PROFILERS
51#import "Support/CCProfiling.h"
52#endif
53#import "CCParticleSystem.h"
54#import "CCTextureCache.h"
55#import "ccMacros.h"
56
57// support
58#import "Support/OpenGL_Internal.h"
59#import "Support/CGPointExtension.h"
60#import "Support/base64.h"
61#import "Support/ZipUtils.h"
62#import "Support/CCFileUtils.h"
63
64@implementation CCParticleSystem
65@synthesize active, duration;
66@synthesize sourcePosition, posVar;
67@synthesize particleCount;
68@synthesize life, lifeVar;
69@synthesize angle, angleVar;
70@synthesize startColor, startColorVar, endColor, endColorVar;
71@synthesize startSpin, startSpinVar, endSpin, endSpinVar;
72@synthesize emissionRate;
73@synthesize totalParticles;
74@synthesize startSize, startSizeVar;
75@synthesize endSize, endSizeVar;
76@synthesize blendFunc = blendFunc_;
77@synthesize positionType = positionType_;
78@synthesize autoRemoveOnFinish = autoRemoveOnFinish_;
79@synthesize emitterMode = emitterMode_;
80
81
82+(id) particleWithFile:(NSString*) plistFile
83{
84 return [[[self alloc] initWithFile:plistFile] autorelease];
85}
86
87-(id) init {
88 NSAssert(NO, @"CCParticleSystem: Init not supported.");
89 [self release];
90 return nil;
91}
92
93-(id) initWithFile:(NSString *)plistFile
94{
95 NSString *path = [CCFileUtils fullPathFromRelativePath:plistFile];
96 NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
97
98 NSAssert( dict != nil, @"Particles: file not found");
99 return [self initWithDictionary:dict];
100}
101
102-(id) initWithDictionary:(NSDictionary *)dictionary
103{
104 NSUInteger maxParticles = [[dictionary valueForKey:@"maxParticles"] intValue];
105 // self, not super
106 if ((self=[self initWithTotalParticles:maxParticles] ) ) {
107
108 // angle
109 angle = [[dictionary valueForKey:@"angle"] floatValue];
110 angleVar = [[dictionary valueForKey:@"angleVariance"] floatValue];
111
112 // duration
113 duration = [[dictionary valueForKey:@"duration"] floatValue];
114
115 // blend function
116 blendFunc_.src = [[dictionary valueForKey:@"blendFuncSource"] intValue];
117 blendFunc_.dst = [[dictionary valueForKey:@"blendFuncDestination"] intValue];
118
119 // color
120 float r,g,b,a;
121
122 r = [[dictionary valueForKey:@"startColorRed"] floatValue];
123 g = [[dictionary valueForKey:@"startColorGreen"] floatValue];
124 b = [[dictionary valueForKey:@"startColorBlue"] floatValue];
125 a = [[dictionary valueForKey:@"startColorAlpha"] floatValue];
126 startColor = (ccColor4F) {r,g,b,a};
127
128 r = [[dictionary valueForKey:@"startColorVarianceRed"] floatValue];
129 g = [[dictionary valueForKey:@"startColorVarianceGreen"] floatValue];
130 b = [[dictionary valueForKey:@"startColorVarianceBlue"] floatValue];
131 a = [[dictionary valueForKey:@"startColorVarianceAlpha"] floatValue];
132 startColorVar = (ccColor4F) {r,g,b,a};
133
134 r = [[dictionary valueForKey:@"finishColorRed"] floatValue];
135 g = [[dictionary valueForKey:@"finishColorGreen"] floatValue];
136 b = [[dictionary valueForKey:@"finishColorBlue"] floatValue];
137 a = [[dictionary valueForKey:@"finishColorAlpha"] floatValue];
138 endColor = (ccColor4F) {r,g,b,a};
139
140 r = [[dictionary valueForKey:@"finishColorVarianceRed"] floatValue];
141 g = [[dictionary valueForKey:@"finishColorVarianceGreen"] floatValue];
142 b = [[dictionary valueForKey:@"finishColorVarianceBlue"] floatValue];
143 a = [[dictionary valueForKey:@"finishColorVarianceAlpha"] floatValue];
144 endColorVar = (ccColor4F) {r,g,b,a};
145
146 // particle size
147 startSize = [[dictionary valueForKey:@"startParticleSize"] floatValue];
148 startSizeVar = [[dictionary valueForKey:@"startParticleSizeVariance"] floatValue];
149 endSize = [[dictionary valueForKey:@"finishParticleSize"] floatValue];
150 endSizeVar = [[dictionary valueForKey:@"finishParticleSizeVariance"] floatValue];
151
152
153 // position
154 float x = [[dictionary valueForKey:@"sourcePositionx"] floatValue];
155 float y = [[dictionary valueForKey:@"sourcePositiony"] floatValue];
156 self.position = ccp(x,y);
157 posVar.x = [[dictionary valueForKey:@"sourcePositionVariancex"] floatValue];
158 posVar.y = [[dictionary valueForKey:@"sourcePositionVariancey"] floatValue];
159
160
161 // Spinning
162 startSpin = [[dictionary valueForKey:@"rotationStart"] floatValue];
163 startSpinVar = [[dictionary valueForKey:@"rotationStartVariance"] floatValue];
164 endSpin = [[dictionary valueForKey:@"rotationEnd"] floatValue];
165 endSpinVar = [[dictionary valueForKey:@"rotationEndVariance"] floatValue];
166
167 emitterMode_ = [[dictionary valueForKey:@"emitterType"] intValue];
168
169 // Mode A: Gravity + tangential accel + radial accel
170 if( emitterMode_ == kCCParticleModeGravity ) {
171 // gravity
172 mode.A.gravity.x = [[dictionary valueForKey:@"gravityx"] floatValue];
173 mode.A.gravity.y = [[dictionary valueForKey:@"gravityy"] floatValue];
174
175 //
176 // speed
177 mode.A.speed = [[dictionary valueForKey:@"speed"] floatValue];
178 mode.A.speedVar = [[dictionary valueForKey:@"speedVariance"] floatValue];
179
180 // radial acceleration
181 NSString *tmp = [dictionary valueForKey:@"radialAcceleration"];
182 mode.A.radialAccel = tmp ? [tmp floatValue] : 0;
183
184 tmp = [dictionary valueForKey:@"radialAccelVariance"];
185 mode.A.radialAccelVar = tmp ? [tmp floatValue] : 0;
186
187 // tangential acceleration
188 tmp = [dictionary valueForKey:@"tangentialAcceleration"];
189 mode.A.tangentialAccel = tmp ? [tmp floatValue] : 0;
190
191 tmp = [dictionary valueForKey:@"tangentialAccelVariance"];
192 mode.A.tangentialAccelVar = tmp ? [tmp floatValue] : 0;
193 }
194
195
196 // or Mode B: radius movement
197 else if( emitterMode_ == kCCParticleModeRadius ) {
198 float maxRadius = [[dictionary valueForKey:@"maxRadius"] floatValue];
199 float maxRadiusVar = [[dictionary valueForKey:@"maxRadiusVariance"] floatValue];
200 float minRadius = [[dictionary valueForKey:@"minRadius"] floatValue];
201
202 mode.B.startRadius = maxRadius;
203 mode.B.startRadiusVar = maxRadiusVar;
204 mode.B.endRadius = minRadius;
205 mode.B.endRadiusVar = 0;
206 mode.B.rotatePerSecond = [[dictionary valueForKey:@"rotatePerSecond"] floatValue];
207 mode.B.rotatePerSecondVar = [[dictionary valueForKey:@"rotatePerSecondVariance"] floatValue];
208
209 } else {
210 NSAssert( NO, @"Invalid emitterType in config file");
211 }
212
213 // life span
214 life = [[dictionary valueForKey:@"particleLifespan"] floatValue];
215 lifeVar = [[dictionary valueForKey:@"particleLifespanVariance"] floatValue];
216
217 // emission Rate
218 emissionRate = totalParticles/life;
219
220 // texture
221 // Try to get the texture from the cache
222 NSString *textureName = [dictionary valueForKey:@"textureFileName"];
223
224 CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:textureName];
225
226 if( tex )
227 self.texture = tex;
228
229 else {
230
231 NSString *textureData = [dictionary valueForKey:@"textureImageData"];
232 NSAssert( textureData, @"CCParticleSystem: Couldn't load texture");
233
234 // if it fails, try to get it from the base64-gzipped data
235 unsigned char *buffer = NULL;
236 int len = base64Decode((unsigned char*)[textureData UTF8String], (unsigned int)[textureData length], &buffer);
237 NSAssert( buffer != NULL, @"CCParticleSystem: error decoding textureImageData");
238
239 unsigned char *deflated = NULL;
240 NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated);
241 free( buffer );
242
243 NSAssert( deflated != NULL, @"CCParticleSystem: error ungzipping textureImageData");
244 NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen];
245
246#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
247 UIImage *image = [[UIImage alloc] initWithData:data];
248#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
249 NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data];
250#endif
251
252 free(deflated); deflated = NULL;
253
254 self.texture = [[CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName];
255 [data release];
256 [image release];
257 }
258
259 NSAssert( [self texture] != NULL, @"CCParticleSystem: error loading the texture");
260
261 }
262
263 return self;
264}
265
266-(id) initWithTotalParticles:(NSUInteger) numberOfParticles
267{
268 if( (self=[super init]) ) {
269
270 totalParticles = numberOfParticles;
271
272 particles = calloc( totalParticles, sizeof(tCCParticle) );
273
274 if( ! particles ) {
275 NSLog(@"Particle system: not enough memory");
276 [self release];
277 return nil;
278 }
279
280 // default, active
281 active = YES;
282
283 // default blend function
284 blendFunc_ = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST };
285
286 // default movement type;
287 positionType_ = kCCPositionTypeFree;
288
289 // by default be in mode A:
290 emitterMode_ = kCCParticleModeGravity;
291
292 // default: modulate
293 // XXX: not used
294 // colorModulate = YES;
295
296 autoRemoveOnFinish_ = NO;
297
298 // profiling
299#if CC_ENABLE_PROFILERS
300 _profilingTimer = [[CCProfiler timerWithName:@"particle system" andInstance:self] retain];
301#endif
302
303 // Optimization: compile udpateParticle method
304 updateParticleSel = @selector(updateQuadWithParticle:newPosition:);
305 updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel];
306
307 // udpate after action in run!
308 [self scheduleUpdateWithPriority:1];
309
310 }
311
312 return self;
313}
314
315-(void) dealloc
316{
317 free( particles );
318
319 [texture_ release];
320 // profiling
321#if CC_ENABLE_PROFILERS
322 [CCProfiler releaseTimer:_profilingTimer];
323#endif
324
325 [super dealloc];
326}
327
328-(BOOL) addParticle
329{
330 if( [self isFull] )
331 return NO;
332
333 tCCParticle * particle = &particles[ particleCount ];
334
335 [self initParticle: particle];
336 particleCount++;
337
338 return YES;
339}
340
341-(void) initParticle: (tCCParticle*) particle
342{
343
344 // timeToLive
345 // no negative life. prevent division by 0
346 particle->timeToLive = life + lifeVar * CCRANDOM_MINUS1_1();
347 particle->timeToLive = MAX(0, particle->timeToLive);
348
349 // position
350 particle->pos.x = sourcePosition.x + posVar.x * CCRANDOM_MINUS1_1();
351 particle->pos.x *= CC_CONTENT_SCALE_FACTOR();
352 particle->pos.y = sourcePosition.y + posVar.y * CCRANDOM_MINUS1_1();
353 particle->pos.y *= CC_CONTENT_SCALE_FACTOR();
354
355 // Color
356 ccColor4F start;
357 start.r = clampf( startColor.r + startColorVar.r * CCRANDOM_MINUS1_1(), 0, 1);
358 start.g = clampf( startColor.g + startColorVar.g * CCRANDOM_MINUS1_1(), 0, 1);
359 start.b = clampf( startColor.b + startColorVar.b * CCRANDOM_MINUS1_1(), 0, 1);
360 start.a = clampf( startColor.a + startColorVar.a * CCRANDOM_MINUS1_1(), 0, 1);
361
362 ccColor4F end;
363 end.r = clampf( endColor.r + endColorVar.r * CCRANDOM_MINUS1_1(), 0, 1);
364 end.g = clampf( endColor.g + endColorVar.g * CCRANDOM_MINUS1_1(), 0, 1);
365 end.b = clampf( endColor.b + endColorVar.b * CCRANDOM_MINUS1_1(), 0, 1);
366 end.a = clampf( endColor.a + endColorVar.a * CCRANDOM_MINUS1_1(), 0, 1);
367
368 particle->color = start;
369 particle->deltaColor.r = (end.r - start.r) / particle->timeToLive;
370 particle->deltaColor.g = (end.g - start.g) / particle->timeToLive;
371 particle->deltaColor.b = (end.b - start.b) / particle->timeToLive;
372 particle->deltaColor.a = (end.a - start.a) / particle->timeToLive;
373
374 // size
375 float startS = startSize + startSizeVar * CCRANDOM_MINUS1_1();
376 startS = MAX(0, startS); // No negative value
377 startS *= CC_CONTENT_SCALE_FACTOR();
378
379 particle->size = startS;
380 if( endSize == kCCParticleStartSizeEqualToEndSize )
381 particle->deltaSize = 0;
382 else {
383 float endS = endSize + endSizeVar * CCRANDOM_MINUS1_1();
384 endS = MAX(0, endS); // No negative values
385 endS *= CC_CONTENT_SCALE_FACTOR();
386 particle->deltaSize = (endS - startS) / particle->timeToLive;
387 }
388
389 // rotation
390 float startA = startSpin + startSpinVar * CCRANDOM_MINUS1_1();
391 float endA = endSpin + endSpinVar * CCRANDOM_MINUS1_1();
392 particle->rotation = startA;
393 particle->deltaRotation = (endA - startA) / particle->timeToLive;
394
395 // position
396 if( positionType_ == kCCPositionTypeFree ) {
397 CGPoint p = [self convertToWorldSpace:CGPointZero];
398 particle->startPos = ccpMult( p, CC_CONTENT_SCALE_FACTOR() );
399 }
400 else if( positionType_ == kCCPositionTypeRelative ) {
401 particle->startPos = ccpMult( position_, CC_CONTENT_SCALE_FACTOR() );
402 }
403
404 // direction
405 float a = CC_DEGREES_TO_RADIANS( angle + angleVar * CCRANDOM_MINUS1_1() );
406
407 // Mode Gravity: A
408 if( emitterMode_ == kCCParticleModeGravity ) {
409
410 CGPoint v = {cosf( a ), sinf( a )};
411 float s = mode.A.speed + mode.A.speedVar * CCRANDOM_MINUS1_1();
412 s *= CC_CONTENT_SCALE_FACTOR();
413
414 // direction
415 particle->mode.A.dir = ccpMult( v, s );
416
417 // radial accel
418 particle->mode.A.radialAccel = mode.A.radialAccel + mode.A.radialAccelVar * CCRANDOM_MINUS1_1();
419 particle->mode.A.radialAccel *= CC_CONTENT_SCALE_FACTOR();
420
421 // tangential accel
422 particle->mode.A.tangentialAccel = mode.A.tangentialAccel + mode.A.tangentialAccelVar * CCRANDOM_MINUS1_1();
423 particle->mode.A.tangentialAccel *= CC_CONTENT_SCALE_FACTOR();
424
425 }
426
427 // Mode Radius: B
428 else {
429 // Set the default diameter of the particle from the source position
430 float startRadius = mode.B.startRadius + mode.B.startRadiusVar * CCRANDOM_MINUS1_1();
431 float endRadius = mode.B.endRadius + mode.B.endRadiusVar * CCRANDOM_MINUS1_1();
432
433 startRadius *= CC_CONTENT_SCALE_FACTOR();
434 endRadius *= CC_CONTENT_SCALE_FACTOR();
435
436 particle->mode.B.radius = startRadius;
437
438 if( mode.B.endRadius == kCCParticleStartRadiusEqualToEndRadius )
439 particle->mode.B.deltaRadius = 0;
440 else
441 particle->mode.B.deltaRadius = (endRadius - startRadius) / particle->timeToLive;
442
443 particle->mode.B.angle = a;
444 particle->mode.B.degreesPerSecond = CC_DEGREES_TO_RADIANS(mode.B.rotatePerSecond + mode.B.rotatePerSecondVar * CCRANDOM_MINUS1_1());
445 }
446}
447
448-(void) stopSystem
449{
450 active = NO;
451 elapsed = duration;
452 emitCounter = 0;
453}
454
455-(void) resetSystem
456{
457 active = YES;
458 elapsed = 0;
459 for(particleIdx = 0; particleIdx < particleCount; ++particleIdx) {
460 tCCParticle *p = &particles[particleIdx];
461 p->timeToLive = 0;
462 }
463}
464
465-(BOOL) isFull
466{
467 return (particleCount == totalParticles);
468}
469
470#pragma mark ParticleSystem - MainLoop
471-(void) update: (ccTime) dt
472{
473 if( active && emissionRate ) {
474 float rate = 1.0f / emissionRate;
475 emitCounter += dt;
476 while( particleCount < totalParticles && emitCounter > rate ) {
477 [self addParticle];
478 emitCounter -= rate;
479 }
480
481 elapsed += dt;
482 if(duration != -1 && duration < elapsed)
483 [self stopSystem];
484 }
485
486 particleIdx = 0;
487
488
489#if CC_ENABLE_PROFILERS
490 CCProfilingBeginTimingBlock(_profilingTimer);
491#endif
492
493
494 CGPoint currentPosition = CGPointZero;
495 if( positionType_ == kCCPositionTypeFree ) {
496 currentPosition = [self convertToWorldSpace:CGPointZero];
497 currentPosition.x *= CC_CONTENT_SCALE_FACTOR();
498 currentPosition.y *= CC_CONTENT_SCALE_FACTOR();
499 }
500 else if( positionType_ == kCCPositionTypeRelative ) {
501 currentPosition = position_;
502 currentPosition.x *= CC_CONTENT_SCALE_FACTOR();
503 currentPosition.y *= CC_CONTENT_SCALE_FACTOR();
504 }
505
506 while( particleIdx < particleCount )
507 {
508 tCCParticle *p = &particles[particleIdx];
509
510 // life
511 p->timeToLive -= dt;
512
513 if( p->timeToLive > 0 ) {
514
515 // Mode A: gravity, direction, tangential accel & radial accel
516 if( emitterMode_ == kCCParticleModeGravity ) {
517 CGPoint tmp, radial, tangential;
518
519 radial = CGPointZero;
520 // radial acceleration
521 if(p->pos.x || p->pos.y)
522 radial = ccpNormalize(p->pos);
523
524 tangential = radial;
525 radial = ccpMult(radial, p->mode.A.radialAccel);
526
527 // tangential acceleration
528 float newy = tangential.x;
529 tangential.x = -tangential.y;
530 tangential.y = newy;
531 tangential = ccpMult(tangential, p->mode.A.tangentialAccel);
532
533 // (gravity + radial + tangential) * dt
534 tmp = ccpAdd( ccpAdd( radial, tangential), mode.A.gravity);
535 tmp = ccpMult( tmp, dt);
536 p->mode.A.dir = ccpAdd( p->mode.A.dir, tmp);
537 tmp = ccpMult(p->mode.A.dir, dt);
538 p->pos = ccpAdd( p->pos, tmp );
539 }
540
541 // Mode B: radius movement
542 else {
543 // Update the angle and radius of the particle.
544 p->mode.B.angle += p->mode.B.degreesPerSecond * dt;
545 p->mode.B.radius += p->mode.B.deltaRadius * dt;
546
547 p->pos.x = - cosf(p->mode.B.angle) * p->mode.B.radius;
548 p->pos.y = - sinf(p->mode.B.angle) * p->mode.B.radius;
549 }
550
551 // color
552 p->color.r += (p->deltaColor.r * dt);
553 p->color.g += (p->deltaColor.g * dt);
554 p->color.b += (p->deltaColor.b * dt);
555 p->color.a += (p->deltaColor.a * dt);
556
557 // size
558 p->size += (p->deltaSize * dt);
559 p->size = MAX( 0, p->size );
560
561 // angle
562 p->rotation += (p->deltaRotation * dt);
563
564 //
565 // update values in quad
566 //
567
568 CGPoint newPos;
569
570 if( positionType_ == kCCPositionTypeFree || positionType_ == kCCPositionTypeRelative ) {
571 CGPoint diff = ccpSub( currentPosition, p->startPos );
572 newPos = ccpSub(p->pos, diff);
573
574 } else
575 newPos = p->pos;
576
577
578 updateParticleImp(self, updateParticleSel, p, newPos);
579
580 // update particle counter
581 particleIdx++;
582
583 } else {
584 // life < 0
585 if( particleIdx != particleCount-1 )
586 particles[particleIdx] = particles[particleCount-1];
587 particleCount--;
588
589 if( particleCount == 0 && autoRemoveOnFinish_ ) {
590 [self unscheduleUpdate];
591 [parent_ removeChild:self cleanup:YES];
592 return;
593 }
594 }
595 }
596
597#if CC_ENABLE_PROFILERS
598 CCProfilingEndTimingBlock(_profilingTimer);
599#endif
600
601#ifdef CC_USES_VBO
602 [self postStep];
603#endif
604}
605
606-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos;
607{
608 // should be overriden
609}
610
611-(void) postStep
612{
613 // should be overriden
614}
615
616#pragma mark ParticleSystem - CCTexture protocol
617
618-(void) setTexture:(CCTexture2D*) texture
619{
620 [texture_ release];
621 texture_ = [texture retain];
622
623 // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
624 if( texture_ && ! [texture hasPremultipliedAlpha] &&
625 ( blendFunc_.src == CC_BLEND_SRC && blendFunc_.dst == CC_BLEND_DST ) ) {
626
627 blendFunc_.src = GL_SRC_ALPHA;
628 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
629 }
630}
631
632-(CCTexture2D*) texture
633{
634 return texture_;
635}
636
637#pragma mark ParticleSystem - Additive Blending
638-(void) setBlendAdditive:(BOOL)additive
639{
640 if( additive ) {
641 blendFunc_.src = GL_SRC_ALPHA;
642 blendFunc_.dst = GL_ONE;
643
644 } else {
645
646 if( texture_ && ! [texture_ hasPremultipliedAlpha] ) {
647 blendFunc_.src = GL_SRC_ALPHA;
648 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
649 } else {
650 blendFunc_.src = CC_BLEND_SRC;
651 blendFunc_.dst = CC_BLEND_DST;
652 }
653 }
654}
655
656-(BOOL) blendAdditive
657{
658 return( blendFunc_.src == GL_SRC_ALPHA && blendFunc_.dst == GL_ONE);
659}
660
661#pragma mark ParticleSystem - Properties of Gravity Mode
662-(void) setTangentialAccel:(float)t
663{
664 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
665 mode.A.tangentialAccel = t;
666}
667-(float) tangentialAccel
668{
669 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
670 return mode.A.tangentialAccel;
671}
672
673-(void) setTangentialAccelVar:(float)t
674{
675 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
676 mode.A.tangentialAccelVar = t;
677}
678-(float) tangentialAccelVar
679{
680 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
681 return mode.A.tangentialAccelVar;
682}
683
684-(void) setRadialAccel:(float)t
685{
686 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
687 mode.A.radialAccel = t;
688}
689-(float) radialAccel
690{
691 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
692 return mode.A.radialAccel;
693}
694
695-(void) setRadialAccelVar:(float)t
696{
697 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
698 mode.A.radialAccelVar = t;
699}
700-(float) radialAccelVar
701{
702 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
703 return mode.A.radialAccelVar;
704}
705
706-(void) setGravity:(CGPoint)g
707{
708 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
709 mode.A.gravity = g;
710}
711-(CGPoint) gravity
712{
713 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
714 return mode.A.gravity;
715}
716
717-(void) setSpeed:(float)speed
718{
719 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
720 mode.A.speed = speed;
721}
722-(float) speed
723{
724 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
725 return mode.A.speed;
726}
727
728-(void) setSpeedVar:(float)speedVar
729{
730 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
731 mode.A.speedVar = speedVar;
732}
733-(float) speedVar
734{
735 NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity");
736 return mode.A.speedVar;
737}
738
739#pragma mark ParticleSystem - Properties of Radius Mode
740
741-(void) setStartRadius:(float)startRadius
742{
743 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
744 mode.B.startRadius = startRadius;
745}
746-(float) startRadius
747{
748 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
749 return mode.B.startRadius;
750}
751
752-(void) setStartRadiusVar:(float)startRadiusVar
753{
754 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
755 mode.B.startRadiusVar = startRadiusVar;
756}
757-(float) startRadiusVar
758{
759 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
760 return mode.B.startRadiusVar;
761}
762
763-(void) setEndRadius:(float)endRadius
764{
765 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
766 mode.B.endRadius = endRadius;
767}
768-(float) endRadius
769{
770 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
771 return mode.B.endRadius;
772}
773
774-(void) setEndRadiusVar:(float)endRadiusVar
775{
776 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
777 mode.B.endRadiusVar = endRadiusVar;
778}
779-(float) endRadiusVar
780{
781 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
782 return mode.B.endRadiusVar;
783}
784
785-(void) setRotatePerSecond:(float)degrees
786{
787 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
788 mode.B.rotatePerSecond = degrees;
789}
790-(float) rotatePerSecond
791{
792 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
793 return mode.B.rotatePerSecond;
794}
795
796-(void) setRotatePerSecondVar:(float)degrees
797{
798 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
799 mode.B.rotatePerSecondVar = degrees;
800}
801-(float) rotatePerSecondVar
802{
803 NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius");
804 return mode.B.rotatePerSecondVar;
805}
806@end
807
808
diff --git a/libs/cocos2d/CCParticleSystemPoint.h b/libs/cocos2d/CCParticleSystemPoint.h new file mode 100755 index 0000000..f0918fe --- /dev/null +++ b/libs/cocos2d/CCParticleSystemPoint.h
@@ -0,0 +1,65 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Availability.h>
29#import "CCParticleSystem.h"
30
31#define CC_MAX_PARTICLE_SIZE 64
32
33#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
34
35/** CCParticleSystemPoint is a subclass of CCParticleSystem
36 Attributes of a Particle System:
37 * All the attributes of Particle System
38
39 Features:
40 * consumes small memory: uses 1 vertex (x,y) per particle, no need to assign tex coordinates
41 * size can't be bigger than 64
42 * the system can't be scaled since the particles are rendered using GL_POINT_SPRITE
43
44 Limitations:
45 * On 3rd gen iPhone devices and iPads, this node performs MUCH slower than CCParticleSystemQuad.
46 */
47@interface CCParticleSystemPoint : CCParticleSystem
48{
49 // Array of (x,y,size)
50 ccPointSprite *vertices;
51 // vertices buffer id
52#if CC_USES_VBO
53 GLuint verticesID;
54#endif
55}
56@end
57
58#elif __MAC_OS_X_VERSION_MAX_ALLOWED
59
60#import "CCParticleSystemQuad.h"
61
62@interface CCParticleSystemPoint : CCParticleSystemQuad
63@end
64
65#endif
diff --git a/libs/cocos2d/CCParticleSystemPoint.m b/libs/cocos2d/CCParticleSystemPoint.m new file mode 100755 index 0000000..0894d2b --- /dev/null +++ b/libs/cocos2d/CCParticleSystemPoint.m
@@ -0,0 +1,211 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Availability.h>
28#import "CCParticleSystemPoint.h"
29
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31
32// opengl
33#import "Platforms/CCGL.h"
34
35// cocos2d
36#import "CCTextureCache.h"
37#import "ccMacros.h"
38
39// support
40#import "Support/OpenGL_Internal.h"
41#import "Support/CGPointExtension.h"
42
43@implementation CCParticleSystemPoint
44
45-(id) initWithTotalParticles:(NSUInteger) numberOfParticles
46{
47 if( (self=[super initWithTotalParticles:numberOfParticles]) ) {
48
49 vertices = malloc( sizeof(ccPointSprite) * totalParticles );
50
51 if( ! vertices ) {
52 NSLog(@"cocos2d: Particle system: not enough memory");
53 [self release];
54 return nil;
55 }
56
57#if CC_USES_VBO
58 glGenBuffers(1, &verticesID);
59
60 // initial binding
61 glBindBuffer(GL_ARRAY_BUFFER, verticesID);
62 glBufferData(GL_ARRAY_BUFFER, sizeof(ccPointSprite)*totalParticles, vertices, GL_DYNAMIC_DRAW);
63 glBindBuffer(GL_ARRAY_BUFFER, 0);
64#endif
65 }
66
67 return self;
68}
69
70-(void) dealloc
71{
72 free(vertices);
73#if CC_USES_VBO
74 glDeleteBuffers(1, &verticesID);
75#endif
76
77 [super dealloc];
78}
79
80-(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos
81{
82 // place vertices and colos in array
83 vertices[particleIdx].pos = (ccVertex2F) {newPos.x, newPos.y};
84 vertices[particleIdx].size = p->size;
85 ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255 };
86 vertices[particleIdx].color = color;
87}
88
89-(void) postStep
90{
91#if CC_USES_VBO
92 glBindBuffer(GL_ARRAY_BUFFER, verticesID);
93 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(ccPointSprite)*particleCount, vertices);
94 glBindBuffer(GL_ARRAY_BUFFER, 0);
95#endif
96}
97
98-(void) draw
99{
100 [super draw];
101
102 if (particleIdx==0)
103 return;
104
105 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
106 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY
107 // Unneeded states: GL_TEXTURE_COORD_ARRAY
108 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
109
110 glBindTexture(GL_TEXTURE_2D, texture_.name);
111
112 glEnable(GL_POINT_SPRITE_OES);
113 glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE );
114
115#define kPointSize sizeof(vertices[0])
116
117#if CC_USES_VBO
118 glBindBuffer(GL_ARRAY_BUFFER, verticesID);
119
120 glVertexPointer(2,GL_FLOAT, kPointSize, 0);
121
122 glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) offsetof(ccPointSprite, color) );
123
124 glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
125 glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, size) );
126#else // Uses Vertex Array List
127 int offset = (int)vertices;
128 glVertexPointer(2,GL_FLOAT, kPointSize, (GLvoid*) offset);
129
130 int diff = offsetof(ccPointSprite, color);
131 glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) (offset+diff));
132
133 glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
134 diff = offsetof(ccPointSprite, size);
135 glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) (offset+diff));
136#endif
137
138 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
139 if( newBlend )
140 glBlendFunc( blendFunc_.src, blendFunc_.dst );
141
142
143 glDrawArrays(GL_POINTS, 0, particleIdx);
144
145 // restore blend state
146 if( newBlend )
147 glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST);
148
149
150#if CC_USES_VBO
151 // unbind VBO buffer
152 glBindBuffer(GL_ARRAY_BUFFER, 0);
153#endif
154
155 glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
156 glDisable(GL_POINT_SPRITE_OES);
157
158 // restore GL default state
159 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
160}
161
162#pragma mark Non supported properties
163
164//
165// SPIN IS NOT SUPPORTED
166//
167-(void) setStartSpin:(float)a
168{
169 NSAssert(a == 0, @"PointParticleSystem doesn't support spinning");
170 [super setStartSpin:a];
171}
172-(void) setStartSpinVar:(float)a
173{
174 NSAssert(a == 0, @"PointParticleSystem doesn't support spinning");
175 [super setStartSpin:a];
176}
177-(void) setEndSpin:(float)a
178{
179 NSAssert(a == 0, @"PointParticleSystem doesn't support spinning");
180 [super setStartSpin:a];
181}
182-(void) setEndSpinVar:(float)a
183{
184 NSAssert(a == 0, @"PointParticleSystem doesn't support spinning");
185 [super setStartSpin:a];
186}
187
188//
189// SIZE > 64 IS NOT SUPPORTED
190//
191-(void) setStartSize:(float)size
192{
193 NSAssert(size >= 0 && size <= CC_MAX_PARTICLE_SIZE, @"PointParticleSystem only supports 0 <= size <= 64");
194 [super setStartSize:size];
195}
196
197-(void) setEndSize:(float)size
198{
199 NSAssert( (size == kCCParticleStartSizeEqualToEndSize) ||
200 ( size >= 0 && size <= CC_MAX_PARTICLE_SIZE), @"PointParticleSystem only supports 0 <= size <= 64");
201 [super setEndSize:size];
202}
203@end
204
205#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
206@implementation CCParticleSystemPoint
207@end
208
209#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
210
211
diff --git a/libs/cocos2d/CCParticleSystemQuad.h b/libs/cocos2d/CCParticleSystemQuad.h new file mode 100755 index 0000000..74a9d93 --- /dev/null +++ b/libs/cocos2d/CCParticleSystemQuad.h
@@ -0,0 +1,76 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Leonardo Kasperavičius
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30#import "CCParticleSystem.h"
31#import "ccConfig.h"
32
33@class CCSpriteFrame;
34
35/** CCParticleSystemQuad is a subclass of CCParticleSystem
36
37 It includes all the features of ParticleSystem.
38
39 Special features and Limitations:
40 - Particle size can be any float number.
41 - The system can be scaled
42 - The particles can be rotated
43 - On 1st and 2nd gen iPhones: It is only a bit slower that CCParticleSystemPoint
44 - On 3rd gen iPhone and iPads: It is MUCH faster than CCParticleSystemPoint
45 - It consumes more RAM and more GPU memory than CCParticleSystemPoint
46 - It supports subrects
47 @since v0.8
48 */
49@interface CCParticleSystemQuad : CCParticleSystem
50{
51 ccV2F_C4B_T2F_Quad *quads_; // quads to be rendered
52 GLushort *indices_; // indices
53#if CC_USES_VBO
54 GLuint quadsID_; // VBO id
55#endif
56}
57
58/** initialices the indices for the vertices */
59-(void) initIndices;
60
61/** initilizes the texture with a rectangle measured Points */
62-(void) initTexCoordsWithRect:(CGRect)rect;
63
64/** Sets a new CCSpriteFrame as particle.
65 WARNING: this method is experimental. Use setTexture:withRect instead.
66 @since v0.99.4
67 */
68-(void)setDisplayFrame:(CCSpriteFrame*)spriteFrame;
69
70/** Sets a new texture with a rect. The rect is in Points.
71 @since v0.99.4
72 */
73-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect;
74
75@end
76
diff --git a/libs/cocos2d/CCParticleSystemQuad.m b/libs/cocos2d/CCParticleSystemQuad.m new file mode 100755 index 0000000..4916964 --- /dev/null +++ b/libs/cocos2d/CCParticleSystemQuad.m
@@ -0,0 +1,318 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Leonardo Kasperavičius
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30// opengl
31#import "Platforms/CCGL.h"
32
33// cocos2d
34#import "ccConfig.h"
35#import "CCParticleSystemQuad.h"
36#import "CCTextureCache.h"
37#import "ccMacros.h"
38#import "CCSpriteFrame.h"
39
40// support
41#import "Support/OpenGL_Internal.h"
42#import "Support/CGPointExtension.h"
43
44@implementation CCParticleSystemQuad
45
46
47// overriding the init method
48-(id) initWithTotalParticles:(NSUInteger) numberOfParticles
49{
50 // base initialization
51 if( (self=[super initWithTotalParticles:numberOfParticles]) ) {
52
53 // allocating data space
54 quads_ = calloc( sizeof(quads_[0]) * totalParticles, 1 );
55 indices_ = calloc( sizeof(indices_[0]) * totalParticles * 6, 1 );
56
57 if( !quads_ || !indices_) {
58 NSLog(@"cocos2d: Particle system: not enough memory");
59 if( quads_ )
60 free( quads_ );
61 if(indices_)
62 free(indices_);
63
64 [self release];
65 return nil;
66 }
67
68 // initialize only once the texCoords and the indices
69 [self initTexCoordsWithRect:CGRectMake(0, 0, [texture_ pixelsWide], [texture_ pixelsHigh])];
70 [self initIndices];
71
72#if CC_USES_VBO
73 // create the VBO buffer
74 glGenBuffers(1, &quadsID_);
75
76 // initial binding
77 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
78 glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0])*totalParticles, quads_,GL_DYNAMIC_DRAW);
79 glBindBuffer(GL_ARRAY_BUFFER, 0);
80#endif
81 }
82
83 return self;
84}
85
86-(void) dealloc
87{
88 free(quads_);
89 free(indices_);
90#if CC_USES_VBO
91 glDeleteBuffers(1, &quadsID_);
92#endif
93
94 [super dealloc];
95}
96
97// pointRect is in Points coordinates.
98-(void) initTexCoordsWithRect:(CGRect)pointRect
99{
100 // convert to pixels coords
101 CGRect rect = CGRectMake(
102 pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(),
103 pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(),
104 pointRect.size.width * CC_CONTENT_SCALE_FACTOR(),
105 pointRect.size.height * CC_CONTENT_SCALE_FACTOR() );
106
107 GLfloat wide = [texture_ pixelsWide];
108 GLfloat high = [texture_ pixelsHigh];
109
110#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
111 GLfloat left = (rect.origin.x*2+1) / (wide*2);
112 GLfloat bottom = (rect.origin.y*2+1) / (high*2);
113 GLfloat right = left + (rect.size.width*2-2) / (wide*2);
114 GLfloat top = bottom + (rect.size.height*2-2) / (high*2);
115#else
116 GLfloat left = rect.origin.x / wide;
117 GLfloat bottom = rect.origin.y / high;
118 GLfloat right = left + rect.size.width / wide;
119 GLfloat top = bottom + rect.size.height / high;
120#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
121
122 // Important. Texture in cocos2d are inverted, so the Y component should be inverted
123 CC_SWAP( top, bottom);
124
125 for(NSUInteger i=0; i<totalParticles; i++) {
126 // bottom-left vertex:
127 quads_[i].bl.texCoords.u = left;
128 quads_[i].bl.texCoords.v = bottom;
129 // bottom-right vertex:
130 quads_[i].br.texCoords.u = right;
131 quads_[i].br.texCoords.v = bottom;
132 // top-left vertex:
133 quads_[i].tl.texCoords.u = left;
134 quads_[i].tl.texCoords.v = top;
135 // top-right vertex:
136 quads_[i].tr.texCoords.u = right;
137 quads_[i].tr.texCoords.v = top;
138 }
139}
140
141-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect
142{
143 // Only update the texture if is different from the current one
144 if( [texture name] != [texture_ name] )
145 [super setTexture:texture];
146
147 [self initTexCoordsWithRect:rect];
148}
149
150-(void) setTexture:(CCTexture2D *)texture
151{
152 CGSize s = [texture contentSize];
153 [self setTexture:texture withRect:CGRectMake(0,0, s.width, s.height)];
154}
155
156-(void) setDisplayFrame:(CCSpriteFrame *)spriteFrame
157{
158
159 NSAssert( CGPointEqualToPoint( spriteFrame.offsetInPixels , CGPointZero ), @"QuadParticle only supports SpriteFrames with no offsets");
160
161 // update texture before updating texture rect
162 if ( spriteFrame.texture.name != texture_.name )
163 [self setTexture: spriteFrame.texture];
164}
165
166-(void) initIndices
167{
168 for( NSUInteger i=0;i< totalParticles;i++) {
169 const NSUInteger i6 = i*6;
170 const NSUInteger i4 = i*4;
171 indices_[i6+0] = (GLushort) i4+0;
172 indices_[i6+1] = (GLushort) i4+1;
173 indices_[i6+2] = (GLushort) i4+2;
174
175 indices_[i6+5] = (GLushort) i4+1;
176 indices_[i6+4] = (GLushort) i4+2;
177 indices_[i6+3] = (GLushort) i4+3;
178 }
179}
180
181-(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos
182{
183 // colors
184 ccV2F_C4B_T2F_Quad *quad = &(quads_[particleIdx]);
185
186 ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255};
187 quad->bl.colors = color;
188 quad->br.colors = color;
189 quad->tl.colors = color;
190 quad->tr.colors = color;
191
192 // vertices
193 GLfloat size_2 = p->size/2;
194 if( p->rotation ) {
195 GLfloat x1 = -size_2;
196 GLfloat y1 = -size_2;
197
198 GLfloat x2 = size_2;
199 GLfloat y2 = size_2;
200 GLfloat x = newPos.x;
201 GLfloat y = newPos.y;
202
203 GLfloat r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation);
204 GLfloat cr = cosf(r);
205 GLfloat sr = sinf(r);
206 GLfloat ax = x1 * cr - y1 * sr + x;
207 GLfloat ay = x1 * sr + y1 * cr + y;
208 GLfloat bx = x2 * cr - y1 * sr + x;
209 GLfloat by = x2 * sr + y1 * cr + y;
210 GLfloat cx = x2 * cr - y2 * sr + x;
211 GLfloat cy = x2 * sr + y2 * cr + y;
212 GLfloat dx = x1 * cr - y2 * sr + x;
213 GLfloat dy = x1 * sr + y2 * cr + y;
214
215 // bottom-left
216 quad->bl.vertices.x = ax;
217 quad->bl.vertices.y = ay;
218
219 // bottom-right vertex:
220 quad->br.vertices.x = bx;
221 quad->br.vertices.y = by;
222
223 // top-left vertex:
224 quad->tl.vertices.x = dx;
225 quad->tl.vertices.y = dy;
226
227 // top-right vertex:
228 quad->tr.vertices.x = cx;
229 quad->tr.vertices.y = cy;
230 } else {
231 // bottom-left vertex:
232 quad->bl.vertices.x = newPos.x - size_2;
233 quad->bl.vertices.y = newPos.y - size_2;
234
235 // bottom-right vertex:
236 quad->br.vertices.x = newPos.x + size_2;
237 quad->br.vertices.y = newPos.y - size_2;
238
239 // top-left vertex:
240 quad->tl.vertices.x = newPos.x - size_2;
241 quad->tl.vertices.y = newPos.y + size_2;
242
243 // top-right vertex:
244 quad->tr.vertices.x = newPos.x + size_2;
245 quad->tr.vertices.y = newPos.y + size_2;
246 }
247}
248
249-(void) postStep
250{
251#if CC_USES_VBO
252 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
253 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quads_[0])*particleCount, quads_);
254 glBindBuffer(GL_ARRAY_BUFFER, 0);
255#endif
256}
257
258// overriding draw method
259-(void) draw
260{
261 [super draw];
262
263 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
264 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
265 // Unneeded states: -
266
267 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
268
269#define kQuadSize sizeof(quads_[0].bl)
270
271#if CC_USES_VBO
272 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
273
274 glVertexPointer(2,GL_FLOAT, kQuadSize, 0);
275
276 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof(ccV2F_C4B_T2F,colors) );
277
278 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4B_T2F,texCoords) );
279#else // vertex array list
280
281 NSUInteger offset = (NSUInteger) quads_;
282
283 // vertex
284 NSUInteger diff = offsetof( ccV2F_C4B_T2F, vertices);
285 glVertexPointer(2,GL_FLOAT, kQuadSize, (GLvoid*) (offset+diff) );
286
287 // color
288 diff = offsetof( ccV2F_C4B_T2F, colors);
289 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
290
291 // tex coords
292 diff = offsetof( ccV2F_C4B_T2F, texCoords);
293 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
294
295#endif // ! CC_USES_VBO
296
297 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
298 if( newBlend )
299 glBlendFunc( blendFunc_.src, blendFunc_.dst );
300
301 NSAssert( particleIdx == particleCount, @"Abnormal error in particle quad");
302 glDrawElements(GL_TRIANGLES, (GLsizei) particleIdx*6, GL_UNSIGNED_SHORT, indices_);
303
304 // restore blend state
305 if( newBlend )
306 glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST );
307
308#if CC_USES_VBO
309 glBindBuffer(GL_ARRAY_BUFFER, 0);
310#endif
311
312 // restore GL default state
313 // -
314}
315
316@end
317
318
diff --git a/libs/cocos2d/CCProgressTimer.h b/libs/cocos2d/CCProgressTimer.h new file mode 100755 index 0000000..9a07f2f --- /dev/null +++ b/libs/cocos2d/CCProgressTimer.h
@@ -0,0 +1,83 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Foundation/Foundation.h>
27#import "CCSprite.h"
28
29/** Types of progress
30 @since v0.99.1
31 */
32typedef enum {
33 /// Radial Counter-Clockwise
34 kCCProgressTimerTypeRadialCCW,
35 /// Radial ClockWise
36 kCCProgressTimerTypeRadialCW,
37 /// Horizontal Left-Right
38 kCCProgressTimerTypeHorizontalBarLR,
39 /// Horizontal Right-Left
40 kCCProgressTimerTypeHorizontalBarRL,
41 /// Vertical Bottom-top
42 kCCProgressTimerTypeVerticalBarBT,
43 /// Vertical Top-Bottom
44 kCCProgressTimerTypeVerticalBarTB,
45} CCProgressTimerType;
46
47/**
48 CCProgresstimer is a subclass of CCNode.
49 It renders the inner sprite according to the percentage.
50 The progress can be Radial, Horizontal or vertical.
51 @since v0.99.1
52 */
53@interface CCProgressTimer : CCNode
54{
55 CCProgressTimerType type_;
56 float percentage_;
57 CCSprite *sprite_;
58
59 int vertexDataCount_;
60 ccV2F_C4B_T2F *vertexData_;
61}
62
63/** Change the percentage to change progress. */
64@property (nonatomic, readwrite) CCProgressTimerType type;
65
66/** Percentages are from 0 to 100 */
67@property (nonatomic, readwrite) float percentage;
68
69/** The image to show the progress percentage */
70@property (nonatomic, readwrite, retain) CCSprite *sprite;
71
72
73/** Creates a progress timer with an image filename as the shape the timer goes through */
74+ (id) progressWithFile:(NSString*) filename;
75/** Initializes a progress timer with an image filename as the shape the timer goes through */
76- (id) initWithFile:(NSString*) filename;
77
78/** Creates a progress timer with the texture as the shape the timer goes through */
79+ (id) progressWithTexture:(CCTexture2D*) texture;
80/** Creates a progress timer with the texture as the shape the timer goes through */
81- (id) initWithTexture:(CCTexture2D*) texture;
82
83@end
diff --git a/libs/cocos2d/CCProgressTimer.m b/libs/cocos2d/CCProgressTimer.m new file mode 100755 index 0000000..4e697b2 --- /dev/null +++ b/libs/cocos2d/CCProgressTimer.m
@@ -0,0 +1,493 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "CCProgressTimer.h"
27
28#import "ccMacros.h"
29#import "CCTextureCache.h"
30#import "Support/CGPointExtension.h"
31
32
33
34#define kProgressTextureCoordsCount 4
35// kProgressTextureCoords holds points {0,0} {0,1} {1,1} {1,0} we can represent it as bits
36const char kProgressTextureCoords = 0x1e;
37
38@interface CCProgressTimer (Internal)
39
40-(void)updateProgress;
41-(void)updateBar;
42-(void)updateRadial;
43-(void)updateColor;
44-(CGPoint)boundaryTexCoord:(char)index;
45@end
46
47
48@implementation CCProgressTimer
49@synthesize percentage = percentage_;
50@synthesize sprite = sprite_;
51@synthesize type = type_;
52
53+(id)progressWithFile:(NSString*) filename
54{
55 return [[[self alloc]initWithFile:filename] autorelease];
56}
57-(id)initWithFile:(NSString*) filename
58{
59 return [self initWithTexture:[[CCTextureCache sharedTextureCache] addImage: filename]];
60}
61
62+(id)progressWithTexture:(CCTexture2D*) texture
63{
64 return [[[self alloc]initWithTexture:texture] autorelease];
65}
66-(id)initWithTexture:(CCTexture2D*) texture
67{
68 if(( self = [super init] )){
69 self.sprite = [CCSprite spriteWithTexture:texture];
70 percentage_ = 0.f;
71 vertexData_ = NULL;
72 vertexDataCount_ = 0;
73 self.anchorPoint = ccp(.5f,.5f);
74 self.contentSize = sprite_.contentSize;
75 self.type = kCCProgressTimerTypeRadialCCW;
76 }
77 return self;
78}
79-(void)dealloc
80{
81 if(vertexData_)
82 free(vertexData_);
83
84 [sprite_ release];
85 [super dealloc];
86}
87
88-(void)setPercentage:(float) percentage
89{
90 if(percentage_ != percentage) {
91 percentage_ = clampf( percentage, 0, 100);
92 [self updateProgress];
93 }
94}
95-(void)setSprite:(CCSprite *)newSprite
96{
97 if(sprite_ != newSprite){
98 [sprite_ release];
99 sprite_ = [newSprite retain];
100
101 // Everytime we set a new sprite, we free the current vertex data
102 if(vertexData_){
103 free(vertexData_);
104 vertexData_ = NULL;
105 vertexDataCount_ = 0;
106 }
107 }
108}
109-(void)setType:(CCProgressTimerType)newType
110{
111 if (newType != type_) {
112
113 // release all previous information
114 if(vertexData_){
115 free(vertexData_);
116 vertexData_ = NULL;
117 vertexDataCount_ = 0;
118 }
119 type_ = newType;
120 }
121}
122@end
123
124@implementation CCProgressTimer(Internal)
125
126///
127// @returns the vertex position from the texture coordinate
128///
129-(ccVertex2F)vertexFromTexCoord:(CGPoint) texCoord
130{
131 CGPoint tmp;
132 ccVertex2F ret;
133 if (sprite_.texture) {
134 CCTexture2D *texture = [sprite_ texture];
135 CGSize texSize = [texture contentSizeInPixels];
136 tmp = ccp(texSize.width * texCoord.x/texture.maxS,
137 texSize.height * (1 - (texCoord.y/texture.maxT)));
138 } else
139 tmp = CGPointZero;
140
141 ret.x = tmp.x;
142 ret.y = tmp.y;
143 return ret;
144}
145
146-(void)updateColor
147{
148 GLubyte op = sprite_.opacity;
149 ccColor3B c3b = sprite_.color;
150
151 ccColor4B color = { c3b.r, c3b.g, c3b.b, op };
152 if([sprite_.texture hasPremultipliedAlpha]){
153 color.r *= op/255;
154 color.g *= op/255;
155 color.b *= op/255;
156 }
157
158 if(vertexData_){
159 for (int i=0; i < vertexDataCount_; ++i) {
160 vertexData_[i].colors = color;
161 }
162 }
163}
164
165-(void)updateProgress
166{
167 switch (type_) {
168 case kCCProgressTimerTypeRadialCW:
169 case kCCProgressTimerTypeRadialCCW:
170 [self updateRadial];
171 break;
172 case kCCProgressTimerTypeHorizontalBarLR:
173 case kCCProgressTimerTypeHorizontalBarRL:
174 case kCCProgressTimerTypeVerticalBarBT:
175 case kCCProgressTimerTypeVerticalBarTB:
176 [self updateBar];
177 break;
178 default:
179 break;
180 }
181}
182
183///
184// Update does the work of mapping the texture onto the triangles
185// It now doesn't occur the cost of free/alloc data every update cycle.
186// It also only changes the percentage point but no other points if they have not
187// been modified.
188//
189// It now deals with flipped texture. If you run into this problem, just use the
190// sprite property and enable the methods flipX, flipY.
191///
192-(void)updateRadial
193{
194 // Texture Max is the actual max coordinates to deal with non-power of 2 textures
195 CGPoint tMax = ccp(sprite_.texture.maxS,sprite_.texture.maxT);
196
197 // Grab the midpoint
198 CGPoint midpoint = ccpCompMult(self.anchorPoint, tMax);
199
200 float alpha = percentage_ / 100.f;
201
202 // Otherwise we can get the angle from the alpha
203 float angle = 2.f*((float)M_PI) * ( type_ == kCCProgressTimerTypeRadialCW? alpha : 1.f - alpha);
204
205 // We find the vector to do a hit detection based on the percentage
206 // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate
207 // from that by the progress angle around the midpoint pivot
208 CGPoint topMid = ccp(midpoint.x, 0.f);
209 CGPoint percentagePt = ccpRotateByAngle(topMid, midpoint, angle);
210
211
212 int index = 0;
213 CGPoint hit = CGPointZero;
214
215 if (alpha == 0.f) {
216 // More efficient since we don't always need to check intersection
217 // If the alpha is zero then the hit point is top mid and the index is 0.
218 hit = topMid;
219 index = 0;
220 } else if (alpha == 1.f) {
221 // More efficient since we don't always need to check intersection
222 // If the alpha is one then the hit point is top mid and the index is 4.
223 hit = topMid;
224 index = 4;
225 } else {
226 // We run a for loop checking the edges of the texture to find the
227 // intersection point
228 // We loop through five points since the top is split in half
229
230 float min_t = FLT_MAX;
231
232 for (int i = 0; i <= kProgressTextureCoordsCount; ++i) {
233 int pIndex = (i + (kProgressTextureCoordsCount - 1))%kProgressTextureCoordsCount;
234
235 CGPoint edgePtA = ccpCompMult([self boundaryTexCoord:i % kProgressTextureCoordsCount],tMax);
236 CGPoint edgePtB = ccpCompMult([self boundaryTexCoord:pIndex],tMax);
237
238 // Remember that the top edge is split in half for the 12 o'clock position
239 // Let's deal with that here by finding the correct endpoints
240 if(i == 0){
241 edgePtB = ccpLerp(edgePtA,edgePtB,.5f);
242 } else if(i == 4){
243 edgePtA = ccpLerp(edgePtA,edgePtB,.5f);
244 }
245
246 // s and t are returned by ccpLineIntersect
247 float s = 0, t = 0;
248 if(ccpLineIntersect(edgePtA, edgePtB, midpoint, percentagePt, &s, &t))
249 {
250
251 // Since our hit test is on rays we have to deal with the top edge
252 // being in split in half so we have to test as a segment
253 if ((i == 0 || i == 4)) {
254 // s represents the point between edgePtA--edgePtB
255 if (!(0.f <= s && s <= 1.f)) {
256 continue;
257 }
258 }
259 // As long as our t isn't negative we are at least finding a
260 // correct hitpoint from midpoint to percentagePt.
261 if (t >= 0.f) {
262 // Because the percentage line and all the texture edges are
263 // rays we should only account for the shortest intersection
264 if (t < min_t) {
265 min_t = t;
266 index = i;
267 }
268 }
269 }
270 }
271
272 // Now that we have the minimum magnitude we can use that to find our intersection
273 hit = ccpAdd(midpoint, ccpMult(ccpSub(percentagePt, midpoint),min_t));
274
275 }
276
277
278 // The size of the vertex data is the index from the hitpoint
279 // the 3 is for the midpoint, 12 o'clock point and hitpoint position.
280
281 BOOL sameIndexCount = YES;
282 if(vertexDataCount_ != index + 3){
283 sameIndexCount = NO;
284 if(vertexData_){
285 free(vertexData_);
286 vertexData_ = NULL;
287 vertexDataCount_ = 0;
288 }
289 }
290
291
292 if(!vertexData_) {
293 vertexDataCount_ = index + 3;
294 vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4B_T2F));
295 NSAssert( vertexData_, @"CCProgressTimer. Not enough memory");
296
297 [self updateColor];
298 }
299
300 if (!sameIndexCount) {
301
302 // First we populate the array with the midpoint, then all
303 // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint
304 vertexData_[0].texCoords = (ccTex2F){midpoint.x, midpoint.y};
305 vertexData_[0].vertices = [self vertexFromTexCoord:midpoint];
306
307 vertexData_[1].texCoords = (ccTex2F){midpoint.x, 0.f};
308 vertexData_[1].vertices = [self vertexFromTexCoord:ccp(midpoint.x, 0.f)];
309
310 for(int i = 0; i < index; ++i){
311 CGPoint texCoords = ccpCompMult([self boundaryTexCoord:i], tMax);
312
313 vertexData_[i+2].texCoords = (ccTex2F){texCoords.x, texCoords.y};
314 vertexData_[i+2].vertices = [self vertexFromTexCoord:texCoords];
315 }
316
317 // Flip the texture coordinates if set
318 if (sprite_.flipY || sprite_.flipX) {
319 for(int i = 0; i < vertexDataCount_ - 1; ++i){
320 if (sprite_.flipX) {
321 vertexData_[i].texCoords.u = tMax.x - vertexData_[i].texCoords.u;
322 }
323 if(sprite_.flipY){
324 vertexData_[i].texCoords.v = tMax.y - vertexData_[i].texCoords.v;
325 }
326 }
327 }
328 }
329
330 // hitpoint will go last
331 vertexData_[vertexDataCount_ - 1].texCoords = (ccTex2F){hit.x, hit.y};
332 vertexData_[vertexDataCount_ - 1].vertices = [self vertexFromTexCoord:hit];
333
334 if (sprite_.flipY || sprite_.flipX) {
335 if (sprite_.flipX) {
336 vertexData_[vertexDataCount_ - 1].texCoords.u = tMax.x - vertexData_[vertexDataCount_ - 1].texCoords.u;
337 }
338 if(sprite_.flipY){
339 vertexData_[vertexDataCount_ - 1].texCoords.v = tMax.y - vertexData_[vertexDataCount_ - 1].texCoords.v;
340 }
341 }
342}
343
344///
345// Update does the work of mapping the texture onto the triangles for the bar
346// It now doesn't occur the cost of free/alloc data every update cycle.
347// It also only changes the percentage point but no other points if they have not
348// been modified.
349//
350// It now deals with flipped texture. If you run into this problem, just use the
351// sprite property and enable the methods flipX, flipY.
352///
353-(void)updateBar
354{
355
356 float alpha = percentage_ / 100.f;
357
358 CGPoint tMax = ccp(sprite_.texture.maxS,sprite_.texture.maxT);
359
360 unsigned char vIndexes[2] = {0,0};
361 unsigned char index = 0;
362
363 // We know vertex data is always equal to the 4 corners
364 // If we don't have vertex data then we create it here and populate
365 // the side of the bar vertices that won't ever change.
366 if (!vertexData_) {
367 vertexDataCount_ = kProgressTextureCoordsCount;
368 vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4B_T2F));
369 NSAssert( vertexData_, @"CCProgressTimer. Not enough memory");
370
371 if(type_ == kCCProgressTimerTypeHorizontalBarLR){
372 vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0,0};
373 vertexData_[vIndexes[1] = 1].texCoords = (ccTex2F){0, tMax.y};
374 }else if (type_ == kCCProgressTimerTypeHorizontalBarRL) {
375 vertexData_[vIndexes[0] = 2].texCoords = (ccTex2F){tMax.x, tMax.y};
376 vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, 0.f};
377 }else if (type_ == kCCProgressTimerTypeVerticalBarBT) {
378 vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){0, tMax.y};
379 vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, tMax.y};
380 }else if (type_ == kCCProgressTimerTypeVerticalBarTB) {
381 vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0, 0};
382 vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x, 0};
383 }
384
385 index = vIndexes[0];
386 vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)];
387
388 index = vIndexes[1];
389 vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)];
390
391 if (sprite_.flipY || sprite_.flipX) {
392 if (sprite_.flipX) {
393 index = vIndexes[0];
394 vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u;
395 index = vIndexes[1];
396 vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u;
397 }
398 if(sprite_.flipY){
399 index = vIndexes[0];
400 vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v;
401 index = vIndexes[1];
402 vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v;
403 }
404 }
405
406 [self updateColor];
407 }
408
409 if(type_ == kCCProgressTimerTypeHorizontalBarLR){
410 vertexData_[vIndexes[0] = 3].texCoords = (ccTex2F){tMax.x*alpha, tMax.y};
411 vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x*alpha, 0};
412 }else if (type_ == kCCProgressTimerTypeHorizontalBarRL) {
413 vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){tMax.x*(1.f - alpha), 0};
414 vertexData_[vIndexes[1] = 0].texCoords = (ccTex2F){tMax.x*(1.f - alpha), tMax.y};
415 }else if (type_ == kCCProgressTimerTypeVerticalBarBT) {
416 vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0, tMax.y*(1.f - alpha)};
417 vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x, tMax.y*(1.f - alpha)};
418 }else if (type_ == kCCProgressTimerTypeVerticalBarTB) {
419 vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){0, tMax.y*alpha};
420 vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, tMax.y*alpha};
421 }
422
423 index = vIndexes[0];
424 vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)];
425 index = vIndexes[1];
426 vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)];
427
428 if (sprite_.flipY || sprite_.flipX) {
429 if (sprite_.flipX) {
430 index = vIndexes[0];
431 vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u;
432 index = vIndexes[1];
433 vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u;
434 }
435 if(sprite_.flipY){
436 index = vIndexes[0];
437 vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v;
438 index = vIndexes[1];
439 vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v;
440 }
441 }
442
443}
444
445-(CGPoint)boundaryTexCoord:(char)index
446{
447 if (index < kProgressTextureCoordsCount) {
448 switch (type_) {
449 case kCCProgressTimerTypeRadialCW:
450 return ccp((kProgressTextureCoords>>((index<<1)+1))&1,(kProgressTextureCoords>>(index<<1))&1);
451 case kCCProgressTimerTypeRadialCCW:
452 return ccp((kProgressTextureCoords>>(7-(index<<1)))&1,(kProgressTextureCoords>>(7-((index<<1)+1)))&1);
453 default:
454 break;
455 }
456 }
457 return CGPointZero;
458}
459
460-(void)draw
461{
462 [super draw];
463
464 if(!vertexData_)return;
465 if(!sprite_)return;
466 ccBlendFunc blendFunc = sprite_.blendFunc;
467 BOOL newBlend = blendFunc.src != CC_BLEND_SRC || blendFunc.dst != CC_BLEND_DST;
468 if( newBlend )
469 glBlendFunc( blendFunc.src, blendFunc.dst );
470
471 /// ========================================================================
472 // Replaced [texture_ drawAtPoint:CGPointZero] with my own vertexData
473 // Everything above me and below me is copied from CCTextureNode's draw
474 glBindTexture(GL_TEXTURE_2D, sprite_.texture.name);
475 glVertexPointer(2, GL_FLOAT, sizeof(ccV2F_C4B_T2F), &vertexData_[0].vertices);
476 glTexCoordPointer(2, GL_FLOAT, sizeof(ccV2F_C4B_T2F), &vertexData_[0].texCoords);
477 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ccV2F_C4B_T2F), &vertexData_[0].colors);
478 if(type_ == kCCProgressTimerTypeRadialCCW || type_ == kCCProgressTimerTypeRadialCW){
479 glDrawArrays(GL_TRIANGLE_FAN, 0, vertexDataCount_);
480 } else if (type_ == kCCProgressTimerTypeHorizontalBarLR ||
481 type_ == kCCProgressTimerTypeHorizontalBarRL ||
482 type_ == kCCProgressTimerTypeVerticalBarBT ||
483 type_ == kCCProgressTimerTypeVerticalBarTB) {
484 glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexDataCount_);
485 }
486 //glDrawElements(GL_TRIANGLES, indicesCount_, GL_UNSIGNED_BYTE, indices_);
487 /// ========================================================================
488
489 if( newBlend )
490 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
491}
492
493@end
diff --git a/libs/cocos2d/CCProtocols.h b/libs/cocos2d/CCProtocols.h new file mode 100755 index 0000000..f7043fc --- /dev/null +++ b/libs/cocos2d/CCProtocols.h
@@ -0,0 +1,125 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import "ccTypes.h"
28#import "CCTexture2D.h"
29
30#pragma mark -
31#pragma mark CCRGBAProtocol
32
33/// CC RGBA protocol
34@protocol CCRGBAProtocol <NSObject>
35/** sets Color
36 @since v0.8
37 */
38-(void) setColor:(ccColor3B)color;
39/** returns the color
40 @since v0.8
41 */
42-(ccColor3B) color;
43
44/// returns the opacity
45-(GLubyte) opacity;
46/** sets the opacity.
47 @warning If the the texture has premultiplied alpha then, the R, G and B channels will be modifed.
48 Values goes from 0 to 255, where 255 means fully opaque.
49 */
50-(void) setOpacity: (GLubyte) opacity;
51@optional
52/** sets the premultipliedAlphaOpacity property.
53 If set to NO then opacity will be applied as: glColor(R,G,B,opacity);
54 If set to YES then oapcity will be applied as: glColor(opacity, opacity, opacity, opacity );
55 Textures with premultiplied alpha will have this property by default on YES. Otherwise the default value is NO
56 @since v0.8
57 */
58-(void) setOpacityModifyRGB:(BOOL)boolean;
59/** returns whether or not the opacity will be applied using glColor(R,G,B,opacity) or glColor(opacity, opacity, opacity, opacity);
60 @since v0.8
61 */
62 -(BOOL) doesOpacityModifyRGB;
63@end
64
65#pragma mark -
66#pragma mark CCBlendProtocol
67/**
68 You can specify the blending fuction.
69 @since v0.99.0
70 */
71@protocol CCBlendProtocol <NSObject>
72/** set the source blending function for the texture */
73-(void) setBlendFunc:(ccBlendFunc)blendFunc;
74/** returns the blending function used for the texture */
75-(ccBlendFunc) blendFunc;
76@end
77
78
79#pragma mark -
80#pragma mark CCTextureProtocol
81
82/** CCNode objects that uses a Texture2D to render the images.
83 The texture can have a blending function.
84 If the texture has alpha premultiplied the default blending function is:
85 src=GL_ONE dst= GL_ONE_MINUS_SRC_ALPHA
86 else
87 src=GL_SRC_ALPHA dst= GL_ONE_MINUS_SRC_ALPHA
88 But you can change the blending funtion at any time.
89 @since v0.8.0
90 */
91@protocol CCTextureProtocol <CCBlendProtocol>
92/** returns the used texture */
93-(CCTexture2D*) texture;
94/** sets a new texture. it will be retained */
95-(void) setTexture:(CCTexture2D*)texture;
96@end
97
98#pragma mark -
99#pragma mark CCLabelProtocol
100/** Common interface for Labels */
101@protocol CCLabelProtocol <NSObject>
102/** sets a new label using an NSString.
103 The string will be copied.
104 */
105-(void) setString:(NSString*)label;
106/** returns the string that is rendered */
107-(NSString*) string;
108@optional
109/** sets a new label using a CString.
110 It is faster than setString since it doesn't require to alloc/retain/release an NString object.
111 @since v0.99.0
112 */
113-(void) setCString:(char*)label;
114@end
115
116
117#pragma mark -
118#pragma mark CCProjectionProtocol
119/** OpenGL projection protocol */
120@protocol CCProjectionProtocol <NSObject>
121/** Called by CCDirector when the porjection is updated, and "custom" projection is used
122 @since v0.99.5
123 */
124-(void) updateProjection;
125@end
diff --git a/libs/cocos2d/CCRenderTexture.h b/libs/cocos2d/CCRenderTexture.h new file mode 100755 index 0000000..d5e39cc --- /dev/null +++ b/libs/cocos2d/CCRenderTexture.h
@@ -0,0 +1,108 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Foundation/Foundation.h>
27#import "CCNode.h"
28#import "CCSprite.h"
29#import "Support/OpenGL_Internal.h"
30
31#import <Availability.h>
32#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
33#import <UIKit/UIKit.h>
34#endif // iPHone
35
36enum
37{
38 kCCImageFormatJPG = 0,
39 kCCImageFormatPNG = 1,
40 kCCImageFormatRawData =2
41};
42
43
44/**
45 CCRenderTexture is a generic rendering target. To render things into it,
46 simply construct a render target, call begin on it, call visit on any cocos
47 scenes or objects to render them, and call end. For convienience, render texture
48 adds a sprite as it's display child with the results, so you can simply add
49 the render texture to your scene and treat it like any other CocosNode.
50 There are also functions for saving the render texture to disk in PNG or JPG format.
51
52 @since v0.8.1
53 */
54@interface CCRenderTexture : CCNode
55{
56 GLuint fbo_;
57 GLint oldFBO_;
58 CCTexture2D* texture_;
59 CCSprite* sprite_;
60
61 GLenum pixelFormat_;
62}
63
64/** The CCSprite being used.
65 The sprite, by default, will use the following blending function: GL_ONE, GL_ONE_MINUS_SRC_ALPHA.
66 The blending function can be changed in runtime by calling:
67 - [[renderTexture sprite] setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}];
68*/
69@property (nonatomic,readwrite, assign) CCSprite* sprite;
70
71/** creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
72+(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format;
73
74/** creates a RenderTexture object with width and height in Points, pixel format is RGBA8888 */
75+(id)renderTextureWithWidth:(int)w height:(int)h;
76
77/** initializes a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
78-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format;
79
80/** starts grabbing */
81-(void)begin;
82
83/** starts rendering to the texture while clearing the texture first.
84 This is more efficient then calling -clear first and then -begin */
85-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a;
86
87/** ends grabbing */
88-(void)end;
89
90/** clears the texture with a color */
91-(void)clear:(float)r g:(float)g b:(float)b a:(float)a;
92
93#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
94
95/** saves the texture into a file */
96-(BOOL)saveBuffer:(NSString*)name;
97/** saves the texture into a file. The format can be JPG or PNG */
98-(BOOL)saveBuffer:(NSString*)name format:(int)format;
99/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */
100-(NSData*)getUIImageAsDataFromBuffer:(int) format;
101/* get buffer as UIImage */
102-(UIImage *)getUIImageFromBuffer;
103
104#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
105
106@end
107
108
diff --git a/libs/cocos2d/CCRenderTexture.m b/libs/cocos2d/CCRenderTexture.m new file mode 100755 index 0000000..4a4768e --- /dev/null +++ b/libs/cocos2d/CCRenderTexture.m
@@ -0,0 +1,340 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Availability.h>
27#import "CCRenderTexture.h"
28#import "CCDirector.h"
29#import "ccMacros.h"
30#import "Support/ccUtils.h"
31#import "Support/CCFileUtils.h"
32
33@implementation CCRenderTexture
34
35@synthesize sprite=sprite_;
36
37// issue #994
38+(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format
39{
40 return [[[self alloc] initWithWidth:w height:h pixelFormat:format] autorelease];
41}
42
43+(id)renderTextureWithWidth:(int)w height:(int)h
44{
45 return [[[self alloc] initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888] autorelease];
46}
47
48-(id)initWithWidth:(int)w height:(int)h
49{
50 return [self initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888];
51}
52
53-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format
54{
55 if ((self = [super init]))
56 {
57 NSAssert(format != kCCTexture2DPixelFormat_A8,@"only RGB and RGBA formats are valid for a render texture");
58
59 w *= CC_CONTENT_SCALE_FACTOR();
60 h *= CC_CONTENT_SCALE_FACTOR();
61
62 glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_);
63
64 // textures must be power of two
65 NSUInteger powW = ccNextPOT(w);
66 NSUInteger powH = ccNextPOT(h);
67
68 void *data = malloc((int)(powW * powH * 4));
69 memset(data, 0, (int)(powW * powH * 4));
70 pixelFormat_=format;
71
72 texture_ = [[CCTexture2D alloc] initWithData:data pixelFormat:pixelFormat_ pixelsWide:powW pixelsHigh:powH contentSize:CGSizeMake(w, h)];
73 free( data );
74
75 // generate FBO
76 ccglGenFramebuffers(1, &fbo_);
77 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);
78
79 // associate texture with FBO
80 ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_.name, 0);
81
82 // check if it worked (probably worth doing :) )
83 GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER);
84 if (status != CC_GL_FRAMEBUFFER_COMPLETE)
85 {
86 [NSException raise:@"Render Texture" format:@"Could not attach texture to framebuffer"];
87 }
88 [texture_ setAliasTexParameters];
89
90 sprite_ = [CCSprite spriteWithTexture:texture_];
91
92 [texture_ release];
93 [sprite_ setScaleY:-1];
94 [self addChild:sprite_];
95
96 // issue #937
97 [sprite_ setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}];
98
99 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO_);
100 }
101 return self;
102}
103
104-(void)dealloc
105{
106// [self removeAllChildrenWithCleanup:YES];
107 ccglDeleteFramebuffers(1, &fbo_);
108 [super dealloc];
109}
110
111-(void)begin
112{
113 // Save the current matrix
114 glPushMatrix();
115
116 CGSize texSize = [texture_ contentSizeInPixels];
117
118
119 // Calculate the adjustment ratios based on the old and new projections
120 CGSize size = [[CCDirector sharedDirector] displaySizeInPixels];
121 float widthRatio = size.width / texSize.width;
122 float heightRatio = size.height / texSize.height;
123
124
125 // Adjust the orthographic propjection and viewport
126 ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1);
127 glViewport(0, 0, texSize.width, texSize.height);
128
129
130 glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_);
131 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);//Will direct drawing to the frame buffer created above
132
133 // Issue #1145
134 // There is no need to enable the default GL states here
135 // but since CCRenderTexture is mostly used outside the "render" loop
136 // these states needs to be enabled.
137 // Since this bug was discovered in API-freeze (very close of 1.0 release)
138 // This bug won't be fixed to prevent incompatibilities with code.
139 //
140 // If you understand the above mentioned message, then you can comment the following line
141 // and enable the gl states manually, in case you need them.
142 CC_ENABLE_DEFAULT_GL_STATES();
143}
144
145-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a
146{
147 [self begin];
148
149 // save clear color
150 GLfloat clearColor[4];
151 glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor);
152
153 glClearColor(r, g, b, a);
154 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
155
156 // restore clear color
157 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
158}
159
160-(void)end
161{
162 ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO_);
163 // Restore the original matrix and viewport
164 glPopMatrix();
165 CGSize size = [[CCDirector sharedDirector] displaySizeInPixels];
166 glViewport(0, 0, size.width, size.height);
167}
168
169-(void)clear:(float)r g:(float)g b:(float)b a:(float)a
170{
171 [self beginWithClear:r g:g b:b a:a];
172 [self end];
173}
174
175#pragma mark RenderTexture - Save Image
176
177#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
178-(BOOL)saveBuffer:(NSString*)name
179{
180 return [self saveBuffer:name format:kCCImageFormatJPG];
181}
182
183-(BOOL)saveBuffer:(NSString*)fileName format:(int)format
184{
185 NSString *fullPath = [CCFileUtils fullPathFromRelativePath:fileName];
186
187 NSData *data = [self getUIImageAsDataFromBuffer:format];
188
189 return [data writeToFile:fullPath atomically:YES];
190}
191
192/* get buffer as UIImage */
193-(UIImage *)getUIImageFromBuffer
194{
195 NSAssert(pixelFormat_ == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image");
196
197 CGSize s = [texture_ contentSizeInPixels];
198 int tx = s.width;
199 int ty = s.height;
200
201 int bitsPerComponent = 8;
202 int bitsPerPixel = 32;
203 int bytesPerPixel = (bitsPerComponent * 4)/8;
204 int bytesPerRow = bytesPerPixel * tx;
205 NSInteger myDataLength = bytesPerRow * ty;
206
207 NSMutableData *buffer = [[NSMutableData alloc] initWithCapacity:myDataLength];
208 NSMutableData *pixels = [[NSMutableData alloc] initWithCapacity:myDataLength];
209
210 if( ! (buffer && pixels) ) {
211 CCLOG(@"cocos2d: CCRenderTexture#getUIImageFromBuffer: not enough memory");
212 [buffer release];
213 [pixels release];
214 return nil;
215 }
216
217 [self begin];
218 glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, [buffer mutableBytes]);
219 [self end];
220
221 // make data provider with data.
222
223 CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
224 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, [buffer mutableBytes], myDataLength, NULL);
225 CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
226 CGImageRef iref = CGImageCreate(tx, ty,
227 bitsPerComponent, bitsPerPixel, bytesPerRow,
228 colorSpaceRef, bitmapInfo, provider,
229 NULL, false,
230 kCGRenderingIntentDefault);
231
232 CGContextRef context = CGBitmapContextCreate([pixels mutableBytes], tx,
233 ty, CGImageGetBitsPerComponent(iref),
234 CGImageGetBytesPerRow(iref), CGImageGetColorSpace(iref),
235 bitmapInfo);
236 CGContextTranslateCTM(context, 0.0f, ty);
237 CGContextScaleCTM(context, 1.0f, -1.0f);
238 CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, tx, ty), iref);
239 CGImageRef outputRef = CGBitmapContextCreateImage(context);
240 UIImage* image = [[UIImage alloc] initWithCGImage:outputRef];
241
242 CGImageRelease(iref);
243 CGContextRelease(context);
244 CGColorSpaceRelease(colorSpaceRef);
245 CGDataProviderRelease(provider);
246 CGImageRelease(outputRef);
247
248 [pixels release];
249 [buffer release];
250
251 return [image autorelease];
252}
253
254-(NSData*)getUIImageAsDataFromBuffer:(int) format
255{
256 NSAssert(pixelFormat_ == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image");
257
258 CGSize s = [texture_ contentSizeInPixels];
259 int tx = s.width;
260 int ty = s.height;
261
262 int bitsPerComponent=8;
263 int bitsPerPixel=32;
264
265 int bytesPerRow = (bitsPerPixel/8) * tx;
266 NSInteger myDataLength = bytesPerRow * ty;
267
268 GLubyte *buffer = malloc(sizeof(GLubyte)*myDataLength);
269 GLubyte *pixels = malloc(sizeof(GLubyte)*myDataLength);
270
271 if( ! (buffer && pixels) ) {
272 CCLOG(@"cocos2d: CCRenderTexture#getUIImageFromBuffer: not enough memory");
273 free(buffer);
274 free(pixels);
275 return nil;
276 }
277
278 [self begin];
279 glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, buffer);
280 [self end];
281
282 int x,y;
283
284 for(y = 0; y <ty; y++) {
285 for(x = 0; x <tx * 4; x++) {
286 pixels[((ty - 1 - y) * tx * 4 + x)] = buffer[(y * 4 * tx + x)];
287 }
288 }
289
290 NSData* data;
291
292 if (format == kCCImageFormatRawData)
293 {
294 free(buffer);
295 //data frees buffer when it is deallocated
296 data = [NSData dataWithBytesNoCopy:pixels length:myDataLength];
297
298 } else {
299
300 /*
301 CGImageCreate(size_t width, size_t height,
302 size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
303 CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,
304 const CGFloat decode[], bool shouldInterpolate,
305 CGColorRenderingIntent intent)
306 */
307 // make data provider with data.
308 CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
309 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, myDataLength, NULL);
310 CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
311 CGImageRef iref = CGImageCreate(tx, ty,
312 bitsPerComponent, bitsPerPixel, bytesPerRow,
313 colorSpaceRef, bitmapInfo, provider,
314 NULL, false,
315 kCGRenderingIntentDefault);
316
317 UIImage* image = [[UIImage alloc] initWithCGImage:iref];
318
319 CGImageRelease(iref);
320 CGColorSpaceRelease(colorSpaceRef);
321 CGDataProviderRelease(provider);
322
323
324
325 if (format == kCCImageFormatPNG)
326 data = UIImagePNGRepresentation(image);
327 else
328 data = UIImageJPEGRepresentation(image, 1.0f);
329
330 [image release];
331
332 free(pixels);
333 free(buffer);
334 }
335
336 return data;
337}
338
339#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
340@end
diff --git a/libs/cocos2d/CCRibbon.h b/libs/cocos2d/CCRibbon.h new file mode 100755 index 0000000..53898e6 --- /dev/null +++ b/libs/cocos2d/CCRibbon.h
@@ -0,0 +1,117 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008, 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCNode.h"
28#import "CCTexture2D.h"
29#import "CCProtocols.h"
30#import "Platforms/CCGL.h"
31
32/**
33 * A CCRibbon is a dynamically generated list of polygons drawn as a single or series
34 * of triangle strips. The primary use of CCRibbon is as the drawing class of Motion Streak,
35 * but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
36 * and pass in the parameters for the next location in the ribbon. The system will automatically
37 * generate new polygons, texture them accourding to your texture width, etc, etc.
38 *
39 * CCRibbon data is stored in a CCRibbonSegment class. This class statically allocates enough verticies and
40 * texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
41 * new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
42 * allocating new memory and prefer a more static method. However, since there is no way to determine
43 * the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
44 *
45 * @since v0.8.1
46 */
47@interface CCRibbon : CCNode <CCTextureProtocol>
48{
49 NSMutableArray* segments_;
50 NSMutableArray* deletedSegments_;
51
52 CGPoint lastPoint1_;
53 CGPoint lastPoint2_;
54 CGPoint lastLocation_;
55 int vertCount_;
56 float texVPos_;
57 float curTime_;
58 float fadeTime_;
59 float delta_;
60 float lastWidth_;
61 float lastSign_;
62 BOOL pastFirstPoint_;
63
64 // Texture used
65 CCTexture2D* texture_;
66
67 // texture length
68 float textureLength_;
69
70 // RGBA protocol
71 ccColor4B color_;
72
73 // blend func
74 ccBlendFunc blendFunc_;
75}
76
77/** Texture used by the ribbon. Conforms to CCTextureProtocol protocol */
78@property (nonatomic,readwrite,retain) CCTexture2D* texture;
79
80/** Texture lengths in pixels */
81@property (nonatomic,readwrite) float textureLength;
82
83/** GL blendind function */
84@property (nonatomic,readwrite,assign) ccBlendFunc blendFunc;
85
86/** color used by the Ribbon (RGBA) */
87@property (nonatomic,readwrite) ccColor4B color;
88
89/** creates the ribbon */
90+(id)ribbonWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade;
91/** init the ribbon */
92-(id)initWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade;
93/** add a point to the ribbon */
94-(void)addPointAt:(CGPoint)location width:(float)w;
95/** polling function */
96-(void)update:(ccTime)delta;
97/** determine side of line */
98-(float)sideOfLine:(CGPoint)p l1:(CGPoint)l1 l2:(CGPoint)l2;
99
100@end
101
102/** object to hold ribbon segment data */
103@interface CCRibbonSegment : NSObject
104{
105@public
106 GLfloat verts[50*6];
107 GLfloat coords[50*4];
108 GLubyte colors[50*8];
109 float creationTime[50];
110 BOOL finished;
111 uint end;
112 uint begin;
113}
114-(id)init;
115-(void)reset;
116-(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color;
117@end
diff --git a/libs/cocos2d/CCRibbon.m b/libs/cocos2d/CCRibbon.m new file mode 100755 index 0000000..2d9acaa --- /dev/null +++ b/libs/cocos2d/CCRibbon.m
@@ -0,0 +1,383 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008, 2009 Jason Booth
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25/*
26 * A ribbon is a dynamically generated list of polygons drawn as a single or series
27 * of triangle strips. The primary use of Ribbon is as the drawing class of Motion Streak,
28 * but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
29 * and pass in the parameters for the next location in the ribbon. The system will automatically
30 * generate new polygons, texture them accourding to your texture width, etc, etc.
31 *
32 * Ribbon data is stored in a RibbonSegment class. This class statically allocates enough verticies and
33 * texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
34 * new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
35 * allocating new memory and prefer a more static method. However, since there is no way to determine
36 * the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
37 *
38 */
39
40
41#import "CCRibbon.h"
42#import "CCTextureCache.h"
43#import "Support/CGPointExtension.h"
44#import "ccMacros.h"
45
46//
47// Ribbon
48//
49@implementation CCRibbon
50@synthesize blendFunc=blendFunc_;
51@synthesize color=color_;
52@synthesize textureLength = textureLength_;
53
54+(id)ribbonWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade
55{
56 self = [[[self alloc] initWithWidth:w image:path length:l color:color fade:fade] autorelease];
57 return self;
58}
59
60-(id)initWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade
61{
62 self = [super init];
63 if (self)
64 {
65
66 segments_ = [[NSMutableArray alloc] init];
67 deletedSegments_ = [[NSMutableArray alloc] init];
68
69 /* 1 initial segment */
70 CCRibbonSegment* seg = [[CCRibbonSegment alloc] init];
71 [segments_ addObject:seg];
72 [seg release];
73
74 textureLength_ = l;
75
76 color_ = color;
77 fadeTime_ = fade;
78 lastLocation_ = CGPointZero;
79 lastWidth_ = w/2;
80 texVPos_ = 0.0f;
81
82 curTime_ = 0;
83 pastFirstPoint_ = NO;
84
85 /* XXX:
86 Ribbon, by default uses this blend function, which might not be correct
87 if you are using premultiplied alpha images,
88 but 99% you might want to use this blending function regarding of the texture
89 */
90 blendFunc_.src = GL_SRC_ALPHA;
91 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
92
93 self.texture = [[CCTextureCache sharedTextureCache] addImage:path];
94
95 /* default texture parameter */
96 ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
97 [texture_ setTexParameters:&params];
98 }
99 return self;
100}
101
102-(void)dealloc
103{
104 [segments_ release];
105 [deletedSegments_ release];
106 [texture_ release];
107 [super dealloc];
108}
109
110// rotates a point around 0, 0
111-(CGPoint)rotatePoint:(CGPoint)vec rotation:(float)a
112{
113 float xtemp = (vec.x * cosf(a)) - (vec.y * sinf(a));
114 vec.y = (vec.x * sinf(a)) + (vec.y * cosf(a));
115 vec.x = xtemp;
116 return vec;
117}
118
119-(void)update:(ccTime)delta
120{
121 curTime_+= delta;
122 delta_ = delta;
123}
124
125-(float)sideOfLine:(CGPoint)p l1:(CGPoint)l1 l2:(CGPoint)l2
126{
127 CGPoint vp = ccpPerp(ccpSub(l1, l2));
128 CGPoint vx = ccpSub(p, l1);
129 return ccpDot(vx, vp);
130}
131
132// adds a new segment to the ribbon
133-(void)addPointAt:(CGPoint)location width:(float)w
134{
135 location.x *= CC_CONTENT_SCALE_FACTOR();
136 location.y *= CC_CONTENT_SCALE_FACTOR();
137
138 w = w*0.5f;
139 // if this is the first point added, cache it and return
140 if (!pastFirstPoint_)
141 {
142 lastWidth_ = w;
143 lastLocation_ = location;
144 pastFirstPoint_ = YES;
145 return;
146 }
147
148 CGPoint sub = ccpSub(lastLocation_, location);
149 float r = ccpToAngle(sub) + (float)M_PI_2;
150 CGPoint p1 = ccpAdd([self rotatePoint:ccp(-w, 0) rotation:r], location);
151 CGPoint p2 = ccpAdd([self rotatePoint:ccp(w, 0) rotation:r], location);
152 float len = sqrtf(powf(lastLocation_.x - location.x, 2) + powf(lastLocation_.y - location.y, 2));
153 float tend = texVPos_ + len/textureLength_;
154 CCRibbonSegment* seg;
155 // grab last segment
156 seg = [segments_ lastObject];
157 // lets kill old segments
158 for (CCRibbonSegment* seg2 in segments_)
159 {
160 if (seg2 != seg && seg2->finished)
161 {
162 [deletedSegments_ addObject:seg2];
163 }
164 }
165 [segments_ removeObjectsInArray:deletedSegments_];
166 // is the segment full?
167 if (seg->end >= 50)
168 [segments_ removeObjectsInArray:deletedSegments_];
169 // grab last segment and append to it if it's not full
170 seg = [segments_ lastObject];
171 // is the segment full?
172 if (seg->end >= 50)
173 {
174 CCRibbonSegment* newSeg;
175 // grab it from the cache if we can
176 if ([deletedSegments_ count] > 0)
177 {
178 newSeg = [deletedSegments_ objectAtIndex:0];
179 [newSeg retain]; // will be released later
180 [deletedSegments_ removeObject:newSeg];
181 [newSeg reset];
182 }
183 else
184 {
185 newSeg = [[CCRibbonSegment alloc] init]; // will be released later
186 }
187
188 newSeg->creationTime[0] = seg->creationTime[seg->end - 1];
189 int v = (seg->end-1)*6;
190 int c = (seg->end-1)*4;
191 newSeg->verts[0] = seg->verts[v];
192 newSeg->verts[1] = seg->verts[v+1];
193 newSeg->verts[2] = seg->verts[v+2];
194 newSeg->verts[3] = seg->verts[v+3];
195 newSeg->verts[4] = seg->verts[v+4];
196 newSeg->verts[5] = seg->verts[v+5];
197
198 newSeg->coords[0] = seg->coords[c];
199 newSeg->coords[1] = seg->coords[c+1];
200 newSeg->coords[2] = seg->coords[c+2];
201 newSeg->coords[3] = seg->coords[c+3];
202 newSeg->end++;
203 seg = newSeg;
204 [segments_ addObject:seg];
205 [newSeg release]; // it was retained before
206
207 }
208 if (seg->end == 0)
209 {
210 // first edge has to get rotation from the first real polygon
211 CGPoint lp1 = ccpAdd([self rotatePoint:ccp(-lastWidth_, 0) rotation:r], lastLocation_);
212 CGPoint lp2 = ccpAdd([self rotatePoint:ccp(+lastWidth_, 0) rotation:r], lastLocation_);
213 seg->creationTime[0] = curTime_ - delta_;
214 seg->verts[0] = lp1.x;
215 seg->verts[1] = lp1.y;
216 seg->verts[2] = 0.0f;
217 seg->verts[3] = lp2.x;
218 seg->verts[4] = lp2.y;
219 seg->verts[5] = 0.0f;
220 seg->coords[0] = 0.0f;
221 seg->coords[1] = texVPos_;
222 seg->coords[2] = 1.0f;
223 seg->coords[3] = texVPos_;
224 seg->end++;
225 }
226
227 int v = seg->end*6;
228 int c = seg->end*4;
229 // add new vertex
230 seg->creationTime[seg->end] = curTime_;
231 seg->verts[v] = p1.x;
232 seg->verts[v+1] = p1.y;
233 seg->verts[v+2] = 0.0f;
234 seg->verts[v+3] = p2.x;
235 seg->verts[v+4] = p2.y;
236 seg->verts[v+5] = 0.0f;
237
238
239 seg->coords[c] = 0.0f;
240 seg->coords[c+1] = tend;
241 seg->coords[c+2] = 1.0f;
242 seg->coords[c+3] = tend;
243
244 texVPos_ = tend;
245 lastLocation_ = location;
246 lastPoint1_ = p1;
247 lastPoint2_ = p2;
248 lastWidth_ = w;
249 seg->end++;
250}
251
252-(void) draw
253{
254 [super draw];
255
256 if ([segments_ count] > 0)
257 {
258 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
259 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
260 // Unneeded states: GL_COLOR_ARRAY
261 glDisableClientState(GL_COLOR_ARRAY);
262
263 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
264
265 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
266 if( newBlend )
267 glBlendFunc( blendFunc_.src, blendFunc_.dst );
268
269 for (CCRibbonSegment* seg in segments_)
270 [seg draw:curTime_ fadeTime:fadeTime_ color:color_];
271
272 if( newBlend )
273 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
274
275 // restore default GL state
276 glEnableClientState( GL_COLOR_ARRAY );
277 }
278}
279
280#pragma mark Ribbon - CocosNodeTexture protocol
281-(void) setTexture:(CCTexture2D*) texture
282{
283 [texture_ release];
284 texture_ = [texture retain];
285 [self setContentSizeInPixels: texture.contentSizeInPixels];
286 /* XXX Don't update blending function in Ribbons */
287}
288
289-(CCTexture2D*) texture
290{
291 return texture_;
292}
293
294@end
295
296
297#pragma mark -
298#pragma mark RibbonSegment
299
300@implementation CCRibbonSegment
301
302-(id)init
303{
304 self = [super init];
305 if (self)
306 {
307 [self reset];
308 }
309 return self;
310}
311
312- (NSString*) description
313{
314 return [NSString stringWithFormat:@"<%@ = %08X | end = %i, begin = %i>", [self class], self, end, begin];
315}
316
317- (void) dealloc
318{
319 CCLOGINFO(@"cocos2d: deallocing %@", self);
320 [super dealloc];
321}
322
323-(void)reset
324{
325 end = 0;
326 begin = 0;
327 finished = NO;
328}
329
330-(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color
331{
332 GLubyte r = color.r;
333 GLubyte g = color.g;
334 GLubyte b = color.b;
335 GLubyte a = color.a;
336
337 if (begin < 50)
338 {
339 // the motion streak class will call update and cause time to change, thus, if curTime_ != 0
340 // we have to generate alpha for the ribbon each frame.
341 if (curTime == 0)
342 {
343 // no alpha over time, so just set the color
344 glColor4ub(r,g,b,a);
345 }
346 else
347 {
348 // generate alpha/color for each point
349 glEnableClientState(GL_COLOR_ARRAY);
350 uint i = begin;
351 for (; i < end; ++i)
352 {
353 int idx = i*8;
354 colors[idx] = r;
355 colors[idx+1] = g;
356 colors[idx+2] = b;
357 colors[idx+4] = r;
358 colors[idx+5] = g;
359 colors[idx+6] = b;
360 float alive = ((curTime - creationTime[i]) / fadeTime);
361 if (alive > 1)
362 {
363 begin++;
364 colors[idx+3] = 0;
365 colors[idx+7] = 0;
366 }
367 else
368 {
369 colors[idx+3] = (GLubyte)(255.f - (alive * 255.f));
370 colors[idx+7] = colors[idx+3];
371 }
372 }
373 glColorPointer(4, GL_UNSIGNED_BYTE, 0, &colors[begin*8]);
374 }
375 glVertexPointer(3, GL_FLOAT, 0, &verts[begin*6]);
376 glTexCoordPointer(2, GL_FLOAT, 0, &coords[begin*4]);
377 glDrawArrays(GL_TRIANGLE_STRIP, 0, (end - begin) * 2);
378 }
379 else
380 finished = YES;
381}
382@end
383
diff --git a/libs/cocos2d/CCScene.h b/libs/cocos2d/CCScene.h new file mode 100755 index 0000000..1d104bc --- /dev/null +++ b/libs/cocos2d/CCScene.h
@@ -0,0 +1,43 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCNode.h"
29
30/** CCScene is a subclass of CCNode that is used only as an abstract concept.
31
32 CCScene an CCNode are almost identical with the difference that CCScene has it's
33 anchor point (by default) at the center of the screen.
34
35 For the moment CCScene has no other logic than that, but in future releases it might have
36 additional logic.
37
38 It is a good practice to use and CCScene as the parent of all your nodes.
39*/
40@interface CCScene : CCNode
41{
42}
43@end
diff --git a/libs/cocos2d/CCScene.m b/libs/cocos2d/CCScene.m new file mode 100755 index 0000000..e991d6e --- /dev/null +++ b/libs/cocos2d/CCScene.m
@@ -0,0 +1,45 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCScene.h"
29#import "Support/CGPointExtension.h"
30#import "CCDirector.h"
31
32
33@implementation CCScene
34-(id) init
35{
36 if( (self=[super init]) ) {
37 CGSize s = [[CCDirector sharedDirector] winSize];
38 self.isRelativeAnchorPoint = NO;
39 anchorPoint_ = ccp(0.5f, 0.5f);
40 [self setContentSize:s];
41 }
42
43 return self;
44}
45@end
diff --git a/libs/cocos2d/CCScheduler.h b/libs/cocos2d/CCScheduler.h new file mode 100755 index 0000000..122b8fe --- /dev/null +++ b/libs/cocos2d/CCScheduler.h
@@ -0,0 +1,199 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27
28#import "Support/uthash.h"
29#import "ccTypes.h"
30
31typedef void (*TICK_IMP)(id, SEL, ccTime);
32
33//
34// CCTimer
35//
36/** Light weight timer */
37@interface CCTimer : NSObject
38{
39 id target;
40 TICK_IMP impMethod;
41
42 ccTime elapsed;
43
44@public // optimization
45 ccTime interval;
46 SEL selector;
47}
48
49/** interval in seconds */
50@property (nonatomic,readwrite,assign) ccTime interval;
51
52/** Allocates a timer with a target and a selector.
53*/
54+(id) timerWithTarget:(id) t selector:(SEL)s;
55
56/** Allocates a timer with a target, a selector and an interval in seconds.
57*/
58+(id) timerWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds;
59
60/** Initializes a timer with a target and a selector.
61*/
62 -(id) initWithTarget:(id) t selector:(SEL)s;
63
64/** Initializes a timer with a target, a selector and an interval in seconds.
65*/
66-(id) initWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds;
67
68
69/** triggers the timer */
70-(void) update: (ccTime) dt;
71@end
72
73
74
75//
76// CCScheduler
77//
78/** Scheduler is responsible of triggering the scheduled callbacks.
79 You should not use NSTimer. Instead use this class.
80
81 There are 2 different types of callbacks (selectors):
82
83 - update selector: the 'update' selector will be called every frame. You can customize the priority.
84 - custom selector: A custom selector will be called every frame, or with a custom interval of time
85
86 The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update selector'.
87
88*/
89
90struct _listEntry;
91struct _hashSelectorEntry;
92struct _hashUpdateEntry;
93
94@interface CCScheduler : NSObject
95{
96 ccTime timeScale_;
97
98 //
99 // "updates with priority" stuff
100 //
101 struct _listEntry *updatesNeg; // list of priority < 0
102 struct _listEntry *updates0; // list priority == 0
103 struct _listEntry *updatesPos; // list priority > 0
104 struct _hashUpdateEntry *hashForUpdates; // hash used to fetch quickly the list entries for pause,delete,etc.
105
106 // Used for "selectors with interval"
107 struct _hashSelectorEntry *hashForSelectors;
108 struct _hashSelectorEntry *currentTarget;
109 BOOL currentTargetSalvaged;
110
111 // Optimization
112 TICK_IMP impMethod;
113 SEL updateSelector;
114
115 BOOL updateHashLocked; // If true unschedule will not remove anything from a hash. Elements will only be marked for deletion.
116}
117
118/** Modifies the time of all scheduled callbacks.
119 You can use this property to create a 'slow motion' or 'fast fordward' effect.
120 Default is 1.0. To create a 'slow motion' effect, use values below 1.0.
121 To create a 'fast fordward' effect, use values higher than 1.0.
122 @since v0.8
123 @warning It will affect EVERY scheduled selector / action.
124 */
125@property (nonatomic,readwrite) ccTime timeScale;
126
127/** returns a shared instance of the Scheduler */
128+(CCScheduler *)sharedScheduler;
129
130/** purges the shared scheduler. It releases the retained instance.
131 @since v0.99.0
132 */
133+(void)purgeSharedScheduler;
134
135/** 'tick' the scheduler.
136 You should NEVER call this method, unless you know what you are doing.
137 */
138-(void) tick:(ccTime)dt;
139
140/** The scheduled method will be called every 'interval' seconds.
141 If paused is YES, then it won't be called until it is resumed.
142 If 'interval' is 0, it will be called every frame, but if so, it recommened to use 'scheduleUpdateForTarget:' instead.
143 If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
144
145 @since v0.99.3
146 */
147-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused;
148
149/** Schedules the 'update' selector for a given target with a given priority.
150 The 'update' selector will be called every frame.
151 The lower the priority, the earlier it is called.
152 @since v0.99.3
153 */
154-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused;
155
156/** Unshedules a selector for a given target.
157 If you want to unschedule the "update", use unscheudleUpdateForTarget.
158 @since v0.99.3
159 */
160-(void) unscheduleSelector:(SEL)selector forTarget:(id)target;
161
162/** Unschedules the update selector for a given target
163 @since v0.99.3
164 */
165-(void) unscheduleUpdateForTarget:(id)target;
166
167/** Unschedules all selectors for a given target.
168 This also includes the "update" selector.
169 @since v0.99.3
170 */
171-(void) unscheduleAllSelectorsForTarget:(id)target;
172
173/** Unschedules all selectors from all targets.
174 You should NEVER call this method, unless you know what you are doing.
175
176 @since v0.99.3
177 */
178-(void) unscheduleAllSelectors;
179
180/** Pauses the target.
181 All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.
182 If the target is not present, nothing happens.
183 @since v0.99.3
184 */
185-(void) pauseTarget:(id)target;
186
187/** Resumes the target.
188 The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.
189 If the target is not present, nothing happens.
190 @since v0.99.3
191 */
192-(void) resumeTarget:(id)target;
193
194/** Returns whether or not the target is paused
195 @since v1.0.0
196 */
197-(BOOL) isTargetPaused:(id)target;
198
199@end
diff --git a/libs/cocos2d/CCScheduler.m b/libs/cocos2d/CCScheduler.m new file mode 100755 index 0000000..a14ca10 --- /dev/null +++ b/libs/cocos2d/CCScheduler.m
@@ -0,0 +1,657 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27// cocos2d imports
28#import "CCScheduler.h"
29#import "ccMacros.h"
30#import "Support/uthash.h"
31#import "Support/utlist.h"
32#import "Support/ccCArray.h"
33
34//
35// Data structures
36//
37#pragma mark -
38#pragma mark Data Structures
39
40// A list double-linked list used for "updates with priority"
41typedef struct _listEntry
42{
43 struct _listEntry *prev, *next;
44 TICK_IMP impMethod;
45 id target; // not retained (retained by hashUpdateEntry)
46 NSInteger priority;
47 BOOL paused;
48 BOOL markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick
49} tListEntry;
50
51typedef struct _hashUpdateEntry
52{
53 tListEntry **list; // Which list does it belong to ?
54 tListEntry *entry; // entry in the list
55 id target; // hash key (retained)
56 UT_hash_handle hh;
57} tHashUpdateEntry;
58
59// Hash Element used for "selectors with interval"
60typedef struct _hashSelectorEntry
61{
62 struct ccArray *timers;
63 id target; // hash key (retained)
64 unsigned int timerIndex;
65 CCTimer *currentTimer;
66 BOOL currentTimerSalvaged;
67 BOOL paused;
68 UT_hash_handle hh;
69} tHashSelectorEntry;
70
71
72
73//
74// CCTimer
75//
76#pragma mark -
77#pragma mark - CCTimer
78
79@implementation CCTimer
80
81@synthesize interval;
82
83-(id) init
84{
85 NSAssert(NO, @"CCTimer: Init not supported.");
86 [self release];
87 return nil;
88}
89
90+(id) timerWithTarget:(id)t selector:(SEL)s
91{
92 return [[[self alloc] initWithTarget:t selector:s] autorelease];
93}
94
95+(id) timerWithTarget:(id)t selector:(SEL)s interval:(ccTime) i
96{
97 return [[[self alloc] initWithTarget:t selector:s interval:i] autorelease];
98}
99
100-(id) initWithTarget:(id)t selector:(SEL)s
101{
102 return [self initWithTarget:t selector:s interval:0];
103}
104
105-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds
106{
107 if( (self=[super init]) ) {
108#if COCOS2D_DEBUG
109 NSMethodSignature *sig = [t methodSignatureForSelector:s];
110 NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt");
111#endif
112
113 // target is not retained. It is retained in the hash structure
114 target = t;
115 selector = s;
116 impMethod = (TICK_IMP) [t methodForSelector:s];
117 elapsed = -1;
118 interval = seconds;
119 }
120 return self;
121}
122
123- (NSString*) description
124{
125 return [NSString stringWithFormat:@"<%@ = %08X | target:%@ selector:(%@)>", [self class], self, [target class], NSStringFromSelector(selector)];
126}
127
128-(void) dealloc
129{
130 CCLOGINFO(@"cocos2d: deallocing %@", self);
131 [super dealloc];
132}
133
134-(void) update: (ccTime) dt
135{
136 if( elapsed == - 1)
137 elapsed = 0;
138 else
139 elapsed += dt;
140 if( elapsed >= interval ) {
141 impMethod(target, selector, elapsed);
142 elapsed = 0;
143 }
144}
145@end
146
147//
148// CCScheduler
149//
150#pragma mark -
151#pragma mark - CCScheduler
152
153@interface CCScheduler (Private)
154-(void) removeHashElement:(tHashSelectorEntry*)element;
155@end
156
157@implementation CCScheduler
158
159static CCScheduler *sharedScheduler;
160
161@synthesize timeScale = timeScale_;
162
163+ (CCScheduler *)sharedScheduler
164{
165 if (!sharedScheduler)
166 sharedScheduler = [[CCScheduler alloc] init];
167
168 return sharedScheduler;
169}
170
171+(id)alloc
172{
173 NSAssert(sharedScheduler == nil, @"Attempted to allocate a second instance of a singleton.");
174 return [super alloc];
175}
176
177+(void)purgeSharedScheduler
178{
179 [sharedScheduler release];
180 sharedScheduler = nil;
181}
182
183- (id) init
184{
185 if( (self=[super init]) ) {
186 timeScale_ = 1.0f;
187
188 // used to trigger CCTimer#update
189 updateSelector = @selector(update:);
190 impMethod = (TICK_IMP) [CCTimer instanceMethodForSelector:updateSelector];
191
192 // updates with priority
193 updates0 = NULL;
194 updatesNeg = NULL;
195 updatesPos = NULL;
196 hashForUpdates = NULL;
197
198 // selectors with interval
199 currentTarget = nil;
200 currentTargetSalvaged = NO;
201 hashForSelectors = nil;
202 updateHashLocked = NO;
203 }
204
205 return self;
206}
207
208- (void) dealloc
209{
210 CCLOG(@"cocos2d: deallocing %@", self);
211
212 [self unscheduleAllSelectors];
213
214 sharedScheduler = nil;
215
216 [super dealloc];
217}
218
219
220#pragma mark CCScheduler - Custom Selectors
221
222-(void) removeHashElement:(tHashSelectorEntry*)element
223{
224 ccArrayFree(element->timers);
225 [element->target release];
226 HASH_DEL(hashForSelectors, element);
227 free(element);
228}
229
230-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused
231{
232 NSAssert( selector != nil, @"Argument selector must be non-nil");
233 NSAssert( target != nil, @"Argument target must be non-nil");
234
235 tHashSelectorEntry *element = NULL;
236 HASH_FIND_INT(hashForSelectors, &target, element);
237
238 if( ! element ) {
239 element = calloc( sizeof( *element ), 1 );
240 element->target = [target retain];
241 HASH_ADD_INT( hashForSelectors, target, element );
242
243 // Is this the 1st element ? Then set the pause level to all the selectors of this target
244 element->paused = paused;
245
246 } else
247 NSAssert( element->paused == paused, @"CCScheduler. Trying to schedule a selector with a pause value different than the target");
248
249
250 if( element->timers == nil )
251 element->timers = ccArrayNew(10);
252 else
253 {
254 for( unsigned int i=0; i< element->timers->num; i++ ) {
255 CCTimer *timer = element->timers->arr[i];
256 if( selector == timer->selector ) {
257 CCLOG(@"CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.2f to %.2f", timer->interval, interval);
258 timer->interval = interval;
259 return;
260 }
261 }
262 ccArrayEnsureExtraCapacity(element->timers, 1);
263 }
264
265 CCTimer *timer = [[CCTimer alloc] initWithTarget:target selector:selector interval:interval];
266 ccArrayAppendObject(element->timers, timer);
267 [timer release];
268}
269
270-(void) unscheduleSelector:(SEL)selector forTarget:(id)target
271{
272 // explicity handle nil arguments when removing an object
273 if( target==nil && selector==NULL)
274 return;
275
276 NSAssert( target != nil, @"Target MUST not be nil");
277 NSAssert( selector != NULL, @"Selector MUST not be NULL");
278
279 tHashSelectorEntry *element = NULL;
280 HASH_FIND_INT(hashForSelectors, &target, element);
281
282 if( element ) {
283
284 for( unsigned int i=0; i< element->timers->num; i++ ) {
285 CCTimer *timer = element->timers->arr[i];
286
287
288 if( selector == timer->selector ) {
289
290 if( timer == element->currentTimer && !element->currentTimerSalvaged ) {
291 [element->currentTimer retain];
292 element->currentTimerSalvaged = YES;
293 }
294
295 ccArrayRemoveObjectAtIndex(element->timers, i );
296
297 // update timerIndex in case we are in tick:, looping over the actions
298 if( element->timerIndex >= i )
299 element->timerIndex--;
300
301 if( element->timers->num == 0 ) {
302 if( currentTarget == element )
303 currentTargetSalvaged = YES;
304 else
305 [self removeHashElement: element];
306 }
307 return;
308 }
309 }
310 }
311
312 // Not Found
313// NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString);
314
315}
316
317#pragma mark CCScheduler - Update Specific
318
319-(void) priorityIn:(tListEntry**)list target:(id)target priority:(NSInteger)priority paused:(BOOL)paused
320{
321 tListEntry *listElement = malloc( sizeof(*listElement) );
322
323 listElement->target = target;
324 listElement->priority = priority;
325 listElement->paused = paused;
326 listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector];
327 listElement->next = listElement->prev = NULL;
328 listElement->markedForDeletion = NO;
329
330 // empty list ?
331 if( ! *list ) {
332 DL_APPEND( *list, listElement );
333
334 } else {
335 BOOL added = NO;
336
337 for( tListEntry *elem = *list; elem ; elem = elem->next ) {
338 if( priority < elem->priority ) {
339
340 if( elem == *list )
341 DL_PREPEND(*list, listElement);
342 else {
343 listElement->next = elem;
344 listElement->prev = elem->prev;
345
346 elem->prev->next = listElement;
347 elem->prev = listElement;
348 }
349
350 added = YES;
351 break;
352 }
353 }
354
355 // Not added? priority has the higher value. Append it.
356 if( !added )
357 DL_APPEND(*list, listElement);
358 }
359
360 // update hash entry for quicker access
361 tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 );
362 hashElement->target = [target retain];
363 hashElement->list = list;
364 hashElement->entry = listElement;
365 HASH_ADD_INT(hashForUpdates, target, hashElement );
366}
367
368-(void) appendIn:(tListEntry**)list target:(id)target paused:(BOOL)paused
369{
370 tListEntry *listElement = malloc( sizeof( * listElement ) );
371
372 listElement->target = target;
373 listElement->paused = paused;
374 listElement->markedForDeletion = NO;
375 listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector];
376
377 DL_APPEND(*list, listElement);
378
379
380 // update hash entry for quicker access
381 tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 );
382 hashElement->target = [target retain];
383 hashElement->list = list;
384 hashElement->entry = listElement;
385 HASH_ADD_INT(hashForUpdates, target, hashElement );
386}
387
388-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused
389{
390 tHashUpdateEntry * hashElement = NULL;
391 HASH_FIND_INT(hashForUpdates, &target, hashElement);
392 if(hashElement)
393 {
394#if COCOS2D_DEBUG >= 1
395 NSAssert( hashElement->entry->markedForDeletion, @"CCScheduler: You can't re-schedule an 'update' selector'. Unschedule it first");
396#endif
397 // TODO : check if priority has changed!
398
399 hashElement->entry->markedForDeletion = NO;
400 return;
401 }
402
403 // most of the updates are going to be 0, that's way there
404 // is an special list for updates with priority 0
405 if( priority == 0 )
406 [self appendIn:&updates0 target:target paused:paused];
407
408 else if( priority < 0 )
409 [self priorityIn:&updatesNeg target:target priority:priority paused:paused];
410
411 else // priority > 0
412 [self priorityIn:&updatesPos target:target priority:priority paused:paused];
413}
414
415- (void) removeUpdateFromHash:(tListEntry*)entry
416{
417 tHashUpdateEntry * element = NULL;
418
419 HASH_FIND_INT(hashForUpdates, &entry->target, element);
420 if( element ) {
421 // list entry
422 DL_DELETE( *element->list, element->entry );
423 free( element->entry );
424
425 // hash entry
426 [element->target release];
427 HASH_DEL( hashForUpdates, element);
428 free(element);
429 }
430}
431
432-(void) unscheduleUpdateForTarget:(id)target
433{
434 if( target == nil )
435 return;
436
437 tHashUpdateEntry * element = NULL;
438 HASH_FIND_INT(hashForUpdates, &target, element);
439 if( element ) {
440 if(updateHashLocked)
441 element->entry->markedForDeletion = YES;
442 else
443 [self removeUpdateFromHash:element->entry];
444
445// // list entry
446// DL_DELETE( *element->list, element->entry );
447// free( element->entry );
448//
449// // hash entry
450// [element->target release];
451// HASH_DEL( hashForUpdates, element);
452// free(element);
453 }
454}
455
456#pragma mark CCScheduler - Common for Update selector & Custom Selectors
457
458-(void) unscheduleAllSelectors
459{
460 // Custom Selectors
461 for(tHashSelectorEntry *element=hashForSelectors; element != NULL; ) {
462 id target = element->target;
463 element=element->hh.next;
464 [self unscheduleAllSelectorsForTarget:target];
465 }
466
467 // Updates selectors
468 tListEntry *entry, *tmp;
469 DL_FOREACH_SAFE( updates0, entry, tmp ) {
470 [self unscheduleUpdateForTarget:entry->target];
471 }
472 DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
473 [self unscheduleUpdateForTarget:entry->target];
474 }
475 DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
476 [self unscheduleUpdateForTarget:entry->target];
477 }
478
479}
480
481-(void) unscheduleAllSelectorsForTarget:(id)target
482{
483 // explicit nil handling
484 if( target == nil )
485 return;
486
487 // Custom Selectors
488 tHashSelectorEntry *element = NULL;
489 HASH_FIND_INT(hashForSelectors, &target, element);
490
491 if( element ) {
492 if( ccArrayContainsObject(element->timers, element->currentTimer) && !element->currentTimerSalvaged ) {
493 [element->currentTimer retain];
494 element->currentTimerSalvaged = YES;
495 }
496 ccArrayRemoveAllObjects(element->timers);
497 if( currentTarget == element )
498 currentTargetSalvaged = YES;
499 else
500 [self removeHashElement:element];
501 }
502
503 // Update Selector
504 [self unscheduleUpdateForTarget:target];
505}
506
507-(void) resumeTarget:(id)target
508{
509 NSAssert( target != nil, @"target must be non nil" );
510
511 // Custom Selectors
512 tHashSelectorEntry *element = NULL;
513 HASH_FIND_INT(hashForSelectors, &target, element);
514 if( element )
515 element->paused = NO;
516
517 // Update selector
518 tHashUpdateEntry * elementUpdate = NULL;
519 HASH_FIND_INT(hashForUpdates, &target, elementUpdate);
520 if( elementUpdate ) {
521 NSAssert( elementUpdate->entry != NULL, @"resumeTarget: unknown error");
522 elementUpdate->entry->paused = NO;
523 }
524}
525
526-(void) pauseTarget:(id)target
527{
528 NSAssert( target != nil, @"target must be non nil" );
529
530 // Custom selectors
531 tHashSelectorEntry *element = NULL;
532 HASH_FIND_INT(hashForSelectors, &target, element);
533 if( element )
534 element->paused = YES;
535
536 // Update selector
537 tHashUpdateEntry * elementUpdate = NULL;
538 HASH_FIND_INT(hashForUpdates, &target, elementUpdate);
539 if( elementUpdate ) {
540 NSAssert( elementUpdate->entry != NULL, @"pauseTarget: unknown error");
541 elementUpdate->entry->paused = YES;
542 }
543
544}
545
546-(BOOL) isTargetPaused:(id)target
547{
548 NSAssert( target != nil, @"target must be non nil" );
549
550 // Custom selectors
551 tHashSelectorEntry *element = NULL;
552 HASH_FIND_INT(hashForSelectors, &target, element);
553 if( element )
554 {
555 return element->paused;
556 }
557 return NO; // should never get here
558
559}
560
561#pragma mark CCScheduler - Main Loop
562
563-(void) tick: (ccTime) dt
564{
565 updateHashLocked = YES;
566
567 if( timeScale_ != 1.0f )
568 dt *= timeScale_;
569
570 // Iterate all over the Updates selectors
571 tListEntry *entry, *tmp;
572
573 // updates with priority < 0
574 DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
575 if( ! entry->paused && !entry->markedForDeletion )
576 entry->impMethod( entry->target, updateSelector, dt );
577 }
578
579 // updates with priority == 0
580 DL_FOREACH_SAFE( updates0, entry, tmp ) {
581 if( ! entry->paused && !entry->markedForDeletion )
582 {
583 entry->impMethod( entry->target, updateSelector, dt );
584 }
585 }
586
587 // updates with priority > 0
588 DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
589 if( ! entry->paused && !entry->markedForDeletion )
590 entry->impMethod( entry->target, updateSelector, dt );
591 }
592
593 // Iterate all over the custome selectors
594 for(tHashSelectorEntry *elt=hashForSelectors; elt != NULL; ) {
595
596 currentTarget = elt;
597 currentTargetSalvaged = NO;
598
599 if( ! currentTarget->paused ) {
600
601 // The 'timers' ccArray may change while inside this loop.
602 for( elt->timerIndex = 0; elt->timerIndex < elt->timers->num; elt->timerIndex++) {
603 elt->currentTimer = elt->timers->arr[elt->timerIndex];
604 elt->currentTimerSalvaged = NO;
605
606 impMethod( elt->currentTimer, updateSelector, dt);
607
608 if( elt->currentTimerSalvaged ) {
609 // The currentTimer told the remove itself. To prevent the timer from
610 // accidentally deallocating itself before finishing its step, we retained
611 // it. Now that step is done, it's safe to release it.
612 [elt->currentTimer release];
613 }
614
615 elt->currentTimer = nil;
616 }
617 }
618
619 // elt, at this moment, is still valid
620 // so it is safe to ask this here (issue #490)
621 elt = elt->hh.next;
622
623 // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
624 if( currentTargetSalvaged && currentTarget->timers->num == 0 )
625 [self removeHashElement:currentTarget];
626 }
627
628 // delete all updates that are morked for deletion
629 // updates with priority < 0
630 DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
631 if(entry->markedForDeletion )
632 {
633 [self removeUpdateFromHash:entry];
634 }
635 }
636
637 // updates with priority == 0
638 DL_FOREACH_SAFE( updates0, entry, tmp ) {
639 if(entry->markedForDeletion )
640 {
641 [self removeUpdateFromHash:entry];
642 }
643 }
644
645 // updates with priority > 0
646 DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
647 if(entry->markedForDeletion )
648 {
649 [self removeUpdateFromHash:entry];
650 }
651 }
652
653 updateHashLocked = NO;
654 currentTarget = nil;
655}
656@end
657
diff --git a/libs/cocos2d/CCSprite.h b/libs/cocos2d/CCSprite.h new file mode 100755 index 0000000..f01688e --- /dev/null +++ b/libs/cocos2d/CCSprite.h
@@ -0,0 +1,351 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCNode.h"
29#import "CCProtocols.h"
30#import "CCTextureAtlas.h"
31
32@class CCSpriteBatchNode;
33@class CCSpriteFrame;
34@class CCAnimation;
35
36#pragma mark CCSprite
37
38#define CCSpriteIndexNotInitialized 0xffffffff /// CCSprite invalid index on the CCSpriteBatchode
39
40/**
41 Whether or not an CCSprite will rotate, scale or translate with it's parent.
42 Useful in health bars, when you want that the health bar translates with it's parent but you don't
43 want it to rotate with its parent.
44 @since v0.99.0
45 */
46typedef enum {
47 //! Translate with it's parent
48 CC_HONOR_PARENT_TRANSFORM_TRANSLATE = 1 << 0,
49 //! Rotate with it's parent
50 CC_HONOR_PARENT_TRANSFORM_ROTATE = 1 << 1,
51 //! Scale with it's parent
52 CC_HONOR_PARENT_TRANSFORM_SCALE = 1 << 2,
53 //! Skew with it's parent
54 CC_HONOR_PARENT_TRANSFORM_SKEW = 1 << 3,
55
56 //! All possible transformation enabled. Default value.
57 CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE | CC_HONOR_PARENT_TRANSFORM_SKEW,
58
59} ccHonorParentTransform;
60
61/** CCSprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
62 *
63 * CCSprite can be created with an image, or with a sub-rectangle of an image.
64 *
65 * If the parent or any of its ancestors is a CCSpriteBatchNode then the following features/limitations are valid
66 * - Features when the parent is a CCBatchNode:
67 * - MUCH faster rendering, specially if the CCSpriteBatchNode has many children. All the children will be drawn in a single batch.
68 *
69 * - Limitations
70 * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work)
71 * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl)
72 * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property.
73 * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property.
74 * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite.
75 *
76 * If the parent is an standard CCNode, then CCSprite behaves like any other CCNode:
77 * - It supports blending functions
78 * - It supports aliasing / antialiasing
79 * - But the rendering will be slower: 1 draw per children.
80 *
81 * The default anchorPoint in CCSprite is (0.5, 0.5).
82 */
83@interface CCSprite : CCNode <CCRGBAProtocol, CCTextureProtocol>
84{
85
86 //
87 // Data used when the sprite is rendered using a CCSpriteBatchNode
88 //
89 CCTextureAtlas *textureAtlas_; // Sprite Sheet texture atlas (weak reference)
90 NSUInteger atlasIndex_; // Absolute (real) Index on the batch node
91 CCSpriteBatchNode *batchNode_; // Used batch node (weak reference)
92 ccHonorParentTransform honorParentTransform_; // whether or not to transform according to its parent transformations
93 BOOL dirty_; // Sprite needs to be updated
94 BOOL recursiveDirty_; // Subchildren needs to be updated
95 BOOL hasChildren_; // optimization to check if it contain children
96
97 //
98 // Data used when the sprite is self-rendered
99 //
100 ccBlendFunc blendFunc_; // Needed for the texture protocol
101 CCTexture2D *texture_; // Texture used to render the sprite
102
103 //
104 // Shared data
105 //
106
107 // whether or not it's parent is a CCSpriteBatchNode
108 BOOL usesBatchNode_;
109
110 // texture
111 CGRect rect_;
112 CGRect rectInPixels_;
113 BOOL rectRotated_;
114
115 // Offset Position (used by Zwoptex)
116 CGPoint offsetPositionInPixels_;
117 CGPoint unflippedOffsetPositionFromCenter_;
118
119 // vertex coords, texture coords and color info
120 ccV3F_C4B_T2F_Quad quad_;
121
122 // opacity and RGB protocol
123 GLubyte opacity_;
124 ccColor3B color_;
125 ccColor3B colorUnmodified_;
126 BOOL opacityModifyRGB_;
127
128 // image is flipped
129 BOOL flipX_;
130 BOOL flipY_;
131
132
133 // Animations that belong to the sprite
134 NSMutableDictionary *animations_;
135
136@public
137 // used internally.
138 void (*updateMethod)(id, SEL);
139}
140
141/** whether or not the Sprite needs to be updated in the Atlas */
142@property (nonatomic,readwrite) BOOL dirty;
143/** the quad (tex coords, vertex coords and color) information */
144@property (nonatomic,readonly) ccV3F_C4B_T2F_Quad quad;
145/** The index used on the TextureAtlas. Don't modify this value unless you know what you are doing */
146@property (nonatomic,readwrite) NSUInteger atlasIndex;
147/** returns the rect of the CCSprite in points */
148@property (nonatomic,readonly) CGRect textureRect;
149/** returns whether or not the texture rectangle is rotated */
150@property (nonatomic,readonly) BOOL textureRectRotated;
151/** whether or not the sprite is flipped horizontally.
152 It only flips the texture of the sprite, and not the texture of the sprite's children.
153 Also, flipping the texture doesn't alter the anchorPoint.
154 If you want to flip the anchorPoint too, and/or to flip the children too use:
155
156 sprite.scaleX *= -1;
157 */
158@property (nonatomic,readwrite) BOOL flipX;
159/** whether or not the sprite is flipped vertically.
160 It only flips the texture of the sprite, and not the texture of the sprite's children.
161 Also, flipping the texture doesn't alter the anchorPoint.
162 If you want to flip the anchorPoint too, and/or to flip the children too use:
163
164 sprite.scaleY *= -1;
165 */
166@property (nonatomic,readwrite) BOOL flipY;
167/** opacity: conforms to CCRGBAProtocol protocol */
168@property (nonatomic,readwrite) GLubyte opacity;
169/** RGB colors: conforms to CCRGBAProtocol protocol */
170@property (nonatomic,readwrite) ccColor3B color;
171/** whether or not the Sprite is rendered using a CCSpriteBatchNode */
172@property (nonatomic,readwrite) BOOL usesBatchNode;
173/** weak reference of the CCTextureAtlas used when the sprite is rendered using a CCSpriteBatchNode */
174@property (nonatomic,readwrite,assign) CCTextureAtlas *textureAtlas;
175/** weak reference to the CCSpriteBatchNode that renders the CCSprite */
176@property (nonatomic,readwrite,assign) CCSpriteBatchNode *batchNode;
177/** whether or not to transform according to its parent transfomrations.
178 Useful for health bars. eg: Don't rotate the health bar, even if the parent rotates.
179 IMPORTANT: Only valid if it is rendered using an CCSpriteBatchNode.
180 @since v0.99.0
181 */
182@property (nonatomic,readwrite) ccHonorParentTransform honorParentTransform;
183/** offset position in pixels of the sprite in points. Calculated automatically by editors like Zwoptex.
184 @since v0.99.0
185 */
186@property (nonatomic,readonly) CGPoint offsetPositionInPixels;
187/** conforms to CCTextureProtocol protocol */
188@property (nonatomic,readwrite) ccBlendFunc blendFunc;
189
190#pragma mark CCSprite - Initializers
191
192/** Creates an sprite with a texture.
193 The rect used will be the size of the texture.
194 The offset will be (0,0).
195 */
196+(id) spriteWithTexture:(CCTexture2D*)texture;
197
198/** Creates an sprite with a texture and a rect.
199 The offset will be (0,0).
200 */
201+(id) spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
202
203/** Creates an sprite with an sprite frame.
204 */
205+(id) spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame;
206
207/** Creates an sprite with an sprite frame name.
208 An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name.
209 If the CCSpriteFrame doesn't exist it will raise an exception.
210 @since v0.9
211 */
212+(id) spriteWithSpriteFrameName:(NSString*)spriteFrameName;
213
214/** Creates an sprite with an image filename.
215 The rect used will be the size of the image.
216 The offset will be (0,0).
217 */
218+(id) spriteWithFile:(NSString*)filename;
219
220/** Creates an sprite with an image filename and a rect.
221 The offset will be (0,0).
222 */
223+(id) spriteWithFile:(NSString*)filename rect:(CGRect)rect;
224
225/** Creates an sprite with a CGImageRef and a key.
226 The key is used by the CCTextureCache to know if a texture was already created with this CGImage.
227 For example, a valid key is: @"sprite_frame_01".
228 If key is nil, then a new texture will be created each time by the CCTextureCache.
229 @since v0.99.0
230 */
231+(id) spriteWithCGImage: (CGImageRef)image key:(NSString*)key;
232
233
234/** Creates an sprite with an CCBatchNode and a rect
235 */
236+(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect;
237
238
239/** Initializes an sprite with a texture.
240 The rect used will be the size of the texture.
241 The offset will be (0,0).
242 */
243-(id) initWithTexture:(CCTexture2D*)texture;
244
245/** Initializes an sprite with a texture and a rect in points.
246 The offset will be (0,0).
247 */
248-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
249
250/** Initializes an sprite with an sprite frame.
251 */
252-(id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame;
253
254/** Initializes an sprite with an sprite frame name.
255 An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name.
256 If the CCSpriteFrame doesn't exist it will raise an exception.
257 @since v0.9
258 */
259-(id) initWithSpriteFrameName:(NSString*)spriteFrameName;
260
261/** Initializes an sprite with an image filename.
262 The rect used will be the size of the image.
263 The offset will be (0,0).
264 */
265-(id) initWithFile:(NSString*)filename;
266
267/** Initializes an sprite with an image filename, and a rect.
268 The offset will be (0,0).
269 */
270-(id) initWithFile:(NSString*)filename rect:(CGRect)rect;
271
272/** Initializes an sprite with a CGImageRef and a key
273 The key is used by the CCTextureCache to know if a texture was already created with this CGImage.
274 For example, a valid key is: @"sprite_frame_01".
275 If key is nil, then a new texture will be created each time by the CCTextureCache.
276 @since v0.99.0
277 */
278-(id) initWithCGImage:(CGImageRef)image key:(NSString*)key;
279
280/** Initializes an sprite with an CCSpriteBatchNode and a rect in points
281 */
282-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect;
283
284/** Initializes an sprite with an CCSpriteBatchNode and a rect in pixels
285 @since v0.99.5
286 */
287-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect;
288
289
290
291#pragma mark CCSprite - BatchNode methods
292
293/** updates the quad according the the rotation, position, scale values.
294 */
295-(void)updateTransform;
296
297/** updates the texture rect of the CCSprite in points.
298 */
299-(void) setTextureRect:(CGRect) rect;
300/** updates the texture rect, rectRotated and untrimmed size of the CCSprite in pixels
301 */
302-(void) setTextureRectInPixels:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)size;
303
304/** tell the sprite to use self-render.
305 @since v0.99.0
306 */
307-(void) useSelfRender;
308
309/** tell the sprite to use sprite batch node
310 @since v0.99.0
311 */
312-(void) useBatchNode:(CCSpriteBatchNode*)batchNode;
313
314
315#pragma mark CCSprite - Frames
316
317/** sets a new display frame to the CCSprite. */
318-(void) setDisplayFrame:(CCSpriteFrame*)newFrame;
319
320/** returns whether or not a CCSpriteFrame is being displayed */
321-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame;
322
323/** returns the current displayed frame. */
324-(CCSpriteFrame*) displayedFrame;
325
326#pragma mark CCSprite - Animation
327
328/** changes the display frame based on an animation and an index.
329 @deprecated Will be removed in 1.0.1. Use setDisplayFrameWithAnimationName:index instead
330 */
331-(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex DEPRECATED_ATTRIBUTE;
332
333/** changes the display frame with animation name and index.
334 The animation name will be get from the CCAnimationCache
335 @since v0.99.5
336 */
337-(void) setDisplayFrameWithAnimationName:(NSString*)animationName index:(int) frameIndex;
338
339/** returns an Animation given it's name.
340
341 @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
342 */
343-(CCAnimation*)animationByName: (NSString*) animationName DEPRECATED_ATTRIBUTE;
344
345/** adds an Animation to the Sprite.
346
347 @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
348 */
349-(void) addAnimation: (CCAnimation*) animation DEPRECATED_ATTRIBUTE;
350
351@end
diff --git a/libs/cocos2d/CCSprite.m b/libs/cocos2d/CCSprite.m new file mode 100755 index 0000000..37f06d2 --- /dev/null +++ b/libs/cocos2d/CCSprite.m
@@ -0,0 +1,1029 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Availability.h>
28
29#import "ccConfig.h"
30#import "CCSpriteBatchNode.h"
31#import "CCSprite.h"
32#import "CCSpriteFrame.h"
33#import "CCSpriteFrameCache.h"
34#import "CCAnimation.h"
35#import "CCAnimationCache.h"
36#import "CCTextureCache.h"
37#import "Support/CGPointExtension.h"
38#import "CCDrawingPrimitives.h"
39
40#pragma mark -
41#pragma mark CCSprite
42
43#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
44#define RENDER_IN_SUBPIXEL
45#else
46#define RENDER_IN_SUBPIXEL(__A__) ( (int)(__A__))
47#endif
48
49// XXX: Optmization
50struct transformValues_ {
51 CGPoint pos; // position x and y
52 CGPoint scale; // scale x and y
53 float rotation;
54 CGPoint skew; // skew x and y
55 CGPoint ap; // anchor point in pixels
56 BOOL visible;
57};
58
59@interface CCSprite (Private)
60-(void)updateTextureCoords:(CGRect)rect;
61-(void)updateBlendFunc;
62-(void) initAnimationDictionary;
63-(void) getTransformValues:(struct transformValues_*)tv; // optimization
64@end
65
66@implementation CCSprite
67
68@synthesize dirty = dirty_;
69@synthesize quad = quad_;
70@synthesize atlasIndex = atlasIndex_;
71@synthesize textureRect = rect_;
72@synthesize textureRectRotated = rectRotated_;
73@synthesize blendFunc = blendFunc_;
74@synthesize usesBatchNode = usesBatchNode_;
75@synthesize textureAtlas = textureAtlas_;
76@synthesize batchNode = batchNode_;
77@synthesize honorParentTransform = honorParentTransform_;
78@synthesize offsetPositionInPixels = offsetPositionInPixels_;
79
80
81+(id)spriteWithTexture:(CCTexture2D*)texture
82{
83 return [[[self alloc] initWithTexture:texture] autorelease];
84}
85
86+(id)spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
87{
88 return [[[self alloc] initWithTexture:texture rect:rect] autorelease];
89}
90
91+(id)spriteWithFile:(NSString*)filename
92{
93 return [[[self alloc] initWithFile:filename] autorelease];
94}
95
96+(id)spriteWithFile:(NSString*)filename rect:(CGRect)rect
97{
98 return [[[self alloc] initWithFile:filename rect:rect] autorelease];
99}
100
101+(id)spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame
102{
103 return [[[self alloc] initWithSpriteFrame:spriteFrame] autorelease];
104}
105
106+(id)spriteWithSpriteFrameName:(NSString*)spriteFrameName
107{
108 CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName];
109
110 NSAssert1(frame!=nil, @"Invalid spriteFrameName: %@", spriteFrameName);
111 return [self spriteWithSpriteFrame:frame];
112}
113
114+(id)spriteWithCGImage:(CGImageRef)image key:(NSString*)key
115{
116 return [[[self alloc] initWithCGImage:image key:key] autorelease];
117}
118
119+(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect
120{
121 return [[[self alloc] initWithBatchNode:batchNode rect:rect] autorelease];
122}
123
124-(id) init
125{
126 if( (self=[super init]) ) {
127 dirty_ = recursiveDirty_ = NO;
128
129 // by default use "Self Render".
130 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
131 [self useSelfRender];
132
133 opacityModifyRGB_ = YES;
134 opacity_ = 255;
135 color_ = colorUnmodified_ = ccWHITE;
136
137 blendFunc_.src = CC_BLEND_SRC;
138 blendFunc_.dst = CC_BLEND_DST;
139
140 // update texture (calls updateBlendFunc)
141 [self setTexture:nil];
142
143 // clean the Quad
144 bzero(&quad_, sizeof(quad_));
145
146 flipY_ = flipX_ = NO;
147
148 // lazy alloc
149 animations_ = nil;
150
151 // default transform anchor: center
152 anchorPoint_ = ccp(0.5f, 0.5f);
153
154 // zwoptex default values
155 offsetPositionInPixels_ = CGPointZero;
156
157 honorParentTransform_ = CC_HONOR_PARENT_TRANSFORM_ALL;
158 hasChildren_ = NO;
159
160 // Atlas: Color
161 ccColor4B tmpColor = {255,255,255,255};
162 quad_.bl.colors = tmpColor;
163 quad_.br.colors = tmpColor;
164 quad_.tl.colors = tmpColor;
165 quad_.tr.colors = tmpColor;
166
167 // Atlas: Vertex
168
169 // updated in "useSelfRender"
170
171 // Atlas: TexCoords
172 [self setTextureRectInPixels:CGRectZero rotated:NO untrimmedSize:CGSizeZero];
173
174 // updateMethod selector
175 updateMethod = (__typeof__(updateMethod))[self methodForSelector:@selector(updateTransform)];
176 }
177
178 return self;
179}
180
181-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
182{
183 NSAssert(texture!=nil, @"Invalid texture for sprite");
184 // IMPORTANT: [self init] and not [super init];
185 if( (self = [self init]) )
186 {
187 [self setTexture:texture];
188 [self setTextureRect:rect];
189 }
190 return self;
191}
192
193-(id) initWithTexture:(CCTexture2D*)texture
194{
195 NSAssert(texture!=nil, @"Invalid texture for sprite");
196
197 CGRect rect = CGRectZero;
198 rect.size = texture.contentSize;
199 return [self initWithTexture:texture rect:rect];
200}
201
202-(id) initWithFile:(NSString*)filename
203{
204 NSAssert(filename!=nil, @"Invalid filename for sprite");
205
206 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
207 if( texture ) {
208 CGRect rect = CGRectZero;
209 rect.size = texture.contentSize;
210 return [self initWithTexture:texture rect:rect];
211 }
212
213 [self release];
214 return nil;
215}
216
217-(id) initWithFile:(NSString*)filename rect:(CGRect)rect
218{
219 NSAssert(filename!=nil, @"Invalid filename for sprite");
220
221 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
222 if( texture )
223 return [self initWithTexture:texture rect:rect];
224
225 [self release];
226 return nil;
227}
228
229- (id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame
230{
231 NSAssert(spriteFrame!=nil, @"Invalid spriteFrame for sprite");
232
233 id ret = [self initWithTexture:spriteFrame.texture rect:spriteFrame.rect];
234 [self setDisplayFrame:spriteFrame];
235 return ret;
236}
237
238-(id)initWithSpriteFrameName:(NSString*)spriteFrameName
239{
240 NSAssert(spriteFrameName!=nil, @"Invalid spriteFrameName for sprite");
241
242 CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName];
243 return [self initWithSpriteFrame:frame];
244}
245
246// XXX: deprecated
247- (id) initWithCGImage: (CGImageRef)image
248{
249 NSAssert(image!=nil, @"Invalid CGImageRef for sprite");
250
251 // XXX: possible bug. See issue #349. New API should be added
252 NSString *key = [NSString stringWithFormat:@"%08X",(unsigned long)image];
253 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key];
254
255 CGRect rect = CGRectZero;
256 rect.size = texture.contentSize;
257
258 return [self initWithTexture:texture rect:rect];
259}
260
261- (id) initWithCGImage:(CGImageRef)image key:(NSString*)key
262{
263 NSAssert(image!=nil, @"Invalid CGImageRef for sprite");
264
265 // XXX: possible bug. See issue #349. New API should be added
266 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key];
267
268 CGRect rect = CGRectZero;
269 rect.size = texture.contentSize;
270
271 return [self initWithTexture:texture rect:rect];
272}
273
274-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect
275{
276 id ret = [self initWithTexture:batchNode.texture rect:rect];
277 [self useBatchNode:batchNode];
278
279 return ret;
280}
281
282-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect
283{
284 id ret = [self initWithTexture:batchNode.texture];
285 [self setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size];
286 [self useBatchNode:batchNode];
287
288 return ret;
289}
290
291- (NSString*) description
292{
293 return [NSString stringWithFormat:@"<%@ = %08X | Rect = (%.2f,%.2f,%.2f,%.2f) | tag = %i | atlasIndex = %i>", [self class], self,
294 rect_.origin.x, rect_.origin.y, rect_.size.width, rect_.size.height,
295 tag_,
296 atlasIndex_
297 ];
298}
299
300- (void) dealloc
301{
302 [texture_ release];
303 [animations_ release];
304 [super dealloc];
305}
306
307-(void) useSelfRender
308{
309 atlasIndex_ = CCSpriteIndexNotInitialized;
310 usesBatchNode_ = NO;
311 textureAtlas_ = nil;
312 batchNode_ = nil;
313 dirty_ = recursiveDirty_ = NO;
314
315 float x1 = 0 + offsetPositionInPixels_.x;
316 float y1 = 0 + offsetPositionInPixels_.y;
317 float x2 = x1 + rectInPixels_.size.width;
318 float y2 = y1 + rectInPixels_.size.height;
319 quad_.bl.vertices = (ccVertex3F) { x1, y1, 0 };
320 quad_.br.vertices = (ccVertex3F) { x2, y1, 0 };
321 quad_.tl.vertices = (ccVertex3F) { x1, y2, 0 };
322 quad_.tr.vertices = (ccVertex3F) { x2, y2, 0 };
323}
324
325-(void) useBatchNode:(CCSpriteBatchNode*)batchNode
326{
327 usesBatchNode_ = YES;
328 textureAtlas_ = [batchNode textureAtlas]; // weak ref
329 batchNode_ = batchNode; // weak ref
330}
331
332-(void) initAnimationDictionary
333{
334 animations_ = [[NSMutableDictionary alloc] initWithCapacity:2];
335}
336
337-(void)setTextureRect:(CGRect)rect
338{
339 CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect );
340 [self setTextureRectInPixels:rectInPixels rotated:NO untrimmedSize:rectInPixels.size];
341}
342
343-(void)setTextureRectInPixels:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)untrimmedSize
344{
345 rectInPixels_ = rect;
346 rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
347 rectRotated_ = rotated;
348
349 [self setContentSizeInPixels:untrimmedSize];
350 [self updateTextureCoords:rectInPixels_];
351
352 CGPoint relativeOffsetInPixels = unflippedOffsetPositionFromCenter_;
353
354 // issue #732
355 if( flipX_ )
356 relativeOffsetInPixels.x = -relativeOffsetInPixels.x;
357 if( flipY_ )
358 relativeOffsetInPixels.y = -relativeOffsetInPixels.y;
359
360 offsetPositionInPixels_.x = relativeOffsetInPixels.x + (contentSizeInPixels_.width - rectInPixels_.size.width) / 2;
361 offsetPositionInPixels_.y = relativeOffsetInPixels.y + (contentSizeInPixels_.height - rectInPixels_.size.height) / 2;
362
363
364 // rendering using batch node
365 if( usesBatchNode_ ) {
366 // update dirty_, don't update recursiveDirty_
367 dirty_ = YES;
368 }
369
370 // self rendering
371 else
372 {
373 // Atlas: Vertex
374 float x1 = 0 + offsetPositionInPixels_.x;
375 float y1 = 0 + offsetPositionInPixels_.y;
376 float x2 = x1 + rectInPixels_.size.width;
377 float y2 = y1 + rectInPixels_.size.height;
378
379 // Don't update Z.
380 quad_.bl.vertices = (ccVertex3F) { x1, y1, 0 };
381 quad_.br.vertices = (ccVertex3F) { x2, y1, 0 };
382 quad_.tl.vertices = (ccVertex3F) { x1, y2, 0 };
383 quad_.tr.vertices = (ccVertex3F) { x2, y2, 0 };
384 }
385}
386
387-(void)updateTextureCoords:(CGRect)rect
388{
389 CCTexture2D *tex = (usesBatchNode_)?[textureAtlas_ texture]:texture_;
390 if(!tex)
391 return;
392
393 float atlasWidth = (float)tex.pixelsWide;
394 float atlasHeight = (float)tex.pixelsHigh;
395
396 float left,right,top,bottom;
397
398 if(rectRotated_){
399#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
400 left = (2*rect.origin.x+1)/(2*atlasWidth);
401 right = left+(rect.size.height*2-2)/(2*atlasWidth);
402 top = (2*rect.origin.y+1)/(2*atlasHeight);
403 bottom = top+(rect.size.width*2-2)/(2*atlasHeight);
404#else
405 left = rect.origin.x/atlasWidth;
406 right = left+(rect.size.height/atlasWidth);
407 top = rect.origin.y/atlasHeight;
408 bottom = top+(rect.size.width/atlasHeight);
409#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
410
411 if( flipX_)
412 CC_SWAP(top,bottom);
413 if( flipY_)
414 CC_SWAP(left,right);
415
416 quad_.bl.texCoords.u = left;
417 quad_.bl.texCoords.v = top;
418 quad_.br.texCoords.u = left;
419 quad_.br.texCoords.v = bottom;
420 quad_.tl.texCoords.u = right;
421 quad_.tl.texCoords.v = top;
422 quad_.tr.texCoords.u = right;
423 quad_.tr.texCoords.v = bottom;
424 } else {
425#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
426 left = (2*rect.origin.x+1)/(2*atlasWidth);
427 right = left + (rect.size.width*2-2)/(2*atlasWidth);
428 top = (2*rect.origin.y+1)/(2*atlasHeight);
429 bottom = top + (rect.size.height*2-2)/(2*atlasHeight);
430#else
431 left = rect.origin.x/atlasWidth;
432 right = left + rect.size.width/atlasWidth;
433 top = rect.origin.y/atlasHeight;
434 bottom = top + rect.size.height/atlasHeight;
435#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
436
437 if( flipX_)
438 CC_SWAP(left,right);
439 if( flipY_)
440 CC_SWAP(top,bottom);
441
442 quad_.bl.texCoords.u = left;
443 quad_.bl.texCoords.v = bottom;
444 quad_.br.texCoords.u = right;
445 quad_.br.texCoords.v = bottom;
446 quad_.tl.texCoords.u = left;
447 quad_.tl.texCoords.v = top;
448 quad_.tr.texCoords.u = right;
449 quad_.tr.texCoords.v = top;
450 }
451}
452
453-(void)updateTransform
454{
455 NSAssert( usesBatchNode_, @"updateTransform is only valid when CCSprite is being renderd using an CCSpriteBatchNode");
456
457 // optimization. Quick return if not dirty
458 if( ! dirty_ )
459 return;
460
461 CGAffineTransform matrix;
462
463 // Optimization: if it is not visible, then do nothing
464 if( ! visible_ ) {
465 quad_.br.vertices = quad_.tl.vertices = quad_.tr.vertices = quad_.bl.vertices = (ccVertex3F){0,0,0};
466 [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
467 dirty_ = recursiveDirty_ = NO;
468 return ;
469 }
470
471
472 // Optimization: If parent is batchnode, or parent is nil
473 // build Affine transform manually
474 if( ! parent_ || parent_ == batchNode_ ) {
475
476 float radians = -CC_DEGREES_TO_RADIANS(rotation_);
477 float c = cosf(radians);
478 float s = sinf(radians);
479
480 matrix = CGAffineTransformMake( c * scaleX_, s * scaleX_,
481 -s * scaleY_, c * scaleY_,
482 positionInPixels_.x, positionInPixels_.y);
483 if( skewX_ || skewY_ ) {
484 CGAffineTransform skewMatrix = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)),
485 tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f,
486 0.0f, 0.0f);
487 matrix = CGAffineTransformConcat(skewMatrix, matrix);
488 }
489 matrix = CGAffineTransformTranslate(matrix, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
490
491
492 } else { // parent_ != batchNode_
493
494 // else do affine transformation according to the HonorParentTransform
495
496 matrix = CGAffineTransformIdentity;
497 ccHonorParentTransform prevHonor = CC_HONOR_PARENT_TRANSFORM_ALL;
498
499 for (CCNode *p = self ; p && p != batchNode_ ; p = p.parent) {
500
501 // Might happen. Issue #1053
502 NSAssert( [p isKindOfClass:[CCSprite class]], @"CCSprite should be a CCSprite subclass. Probably you initialized an sprite with a batchnode, but you didn't add it to the batch node." );
503
504 struct transformValues_ tv;
505 [(CCSprite*)p getTransformValues: &tv];
506
507 // If any of the parents are not visible, then don't draw this node
508 if( ! tv.visible ) {
509 quad_.br.vertices = quad_.tl.vertices = quad_.tr.vertices = quad_.bl.vertices = (ccVertex3F){0,0,0};
510 [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
511 dirty_ = recursiveDirty_ = NO;
512 return;
513 }
514 CGAffineTransform newMatrix = CGAffineTransformIdentity;
515
516 // 2nd: Translate, Skew, Rotate, Scale
517 if( prevHonor & CC_HONOR_PARENT_TRANSFORM_TRANSLATE )
518 newMatrix = CGAffineTransformTranslate(newMatrix, tv.pos.x, tv.pos.y);
519 if( prevHonor & CC_HONOR_PARENT_TRANSFORM_ROTATE )
520 newMatrix = CGAffineTransformRotate(newMatrix, -CC_DEGREES_TO_RADIANS(tv.rotation));
521 if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_SKEW ) {
522 CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(tv.skew.y)), tanf(CC_DEGREES_TO_RADIANS(tv.skew.x)), 1.0f, 0.0f, 0.0f);
523 // apply the skew to the transform
524 newMatrix = CGAffineTransformConcat(skew, newMatrix);
525 }
526 if( prevHonor & CC_HONOR_PARENT_TRANSFORM_SCALE ) {
527 newMatrix = CGAffineTransformScale(newMatrix, tv.scale.x, tv.scale.y);
528 }
529
530 // 3rd: Translate anchor point
531 newMatrix = CGAffineTransformTranslate(newMatrix, -tv.ap.x, -tv.ap.y);
532
533 // 4th: Matrix multiplication
534 matrix = CGAffineTransformConcat( matrix, newMatrix);
535
536 prevHonor = [(CCSprite*)p honorParentTransform];
537 }
538 }
539
540
541 //
542 // calculate the Quad based on the Affine Matrix
543 //
544
545 CGSize size = rectInPixels_.size;
546
547 float x1 = offsetPositionInPixels_.x;
548 float y1 = offsetPositionInPixels_.y;
549
550 float x2 = x1 + size.width;
551 float y2 = y1 + size.height;
552 float x = matrix.tx;
553 float y = matrix.ty;
554
555 float cr = matrix.a;
556 float sr = matrix.b;
557 float cr2 = matrix.d;
558 float sr2 = -matrix.c;
559 float ax = x1 * cr - y1 * sr2 + x;
560 float ay = x1 * sr + y1 * cr2 + y;
561
562 float bx = x2 * cr - y1 * sr2 + x;
563 float by = x2 * sr + y1 * cr2 + y;
564
565 float cx = x2 * cr - y2 * sr2 + x;
566 float cy = x2 * sr + y2 * cr2 + y;
567
568 float dx = x1 * cr - y2 * sr2 + x;
569 float dy = x1 * sr + y2 * cr2 + y;
570
571 quad_.bl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), vertexZ_ };
572 quad_.br.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), vertexZ_ };
573 quad_.tl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), vertexZ_ };
574 quad_.tr.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), vertexZ_ };
575
576 [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
577 dirty_ = recursiveDirty_ = NO;
578}
579
580// XXX: Optimization: instead of calling 5 times the parent sprite to obtain: position, scale.x, scale.y, anchorpoint and rotation,
581// this fuction return the 5 values in 1 single call
582-(void) getTransformValues:(struct transformValues_*) tv
583{
584 tv->pos = positionInPixels_;
585 tv->scale.x = scaleX_;
586 tv->scale.y = scaleY_;
587 tv->rotation = rotation_;
588 tv->skew.x = skewX_;
589 tv->skew.y = skewY_;
590 tv->ap = anchorPointInPixels_;
591 tv->visible = visible_;
592}
593
594#pragma mark CCSprite - draw
595
596-(void) draw
597{
598 [super draw];
599
600 NSAssert(!usesBatchNode_, @"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
601
602 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
603 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
604 // Unneeded states: -
605
606 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
607 if( newBlend )
608 glBlendFunc( blendFunc_.src, blendFunc_.dst );
609
610#define kQuadSize sizeof(quad_.bl)
611 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
612
613 long offset = (long)&quad_;
614
615 // vertex
616 NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
617 glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) );
618
619 // color
620 diff = offsetof( ccV3F_C4B_T2F, colors);
621 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff));
622
623 // tex coords
624 diff = offsetof( ccV3F_C4B_T2F, texCoords);
625 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff));
626
627 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
628
629 if( newBlend )
630 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
631
632#if CC_SPRITE_DEBUG_DRAW == 1
633 // draw bounding box
634 CGSize s = self.contentSize;
635 CGPoint vertices[4] = {
636 ccp(0,0), ccp(s.width,0),
637 ccp(s.width,s.height), ccp(0,s.height)
638 };
639 ccDrawPoly(vertices, 4, YES);
640#elif CC_SPRITE_DEBUG_DRAW == 2
641 // draw texture box
642 CGSize s = self.textureRect.size;
643 CGPoint offsetPix = self.offsetPositionInPixels;
644 CGPoint vertices[4] = {
645 ccp(offsetPix.x,offsetPix.y), ccp(offsetPix.x+s.width,offsetPix.y),
646 ccp(offsetPix.x+s.width,offsetPix.y+s.height), ccp(offsetPix.x,offsetPix.y+s.height)
647 };
648 ccDrawPoly(vertices, 4, YES);
649#endif // CC_SPRITE_DEBUG_DRAW
650
651}
652
653#pragma mark CCSprite - CCNode overrides
654
655-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag
656{
657 NSAssert( child != nil, @"Argument must be non-nil");
658
659 [super addChild:child z:z tag:aTag];
660
661 if( usesBatchNode_ ) {
662 NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSprite only supports CCSprites as children when using CCSpriteBatchNode");
663 NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCSprite is not using the same texture id");
664
665 NSUInteger index = [batchNode_ atlasIndexForChild:child atZ:z];
666 [batchNode_ insertChild:child inAtlasAtIndex:index];
667 }
668
669 hasChildren_ = YES;
670}
671
672-(void) reorderChild:(CCSprite*)child z:(NSInteger)z
673{
674 NSAssert( child != nil, @"Child must be non-nil");
675 NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" );
676
677 if( z == child.zOrder )
678 return;
679
680 if( usesBatchNode_ ) {
681 // XXX: Instead of removing/adding, it is more efficient to reorder manually
682 [child retain];
683 [self removeChild:child cleanup:NO];
684 [self addChild:child z:z];
685 [child release];
686 }
687
688 else
689 [super reorderChild:child z:z];
690}
691
692-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup
693{
694 if( usesBatchNode_ )
695 [batchNode_ removeSpriteFromAtlas:sprite];
696
697 [super removeChild:sprite cleanup:doCleanup];
698
699 hasChildren_ = ( [children_ count] > 0 );
700}
701
702-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup
703{
704 if( usesBatchNode_ ) {
705 CCSprite *child;
706 CCARRAY_FOREACH(children_, child)
707 [batchNode_ removeSpriteFromAtlas:child];
708 }
709
710 [super removeAllChildrenWithCleanup:doCleanup];
711
712 hasChildren_ = NO;
713}
714
715//
716// CCNode property overloads
717// used only when parent is CCSpriteBatchNode
718//
719#pragma mark CCSprite - property overloads
720
721
722-(void) setDirtyRecursively:(BOOL)b
723{
724 dirty_ = recursiveDirty_ = b;
725 // recursively set dirty
726 if( hasChildren_ ) {
727 CCSprite *child;
728 CCARRAY_FOREACH(children_, child)
729 [child setDirtyRecursively:YES];
730 }
731}
732
733// XXX HACK: optimization
734#define SET_DIRTY_RECURSIVELY() { \
735 if( usesBatchNode_ && ! recursiveDirty_ ) { \
736 dirty_ = recursiveDirty_ = YES; \
737 if( hasChildren_) \
738 [self setDirtyRecursively:YES]; \
739 } \
740 }
741
742-(void)setPosition:(CGPoint)pos
743{
744 [super setPosition:pos];
745 SET_DIRTY_RECURSIVELY();
746}
747
748-(void)setPositionInPixels:(CGPoint)pos
749{
750 [super setPositionInPixels:pos];
751 SET_DIRTY_RECURSIVELY();
752}
753
754-(void)setRotation:(float)rot
755{
756 [super setRotation:rot];
757 SET_DIRTY_RECURSIVELY();
758}
759
760-(void)setSkewX:(float)sx
761{
762 [super setSkewX:sx];
763 SET_DIRTY_RECURSIVELY();
764}
765
766-(void)setSkewY:(float)sy
767{
768 [super setSkewY:sy];
769 SET_DIRTY_RECURSIVELY();
770}
771
772-(void)setScaleX:(float) sx
773{
774 [super setScaleX:sx];
775 SET_DIRTY_RECURSIVELY();
776}
777
778-(void)setScaleY:(float) sy
779{
780 [super setScaleY:sy];
781 SET_DIRTY_RECURSIVELY();
782}
783
784-(void)setScale:(float) s
785{
786 [super setScale:s];
787 SET_DIRTY_RECURSIVELY();
788}
789
790-(void) setVertexZ:(float)z
791{
792 [super setVertexZ:z];
793 SET_DIRTY_RECURSIVELY();
794}
795
796-(void)setAnchorPoint:(CGPoint)anchor
797{
798 [super setAnchorPoint:anchor];
799 SET_DIRTY_RECURSIVELY();
800}
801
802-(void)setIsRelativeAnchorPoint:(BOOL)relative
803{
804 NSAssert( ! usesBatchNode_, @"relativeTransformAnchor is invalid in CCSprite");
805 [super setIsRelativeAnchorPoint:relative];
806}
807
808-(void)setVisible:(BOOL)v
809{
810 [super setVisible:v];
811 SET_DIRTY_RECURSIVELY();
812}
813
814-(void)setFlipX:(BOOL)b
815{
816 if( flipX_ != b ) {
817 flipX_ = b;
818 [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:contentSizeInPixels_];
819 }
820}
821-(BOOL) flipX
822{
823 return flipX_;
824}
825
826-(void) setFlipY:(BOOL)b
827{
828 if( flipY_ != b ) {
829 flipY_ = b;
830 [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:contentSizeInPixels_];
831 }
832}
833-(BOOL) flipY
834{
835 return flipY_;
836}
837
838//
839// RGBA protocol
840//
841#pragma mark CCSprite - RGBA protocol
842-(void) updateColor
843{
844 ccColor4B color4 = {color_.r, color_.g, color_.b, opacity_ };
845
846 quad_.bl.colors = color4;
847 quad_.br.colors = color4;
848 quad_.tl.colors = color4;
849 quad_.tr.colors = color4;
850
851 // renders using Sprite Manager
852 if( usesBatchNode_ ) {
853 if( atlasIndex_ != CCSpriteIndexNotInitialized)
854 [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
855 else
856 // no need to set it recursively
857 // update dirty_, don't update recursiveDirty_
858 dirty_ = YES;
859 }
860 // self render
861 // do nothing
862}
863
864-(GLubyte) opacity
865{
866 return opacity_;
867}
868
869-(void) setOpacity:(GLubyte) anOpacity
870{
871 opacity_ = anOpacity;
872
873 // special opacity for premultiplied textures
874 if( opacityModifyRGB_ )
875 [self setColor: colorUnmodified_];
876
877 [self updateColor];
878}
879
880- (ccColor3B) color
881{
882 if(opacityModifyRGB_)
883 return colorUnmodified_;
884
885 return color_;
886}
887
888-(void) setColor:(ccColor3B)color3
889{
890 color_ = colorUnmodified_ = color3;
891
892 if( opacityModifyRGB_ ){
893 color_.r = color3.r * opacity_/255;
894 color_.g = color3.g * opacity_/255;
895 color_.b = color3.b * opacity_/255;
896 }
897
898 [self updateColor];
899}
900
901-(void) setOpacityModifyRGB:(BOOL)modify
902{
903 ccColor3B oldColor = self.color;
904 opacityModifyRGB_ = modify;
905 self.color = oldColor;
906}
907
908-(BOOL) doesOpacityModifyRGB
909{
910 return opacityModifyRGB_;
911}
912
913//
914// Frames
915//
916#pragma mark CCSprite - Frames
917
918-(void) setDisplayFrame:(CCSpriteFrame*)frame
919{
920 unflippedOffsetPositionFromCenter_ = frame.offsetInPixels;
921
922 CCTexture2D *newTexture = [frame texture];
923 // update texture before updating texture rect
924 if ( newTexture.name != texture_.name )
925 [self setTexture: newTexture];
926
927 // update rect
928 rectRotated_ = frame.rotated;
929 [self setTextureRectInPixels:frame.rectInPixels rotated:frame.rotated untrimmedSize:frame.originalSizeInPixels];
930}
931
932// XXX deprecated
933-(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex
934{
935 if( ! animations_ )
936 [self initAnimationDictionary];
937
938 CCAnimation *a = [animations_ objectForKey: animationName];
939 CCSpriteFrame *frame = [[a frames] objectAtIndex:frameIndex];
940
941 NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame");
942
943 [self setDisplayFrame:frame];
944}
945
946-(void) setDisplayFrameWithAnimationName: (NSString*) animationName index:(int) frameIndex
947{
948 NSAssert( animationName, @"CCSprite#setDisplayFrameWithAnimationName. animationName must not be nil");
949
950 CCAnimation *a = [[CCAnimationCache sharedAnimationCache] animationByName:animationName];
951
952 NSAssert( a, @"CCSprite#setDisplayFrameWithAnimationName: Frame not found");
953
954 CCSpriteFrame *frame = [[a frames] objectAtIndex:frameIndex];
955
956 NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame");
957
958 [self setDisplayFrame:frame];
959}
960
961
962-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame
963{
964 CGRect r = [frame rect];
965 return ( CGRectEqualToRect(r, rect_) &&
966 frame.texture.name == self.texture.name );
967}
968
969-(CCSpriteFrame*) displayedFrame
970{
971 return [CCSpriteFrame frameWithTexture:texture_
972 rectInPixels:rectInPixels_
973 rotated:rectRotated_
974 offset:unflippedOffsetPositionFromCenter_
975 originalSize:contentSizeInPixels_];
976}
977
978-(void) addAnimation: (CCAnimation*) anim
979{
980 // lazy alloc
981 if( ! animations_ )
982 [self initAnimationDictionary];
983
984 [animations_ setObject:anim forKey:[anim name]];
985}
986
987-(CCAnimation*)animationByName: (NSString*) animationName
988{
989 NSAssert( animationName != nil, @"animationName parameter must be non nil");
990 return [animations_ objectForKey:animationName];
991}
992
993#pragma mark CCSprite - CocosNodeTexture protocol
994
995-(void) updateBlendFunc
996{
997 NSAssert( ! usesBatchNode_, @"CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteBatchNode");
998
999 // it's possible to have an untextured sprite
1000 if( !texture_ || ! [texture_ hasPremultipliedAlpha] ) {
1001 blendFunc_.src = GL_SRC_ALPHA;
1002 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
1003 [self setOpacityModifyRGB:NO];
1004 } else {
1005 blendFunc_.src = CC_BLEND_SRC;
1006 blendFunc_.dst = CC_BLEND_DST;
1007 [self setOpacityModifyRGB:YES];
1008 }
1009}
1010
1011-(void) setTexture:(CCTexture2D*)texture
1012{
1013 NSAssert( ! usesBatchNode_, @"CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode");
1014
1015 // accept texture==nil as argument
1016 NSAssert( !texture || [texture isKindOfClass:[CCTexture2D class]], @"setTexture expects a CCTexture2D. Invalid argument");
1017
1018 [texture_ release];
1019 texture_ = [texture retain];
1020
1021 [self updateBlendFunc];
1022}
1023
1024-(CCTexture2D*) texture
1025{
1026 return texture_;
1027}
1028
1029@end
diff --git a/libs/cocos2d/CCSpriteBatchNode.h b/libs/cocos2d/CCSpriteBatchNode.h new file mode 100755 index 0000000..0342e24 --- /dev/null +++ b/libs/cocos2d/CCSpriteBatchNode.h
@@ -0,0 +1,145 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (C) 2009 Matt Oswald
5 *
6 * Copyright (c) 2009-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30#import "CCNode.h"
31#import "CCProtocols.h"
32#import "CCTextureAtlas.h"
33#import "ccMacros.h"
34
35#pragma mark CCSpriteBatchNode
36
37@class CCSprite;
38
39/** CCSpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call
40 * (often known as "batch draw").
41 *
42 * A CCSpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
43 * Only the CCSprites that are contained in that texture can be added to the CCSpriteBatchNode.
44 * All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call.
45 * If the CCSprites are not added to a CCSpriteBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient.
46 *
47 *
48 * Limitations:
49 * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is CCSprite or any subclass of CCSprite. eg: particles, labels and layer can't be added to a CCSpriteBatchNode.
50 * - Either all its children are Aliased or Antialiased. It can't be a mix. This is because "alias" is a property of the texture, and all the sprites share the same texture.
51 *
52 * @since v0.7.1
53 */
54@interface CCSpriteBatchNode : CCNode <CCTextureProtocol>
55{
56 CCTextureAtlas *textureAtlas_;
57 ccBlendFunc blendFunc_;
58
59 // all descendants: chlidren, gran children, etc...
60 CCArray *descendants_;
61}
62
63/** returns the TextureAtlas that is used */
64@property (nonatomic,readwrite,retain) CCTextureAtlas * textureAtlas;
65
66/** conforms to CCTextureProtocol protocol */
67@property (nonatomic,readwrite) ccBlendFunc blendFunc;
68
69/** descendants (children, gran children, etc) */
70@property (nonatomic,readonly) CCArray *descendants;
71
72/** creates a CCSpriteBatchNode with a texture2d and a default capacity of 29 children.
73 The capacity will be increased in 33% in runtime if it run out of space.
74 */
75+(id)batchNodeWithTexture:(CCTexture2D *)tex;
76+(id)spriteSheetWithTexture:(CCTexture2D *)tex DEPRECATED_ATTRIBUTE;
77
78/** creates a CCSpriteBatchNode with a texture2d and capacity of children.
79 The capacity will be increased in 33% in runtime if it run out of space.
80 */
81+(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
82+(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE;
83
84/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) with a default capacity of 29 children.
85 The capacity will be increased in 33% in runtime if it run out of space.
86 The file will be loaded using the TextureMgr.
87 */
88+(id)batchNodeWithFile:(NSString*) fileImage;
89+(id)spriteSheetWithFile:(NSString*) fileImage DEPRECATED_ATTRIBUTE;
90
91/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and capacity of children.
92 The capacity will be increased in 33% in runtime if it run out of space.
93 The file will be loaded using the TextureMgr.
94*/
95+(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity;
96+(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE;
97
98/** initializes a CCSpriteBatchNode with a texture2d and capacity of children.
99 The capacity will be increased in 33% in runtime if it run out of space.
100 */
101-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
102/** initializes a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
103 The capacity will be increased in 33% in runtime if it run out of space.
104 The file will be loaded using the TextureMgr.
105 */
106-(id)initWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity;
107
108-(void) increaseAtlasCapacity;
109
110/** creates an sprite with a rect in the CCSpriteBatchNode.
111 It's the same as:
112 - create an standard CCSsprite
113 - set the usingSpriteSheet = YES
114 - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode
115 @deprecated Use [CCSprite spriteWithBatchNode:rect:] instead;
116 */
117-(CCSprite*) createSpriteWithRect:(CGRect)rect DEPRECATED_ATTRIBUTE;
118
119/** initializes a previously created sprite with a rect. This sprite will have the same texture as the CCSpriteBatchNode.
120 It's the same as:
121 - initialize an standard CCSsprite
122 - set the usingBatchNode = YES
123 - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode
124 @since v0.99.0
125 @deprecated Use [CCSprite initWithBatchNode:rect:] instead;
126*/
127-(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect DEPRECATED_ATTRIBUTE;
128
129/** removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter.
130 @warning Removing a child from a CCSpriteBatchNode is very slow
131 */
132-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup;
133
134/** removes a child given a reference. It will also cleanup the running actions depending on the cleanup parameter.
135 @warning Removing a child from a CCSpriteBatchNode is very slow
136 */
137-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup;
138
139-(void) insertChild:(CCSprite*)child inAtlasAtIndex:(NSUInteger)index;
140-(void) removeSpriteFromAtlas:(CCSprite*)sprite;
141
142-(NSUInteger) rebuildIndexInOrder:(CCSprite*)parent atlasIndex:(NSUInteger)index;
143-(NSUInteger) atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z;
144
145@end
diff --git a/libs/cocos2d/CCSpriteBatchNode.m b/libs/cocos2d/CCSpriteBatchNode.m new file mode 100755 index 0000000..7c8b05b --- /dev/null +++ b/libs/cocos2d/CCSpriteBatchNode.m
@@ -0,0 +1,503 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (C) 2009 Matt Oswald
5 *
6 * Copyright (c) 2009-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 */
28
29
30#import "ccConfig.h"
31#import "CCSprite.h"
32#import "CCSpriteBatchNode.h"
33#import "CCGrid.h"
34#import "CCDrawingPrimitives.h"
35#import "CCTextureCache.h"
36#import "Support/CGPointExtension.h"
37
38const NSUInteger defaultCapacity = 29;
39
40#pragma mark -
41#pragma mark CCSpriteBatchNode
42
43static SEL selUpdate = NULL;
44
45@interface CCSpriteBatchNode (private)
46-(void) updateBlendFunc;
47@end
48
49@implementation CCSpriteBatchNode
50
51@synthesize textureAtlas = textureAtlas_;
52@synthesize blendFunc = blendFunc_;
53@synthesize descendants = descendants_;
54
55
56+(void) initialize
57{
58 if ( self == [CCSpriteBatchNode class] ) {
59 selUpdate = @selector(updateTransform);
60 }
61}
62/*
63 * creation with CCTexture2D
64 */
65+(id)batchNodeWithTexture:(CCTexture2D *)tex
66{
67 return [[[self alloc] initWithTexture:tex capacity:defaultCapacity] autorelease];
68}
69+(id)spriteSheetWithTexture:(CCTexture2D *)tex // XXX DEPRECATED
70{
71 return [self batchNodeWithTexture:tex];
72}
73
74+(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity
75{
76 return [[[self alloc] initWithTexture:tex capacity:capacity] autorelease];
77}
78+(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity // XXX DEPRECATED
79{
80 return [self batchNodeWithTexture:tex capacity:capacity];
81}
82
83/*
84 * creation with File Image
85 */
86+(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity
87{
88 return [[[self alloc] initWithFile:fileImage capacity:capacity] autorelease];
89}
90+(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity // XXX DEPRECATED
91{
92 return [self batchNodeWithFile:fileImage capacity:capacity];
93}
94
95+(id)batchNodeWithFile:(NSString*) imageFile
96{
97 return [[[self alloc] initWithFile:imageFile capacity:defaultCapacity] autorelease];
98}
99+(id)spriteSheetWithFile:(NSString*) imageFile // XXX DEPRECATED
100{
101 return [self batchNodeWithFile:imageFile];
102}
103
104
105/*
106 * init with CCTexture2D
107 */
108-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity
109{
110 if( (self=[super init])) {
111
112 blendFunc_.src = CC_BLEND_SRC;
113 blendFunc_.dst = CC_BLEND_DST;
114 textureAtlas_ = [[CCTextureAtlas alloc] initWithTexture:tex capacity:capacity];
115
116 [self updateBlendFunc];
117
118 // no lazy alloc in this node
119 children_ = [[CCArray alloc] initWithCapacity:capacity];
120 descendants_ = [[CCArray alloc] initWithCapacity:capacity];
121 }
122
123 return self;
124}
125
126/*
127 * init with FileImage
128 */
129-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity
130{
131 CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:fileImage];
132 return [self initWithTexture:tex capacity:capacity];
133}
134
135- (NSString*) description
136{
137 return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_ ];
138}
139
140-(void)dealloc
141{
142 [textureAtlas_ release];
143 [descendants_ release];
144
145 [super dealloc];
146}
147
148#pragma mark CCSpriteBatchNode - composition
149
150// override visit.
151// Don't call visit on it's children
152-(void) visit
153{
154
155 // CAREFUL:
156 // This visit is almost identical to CocosNode#visit
157 // with the exception that it doesn't call visit on it's children
158 //
159 // The alternative is to have a void CCSprite#visit, but
160 // although this is less mantainable, is faster
161 //
162 if (!visible_)
163 return;
164
165 glPushMatrix();
166
167 if ( grid_ && grid_.active) {
168 [grid_ beforeDraw];
169 [self transformAncestors];
170 }
171
172 [self transform];
173
174 [self draw];
175
176 if ( grid_ && grid_.active)
177 [grid_ afterDraw:self];
178
179 glPopMatrix();
180}
181
182// XXX deprecated
183-(CCSprite*) createSpriteWithRect:(CGRect)rect
184{
185 CCSprite *sprite = [CCSprite spriteWithTexture:textureAtlas_.texture rect:rect];
186 [sprite useBatchNode:self];
187
188 return sprite;
189}
190
191// XXX deprecated
192-(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect
193{
194 [sprite initWithTexture:textureAtlas_.texture rect:rect];
195 [sprite useBatchNode:self];
196}
197
198// override addChild:
199-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag
200{
201 NSAssert( child != nil, @"Argument must be non-nil");
202 NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children");
203 NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCSprite is not using the same texture id");
204
205 [super addChild:child z:z tag:aTag];
206
207 NSUInteger index = [self atlasIndexForChild:child atZ:z];
208 [self insertChild:child inAtlasAtIndex:index];
209}
210
211// override reorderChild
212-(void) reorderChild:(CCSprite*)child z:(NSInteger)z
213{
214 NSAssert( child != nil, @"Child must be non-nil");
215 NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" );
216
217 if( z == child.zOrder )
218 return;
219
220 // XXX: Instead of removing/adding, it is more efficient to reorder manually
221 [child retain];
222 [self removeChild:child cleanup:NO];
223 [self addChild:child z:z];
224 [child release];
225}
226
227// override removeChild:
228-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup
229{
230 // explicit nil handling
231 if (sprite == nil)
232 return;
233
234 NSAssert([children_ containsObject:sprite], @"CCSpriteBatchNode doesn't contain the sprite. Can't remove it");
235
236 // cleanup before removing
237 [self removeSpriteFromAtlas:sprite];
238
239 [super removeChild:sprite cleanup:doCleanup];
240}
241
242-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup
243{
244 [self removeChild:(CCSprite *)[children_ objectAtIndex:index] cleanup:doCleanup];
245}
246
247-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup
248{
249 // Invalidate atlas index. issue #569
250 [children_ makeObjectsPerformSelector:@selector(useSelfRender)];
251
252 [super removeAllChildrenWithCleanup:doCleanup];
253
254 [descendants_ removeAllObjects];
255 [textureAtlas_ removeAllQuads];
256}
257
258#pragma mark CCSpriteBatchNode - draw
259-(void) draw
260{
261 [super draw];
262
263 // Optimization: Fast Dispatch
264 if( textureAtlas_.totalQuads == 0 )
265 return;
266
267 CCSprite *child;
268 ccArray *array = descendants_->data;
269
270 NSUInteger i = array->num;
271 id *arr = array->arr;
272
273 if( i > 0 ) {
274
275 while (i-- > 0) {
276 child = *arr++;
277
278 // fast dispatch
279 child->updateMethod(child, selUpdate);
280
281#if CC_SPRITEBATCHNODE_DEBUG_DRAW
282 //Issue #528
283 CGRect rect = [child boundingBox];
284 CGPoint vertices[4]={
285 ccp(rect.origin.x,rect.origin.y),
286 ccp(rect.origin.x+rect.size.width,rect.origin.y),
287 ccp(rect.origin.x+rect.size.width,rect.origin.y+rect.size.height),
288 ccp(rect.origin.x,rect.origin.y+rect.size.height),
289 };
290 ccDrawPoly(vertices, 4, YES);
291#endif // CC_SPRITEBATCHNODE_DEBUG_DRAW
292 }
293 }
294
295 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
296 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
297 // Unneeded states: -
298
299 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
300 if( newBlend )
301 glBlendFunc( blendFunc_.src, blendFunc_.dst );
302
303 [textureAtlas_ drawQuads];
304 if( newBlend )
305 glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
306}
307
308#pragma mark CCSpriteBatchNode - private
309-(void) increaseAtlasCapacity
310{
311 // if we're going beyond the current TextureAtlas's capacity,
312 // all the previously initialized sprites will need to redo their texture coords
313 // this is likely computationally expensive
314 NSUInteger quantity = (textureAtlas_.capacity + 1) * 4 / 3;
315
316 CCLOG(@"cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu].",
317 (long)textureAtlas_.capacity,
318 (long)quantity);
319
320
321 if( ! [textureAtlas_ resizeCapacity:quantity] ) {
322 // serious problems
323 CCLOG(@"cocos2d: WARNING: Not enough memory to resize the atlas");
324 NSAssert(NO,@"XXX: SpriteSheet#increaseAtlasCapacity SHALL handle this assert");
325 }
326}
327
328
329#pragma mark CCSpriteBatchNode - Atlas Index Stuff
330
331-(NSUInteger) rebuildIndexInOrder:(CCSprite*)node atlasIndex:(NSUInteger)index
332{
333 CCSprite *sprite;
334 CCARRAY_FOREACH(node.children, sprite){
335 if( sprite.zOrder < 0 )
336 index = [self rebuildIndexInOrder:sprite atlasIndex:index];
337 }
338
339 // ignore self (batch node)
340 if( ! [node isEqual:self]) {
341 node.atlasIndex = index;
342 index++;
343 }
344
345 CCARRAY_FOREACH(node.children, sprite){
346 if( sprite.zOrder >= 0 )
347 index = [self rebuildIndexInOrder:sprite atlasIndex:index];
348 }
349
350 return index;
351}
352
353-(NSUInteger) highestAtlasIndexInChild:(CCSprite*)sprite
354{
355 CCArray *array = [sprite children];
356 NSUInteger count = [array count];
357 if( count == 0 )
358 return sprite.atlasIndex;
359 else
360 return [self highestAtlasIndexInChild:[array lastObject]];
361}
362
363-(NSUInteger) lowestAtlasIndexInChild:(CCSprite*)sprite
364{
365 CCArray *array = [sprite children];
366 NSUInteger count = [array count];
367 if( count == 0 )
368 return sprite.atlasIndex;
369 else
370 return [self lowestAtlasIndexInChild:[array objectAtIndex:0] ];
371}
372
373
374-(NSUInteger)atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z
375{
376 CCArray *brothers = [[sprite parent] children];
377 NSUInteger childIndex = [brothers indexOfObject:sprite];
378
379 // ignore parent Z if parent is batchnode
380 BOOL ignoreParent = ( sprite.parent == self );
381 CCSprite *previous = nil;
382 if( childIndex > 0 )
383 previous = [brothers objectAtIndex:childIndex-1];
384
385 // first child of the sprite sheet
386 if( ignoreParent ) {
387 if( childIndex == 0 )
388 return 0;
389 // else
390 return [self highestAtlasIndexInChild: previous] + 1;
391 }
392
393 // parent is a CCSprite, so, it must be taken into account
394
395 // first child of an CCSprite ?
396 if( childIndex == 0 )
397 {
398 CCSprite *p = (CCSprite*) sprite.parent;
399
400 // less than parent and brothers
401 if( z < 0 )
402 return p.atlasIndex;
403 else
404 return p.atlasIndex+1;
405
406 } else {
407 // previous & sprite belong to the same branch
408 if( ( previous.zOrder < 0 && z < 0 )|| (previous.zOrder >= 0 && z >= 0) )
409 return [self highestAtlasIndexInChild:previous] + 1;
410
411 // else (previous < 0 and sprite >= 0 )
412 CCSprite *p = (CCSprite*) sprite.parent;
413 return p.atlasIndex + 1;
414 }
415
416 NSAssert( NO, @"Should not happen. Error calculating Z on Batch Node");
417 return 0;
418}
419
420#pragma mark CCSpriteBatchNode - add / remove / reorder helper methods
421// add child helper
422-(void) insertChild:(CCSprite*)sprite inAtlasAtIndex:(NSUInteger)index
423{
424 [sprite useBatchNode:self];
425 [sprite setAtlasIndex:index];
426 [sprite setDirty: YES];
427
428 if(textureAtlas_.totalQuads == textureAtlas_.capacity)
429 [self increaseAtlasCapacity];
430
431 ccV3F_C4B_T2F_Quad quad = [sprite quad];
432 [textureAtlas_ insertQuad:&quad atIndex:index];
433
434 ccArray *descendantsData = descendants_->data;
435
436 ccArrayInsertObjectAtIndex(descendantsData, sprite, index);
437
438 // update indices
439 NSUInteger i = index+1;
440 CCSprite *child;
441 for(; i<descendantsData->num; i++){
442 child = descendantsData->arr[i];
443 child.atlasIndex = child.atlasIndex + 1;
444 }
445
446 // add children recursively
447 CCARRAY_FOREACH(sprite.children, child){
448 NSUInteger idx = [self atlasIndexForChild:child atZ: child.zOrder];
449 [self insertChild:child inAtlasAtIndex:idx];
450 }
451}
452
453// remove child helper
454-(void) removeSpriteFromAtlas:(CCSprite*)sprite
455{
456 // remove from TextureAtlas
457 [textureAtlas_ removeQuadAtIndex:sprite.atlasIndex];
458
459 // Cleanup sprite. It might be reused (issue #569)
460 [sprite useSelfRender];
461
462 ccArray *descendantsData = descendants_->data;
463 NSUInteger index = ccArrayGetIndexOfObject(descendantsData, sprite);
464 if( index != NSNotFound ) {
465 ccArrayRemoveObjectAtIndex(descendantsData, index);
466
467 // update all sprites beyond this one
468 NSUInteger count = descendantsData->num;
469
470 for(; index < count; index++)
471 {
472 CCSprite *s = descendantsData->arr[index];
473 s.atlasIndex = s.atlasIndex - 1;
474 }
475 }
476
477 // remove children recursively
478 CCSprite *child;
479 CCARRAY_FOREACH(sprite.children, child)
480 [self removeSpriteFromAtlas:child];
481}
482
483#pragma mark CCSpriteBatchNode - CocosNodeTexture protocol
484
485-(void) updateBlendFunc
486{
487 if( ! [textureAtlas_.texture hasPremultipliedAlpha] ) {
488 blendFunc_.src = GL_SRC_ALPHA;
489 blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
490 }
491}
492
493-(void) setTexture:(CCTexture2D*)texture
494{
495 textureAtlas_.texture = texture;
496 [self updateBlendFunc];
497}
498
499-(CCTexture2D*) texture
500{
501 return textureAtlas_.texture;
502}
503@end
diff --git a/libs/cocos2d/CCSpriteFrame.h b/libs/cocos2d/CCSpriteFrame.h new file mode 100755 index 0000000..983aeed --- /dev/null +++ b/libs/cocos2d/CCSpriteFrame.h
@@ -0,0 +1,90 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Foundation/Foundation.h>
28#import "CCNode.h"
29#import "CCProtocols.h"
30
31/** A CCSpriteFrame has:
32 - texture: A CCTexture2D that will be used by the CCSprite
33 - rectangle: A rectangle of the texture
34
35
36 You can modify the frame of a CCSprite by doing:
37
38 CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect offset:offset];
39 [sprite setDisplayFrame:frame];
40 */
41@interface CCSpriteFrame : NSObject <NSCopying>
42{
43 CGRect rect_;
44 CGRect rectInPixels_;
45 BOOL rotated_;
46 CGPoint offsetInPixels_;
47 CGSize originalSizeInPixels_;
48 CCTexture2D *texture_;
49}
50/** rect of the frame in points. If it is updated, then rectInPixels will be updated too. */
51@property (nonatomic,readwrite) CGRect rect;
52
53/** rect of the frame in pixels. If it is updated, then rect (points) will be udpated too. */
54@property (nonatomic,readwrite) CGRect rectInPixels;
55
56/** whether or not the rect of the frame is rotated ( x = x+width, y = y+height, width = height, height = width ) */
57@property (nonatomic,readwrite) BOOL rotated;
58
59/** offset of the frame in pixels */
60@property (nonatomic,readwrite) CGPoint offsetInPixels;
61
62/** original size of the trimmed image in pixels */
63@property (nonatomic,readwrite) CGSize originalSizeInPixels;
64
65/** texture of the frame */
66@property (nonatomic, retain, readwrite) CCTexture2D *texture;
67
68/** Create a CCSpriteFrame with a texture, rect in points.
69 It is assumed that the frame was not trimmed.
70 */
71+(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
72
73/** Create a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
74 The originalSize is the size in points of the frame before being trimmed.
75 */
76+(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize;
77
78
79/** Initializes a CCSpriteFrame with a texture, rect in points;
80 It is assumed that the frame was not trimmed.
81 */
82-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
83
84/** Initializes a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
85 The originalSize is the size in points of the frame before being trimmed.
86 */
87-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize;
88
89@end
90
diff --git a/libs/cocos2d/CCSpriteFrame.m b/libs/cocos2d/CCSpriteFrame.m new file mode 100755 index 0000000..e9ebd04 --- /dev/null +++ b/libs/cocos2d/CCSpriteFrame.m
@@ -0,0 +1,111 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCTextureCache.h"
29#import "CCSpriteFrame.h"
30#import "ccMacros.h"
31
32@implementation CCSpriteFrame
33@synthesize rotated = rotated_, offsetInPixels = offsetInPixels_, texture = texture_;
34@synthesize originalSizeInPixels=originalSizeInPixels_;
35
36+(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
37{
38 return [[[self alloc] initWithTexture:texture rect:rect] autorelease];
39}
40
41+(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
42{
43 return [[[self alloc] initWithTexture:texture rectInPixels:rect rotated:rotated offset:offset originalSize:originalSize] autorelease];
44}
45
46-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
47{
48 CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect );
49 return [self initWithTexture:texture rectInPixels:rectInPixels rotated:NO offset:CGPointZero originalSize:rectInPixels.size];
50}
51
52-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
53{
54 if( (self=[super init]) ) {
55 self.texture = texture;
56 rectInPixels_ = rect;
57 rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
58 rotated_ = rotated;
59 offsetInPixels_ = offset;
60 originalSizeInPixels_ = originalSize;
61 }
62 return self;
63}
64
65- (NSString*) description
66{
67 return [NSString stringWithFormat:@"<%@ = %08X | TextureName=%d, Rect = (%.2f,%.2f,%.2f,%.2f)> rotated:%d", [self class], self,
68 texture_.name,
69 rect_.origin.x,
70 rect_.origin.y,
71 rect_.size.width,
72 rect_.size.height,
73 rotated_
74 ];
75}
76
77- (void) dealloc
78{
79 CCLOGINFO( @"cocos2d: deallocing %@",self);
80 [texture_ release];
81 [super dealloc];
82}
83
84-(id) copyWithZone: (NSZone*) zone
85{
86 CCSpriteFrame *copy = [[[self class] allocWithZone: zone] initWithTexture:texture_ rectInPixels:rectInPixels_ rotated:rotated_ offset:offsetInPixels_ originalSize:originalSizeInPixels_];
87 return copy;
88}
89
90-(CGRect) rect
91{
92 return rect_;
93}
94
95-(CGRect) rectInPixels
96{
97 return rectInPixels_;
98}
99
100-(void) setRect:(CGRect)rect
101{
102 rect_ = rect;
103 rectInPixels_ = CC_RECT_POINTS_TO_PIXELS( rect_ );
104}
105
106-(void) setRectInPixels:(CGRect)rectInPixels
107{
108 rectInPixels_ = rectInPixels;
109 rect_ = CC_RECT_PIXELS_TO_POINTS(rectInPixels);
110}
111@end
diff --git a/libs/cocos2d/CCSpriteFrameCache.h b/libs/cocos2d/CCSpriteFrameCache.h new file mode 100755 index 0000000..d3119a6 --- /dev/null +++ b/libs/cocos2d/CCSpriteFrameCache.h
@@ -0,0 +1,137 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Jason Booth
5 *
6 * Copyright (c) 2009 Robert J Payne
7 *
8 * Copyright (c) 2008-2010 Ricardo Quesada
9 * Copyright (c) 2011 Zynga Inc.
10 *
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 * THE SOFTWARE.
29 *
30 */
31
32
33/*
34 * To create sprite frames and texture atlas, use this tool:
35 * http://zwoptex.zwopple.com/
36 */
37
38#import <Foundation/Foundation.h>
39
40#import "CCSpriteFrame.h"
41#import "CCTexture2D.h"
42
43@class CCSprite;
44
45/** Singleton that handles the loading of the sprite frames.
46 It saves in a cache the sprite frames.
47 @since v0.9
48 */
49@interface CCSpriteFrameCache : NSObject
50{
51 NSMutableDictionary *spriteFrames_;
52 NSMutableDictionary *spriteFramesAliases_;
53}
54
55/** Retruns ths shared instance of the Sprite Frame cache */
56+ (CCSpriteFrameCache *) sharedSpriteFrameCache;
57
58/** Purges the cache. It releases all the Sprite Frames and the retained instance.
59 */
60+(void)purgeSharedSpriteFrameCache;
61
62
63/** Adds multiple Sprite Frames with a dictionary. The texture will be associated with the created sprite frames.
64 */
65-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture;
66
67/** Adds multiple Sprite Frames from a plist file.
68 * A texture will be loaded automatically. The texture name will composed by replacing the .plist suffix with .png
69 * If you want to use another texture, you should use the addSpriteFramesWithFile:texture method.
70 */
71-(void) addSpriteFramesWithFile:(NSString*)plist;
72
73/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
74 */
75-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture;
76
77/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
78 @since v0.99.5
79 */
80-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName;
81
82/** Adds an sprite frame with a given name.
83 If the name already exists, then the contents of the old name will be replaced with the new one.
84 */
85-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName;
86
87
88/** Purges the dictionary of loaded sprite frames.
89 * Call this method if you receive the "Memory Warning".
90 * In the short term: it will free some resources preventing your app from being killed.
91 * In the medium term: it will allocate more resources.
92 * In the long term: it will be the same.
93 */
94-(void) removeSpriteFrames;
95
96/** Removes unused sprite frames.
97 * Sprite Frames that have a retain count of 1 will be deleted.
98 * It is convinient to call this method after when starting a new Scene.
99 */
100-(void) removeUnusedSpriteFrames;
101
102/** Deletes an sprite frame from the sprite frame cache.
103 */
104-(void) removeSpriteFrameByName:(NSString*)name;
105
106/** Removes multiple Sprite Frames from a plist file.
107* Sprite Frames stored in this file will be removed.
108* It is convinient to call this method when a specific texture needs to be removed.
109* @since v0.99.5
110*/
111- (void) removeSpriteFramesFromFile:(NSString*) plist;
112
113/** Removes multiple Sprite Frames from NSDictionary.
114 * @since v0.99.5
115 */
116- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary;
117
118/** Removes all Sprite Frames associated with the specified textures.
119 * It is convinient to call this method when a specific texture needs to be removed.
120 * @since v0.995.
121 */
122- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture;
123
124/** Returns an Sprite Frame that was previously added.
125 If the name is not found it will return nil.
126 You should retain the returned copy if you are going to use it.
127 */
128-(CCSpriteFrame*) spriteFrameByName:(NSString*)name;
129
130/** Creates an sprite with the name of an sprite frame.
131 The created sprite will contain the texture, rect and offset of the sprite frame.
132 It returns an autorelease object.
133 @deprecated use [CCSprite spriteWithSpriteFrameName:name]. This method will be removed on final v0.9
134 */
135-(CCSprite*) createSpriteWithFrameName:(NSString*)name DEPRECATED_ATTRIBUTE;
136
137@end
diff --git a/libs/cocos2d/CCSpriteFrameCache.m b/libs/cocos2d/CCSpriteFrameCache.m new file mode 100755 index 0000000..f154c3d --- /dev/null +++ b/libs/cocos2d/CCSpriteFrameCache.m
@@ -0,0 +1,347 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Jason Booth
5 *
6 * Copyright (c) 2009 Robert J Payne
7 *
8 * Copyright (c) 2008-2010 Ricardo Quesada
9 * Copyright (c) 2011 Zynga Inc.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 */
30
31/*
32 * To create sprite frames and texture atlas, use this tool:
33 * http://zwoptex.zwopple.com/
34 */
35
36#import "Platforms/CCNS.h"
37#import "ccMacros.h"
38#import "CCTextureCache.h"
39#import "CCSpriteFrameCache.h"
40#import "CCSpriteFrame.h"
41#import "CCSprite.h"
42#import "Support/CCFileUtils.h"
43
44
45@implementation CCSpriteFrameCache
46
47#pragma mark CCSpriteFrameCache - Alloc, Init & Dealloc
48
49static CCSpriteFrameCache *sharedSpriteFrameCache_=nil;
50
51+ (CCSpriteFrameCache *)sharedSpriteFrameCache
52{
53 if (!sharedSpriteFrameCache_)
54 sharedSpriteFrameCache_ = [[CCSpriteFrameCache alloc] init];
55
56 return sharedSpriteFrameCache_;
57}
58
59+(id)alloc
60{
61 NSAssert(sharedSpriteFrameCache_ == nil, @"Attempted to allocate a second instance of a singleton.");
62 return [super alloc];
63}
64
65+(void)purgeSharedSpriteFrameCache
66{
67 [sharedSpriteFrameCache_ release];
68 sharedSpriteFrameCache_ = nil;
69}
70
71-(id) init
72{
73 if( (self=[super init]) ) {
74 spriteFrames_ = [[NSMutableDictionary alloc] initWithCapacity: 100];
75 spriteFramesAliases_ = [[NSMutableDictionary alloc] initWithCapacity:10];
76 }
77
78 return self;
79}
80
81- (NSString*) description
82{
83 return [NSString stringWithFormat:@"<%@ = %08X | num of sprite frames = %i>", [self class], self, [spriteFrames_ count]];
84}
85
86-(void) dealloc
87{
88 CCLOGINFO(@"cocos2d: deallocing %@", self);
89
90 [spriteFrames_ release];
91 [spriteFramesAliases_ release];
92 [super dealloc];
93}
94
95#pragma mark CCSpriteFrameCache - loading sprite frames
96
97-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture
98{
99 /*
100 Supported Zwoptex Formats:
101 ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version
102 ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b
103 ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1
104 ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+
105 */
106 NSDictionary *metadataDict = [dictionary objectForKey:@"metadata"];
107 NSDictionary *framesDict = [dictionary objectForKey:@"frames"];
108
109 int format = 0;
110
111 // get the format
112 if(metadataDict != nil)
113 format = [[metadataDict objectForKey:@"format"] intValue];
114
115 // check the format
116 NSAssert( format >= 0 && format <= 3, @"cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:");
117
118
119 // add real frames
120 for(NSString *frameDictKey in framesDict) {
121 NSDictionary *frameDict = [framesDict objectForKey:frameDictKey];
122 CCSpriteFrame *spriteFrame;
123 if(format == 0) {
124 float x = [[frameDict objectForKey:@"x"] floatValue];
125 float y = [[frameDict objectForKey:@"y"] floatValue];
126 float w = [[frameDict objectForKey:@"width"] floatValue];
127 float h = [[frameDict objectForKey:@"height"] floatValue];
128 float ox = [[frameDict objectForKey:@"offsetX"] floatValue];
129 float oy = [[frameDict objectForKey:@"offsetY"] floatValue];
130 int ow = [[frameDict objectForKey:@"originalWidth"] intValue];
131 int oh = [[frameDict objectForKey:@"originalHeight"] intValue];
132 // check ow/oh
133 if(!ow || !oh)
134 CCLOG(@"cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist");
135
136 // abs ow/oh
137 ow = abs(ow);
138 oh = abs(oh);
139 // create frame
140
141 spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
142 rectInPixels:CGRectMake(x, y, w, h)
143 rotated:NO
144 offset:CGPointMake(ox, oy)
145 originalSize:CGSizeMake(ow, oh)];
146 } else if(format == 1 || format == 2) {
147 CGRect frame = CCRectFromString([frameDict objectForKey:@"frame"]);
148 BOOL rotated = NO;
149
150 // rotation
151 if(format == 2)
152 rotated = [[frameDict objectForKey:@"rotated"] boolValue];
153
154 CGPoint offset = CCPointFromString([frameDict objectForKey:@"offset"]);
155 CGSize sourceSize = CCSizeFromString([frameDict objectForKey:@"sourceSize"]);
156
157 // create frame
158 spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
159 rectInPixels:frame
160 rotated:rotated
161 offset:offset
162 originalSize:sourceSize];
163 } else if(format == 3) {
164 // get values
165 CGSize spriteSize = CCSizeFromString([frameDict objectForKey:@"spriteSize"]);
166 CGPoint spriteOffset = CCPointFromString([frameDict objectForKey:@"spriteOffset"]);
167 CGSize spriteSourceSize = CCSizeFromString([frameDict objectForKey:@"spriteSourceSize"]);
168 CGRect textureRect = CCRectFromString([frameDict objectForKey:@"textureRect"]);
169 BOOL textureRotated = [[frameDict objectForKey:@"textureRotated"] boolValue];
170
171 // get aliases
172 NSArray *aliases = [frameDict objectForKey:@"aliases"];
173 for(NSString *alias in aliases) {
174 if( [spriteFramesAliases_ objectForKey:alias] )
175 CCLOG(@"cocos2d: WARNING: an alias with name %@ already exists",alias);
176
177 [spriteFramesAliases_ setObject:frameDictKey forKey:alias];
178 }
179
180 // create frame
181 spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
182 rectInPixels:CGRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height)
183 rotated:textureRotated
184 offset:spriteOffset
185 originalSize:spriteSourceSize];
186 }
187
188 // add sprite frame
189 [spriteFrames_ setObject:spriteFrame forKey:frameDictKey];
190 [spriteFrame release];
191 }
192}
193
194-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture
195{
196 NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
197 NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
198
199 [self addSpriteFramesWithDictionary:dict texture:texture];
200}
201
202-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName
203{
204 NSAssert( textureFileName, @"Invalid texture file name");
205 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:textureFileName];
206
207 if( texture )
208 [self addSpriteFramesWithFile:plist texture:texture];
209 else
210 CCLOG(@"cocos2d: CCSpriteFrameCache: couldn't load texture file. File not found: %@", textureFileName);
211}
212
213-(void) addSpriteFramesWithFile:(NSString*)plist
214{
215 NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
216 NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
217
218 NSString *texturePath = nil;
219 NSDictionary *metadataDict = [dict objectForKey:@"metadata"];
220 if( metadataDict )
221 // try to read texture file name from meta data
222 texturePath = [metadataDict objectForKey:@"textureFileName"];
223
224
225 if( texturePath )
226 {
227 // build texture path relative to plist file
228 NSString *textureBase = [plist stringByDeletingLastPathComponent];
229 texturePath = [textureBase stringByAppendingPathComponent:texturePath];
230 } else {
231 // build texture path by replacing file extension
232 texturePath = [plist stringByDeletingPathExtension];
233 texturePath = [texturePath stringByAppendingPathExtension:@"png"];
234
235 CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath);
236 }
237
238 CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:texturePath];
239
240 if( texture )
241 [self addSpriteFramesWithDictionary:dict texture:texture];
242
243 else
244 CCLOG(@"cocos2d: CCSpriteFrameCache: Couldn't load texture");
245}
246
247-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName
248{
249 [spriteFrames_ setObject:frame forKey:frameName];
250}
251
252#pragma mark CCSpriteFrameCache - removing
253
254-(void) removeSpriteFrames
255{
256 [spriteFrames_ removeAllObjects];
257 [spriteFramesAliases_ removeAllObjects];
258}
259
260-(void) removeUnusedSpriteFrames
261{
262 NSArray *keys = [spriteFrames_ allKeys];
263 for( id key in keys ) {
264 id value = [spriteFrames_ objectForKey:key];
265 if( [value retainCount] == 1 ) {
266 CCLOG(@"cocos2d: CCSpriteFrameCache: removing unused frame: %@", key);
267 [spriteFrames_ removeObjectForKey:key];
268 }
269 }
270}
271
272-(void) removeSpriteFrameByName:(NSString*)name
273{
274 // explicit nil handling
275 if( ! name )
276 return;
277
278 // Is this an alias ?
279 NSString *key = [spriteFramesAliases_ objectForKey:name];
280
281 if( key ) {
282 [spriteFrames_ removeObjectForKey:key];
283 [spriteFramesAliases_ removeObjectForKey:name];
284
285 } else
286 [spriteFrames_ removeObjectForKey:name];
287}
288
289- (void) removeSpriteFramesFromFile:(NSString*) plist
290{
291 NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
292 NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
293
294 [self removeSpriteFramesFromDictionary:dict];
295}
296
297- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary
298{
299 NSDictionary *framesDict = [dictionary objectForKey:@"frames"];
300 NSMutableArray *keysToRemove=[NSMutableArray array];
301
302 for(NSString *frameDictKey in framesDict)
303 {
304 if ([spriteFrames_ objectForKey:frameDictKey]!=nil)
305 [keysToRemove addObject:frameDictKey];
306 }
307 [spriteFrames_ removeObjectsForKeys:keysToRemove];
308}
309
310- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture
311{
312 NSMutableArray *keysToRemove=[NSMutableArray array];
313
314 for (NSString *spriteFrameKey in spriteFrames_)
315 {
316 if ([[spriteFrames_ valueForKey:spriteFrameKey] texture] == texture)
317 [keysToRemove addObject:spriteFrameKey];
318
319 }
320 [spriteFrames_ removeObjectsForKeys:keysToRemove];
321}
322
323#pragma mark CCSpriteFrameCache - getting
324
325-(CCSpriteFrame*) spriteFrameByName:(NSString*)name
326{
327 CCSpriteFrame *frame = [spriteFrames_ objectForKey:name];
328 if( ! frame ) {
329 // try alias dictionary
330 NSString *key = [spriteFramesAliases_ objectForKey:name];
331 frame = [spriteFrames_ objectForKey:key];
332
333 if( ! frame )
334 CCLOG(@"cocos2d: CCSpriteFrameCache: Frame '%@' not found", name);
335 }
336
337 return frame;
338}
339
340#pragma mark CCSpriteFrameCache - sprite creation
341
342-(CCSprite*) createSpriteWithFrameName:(NSString*)name
343{
344 CCSpriteFrame *frame = [spriteFrames_ objectForKey:name];
345 return [CCSprite spriteWithSpriteFrame:frame];
346}
347@end
diff --git a/libs/cocos2d/CCTMXLayer.h b/libs/cocos2d/CCTMXLayer.h new file mode 100755 index 0000000..477a380 --- /dev/null +++ b/libs/cocos2d/CCTMXLayer.h
@@ -0,0 +1,152 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31
32#import "CCAtlasNode.h"
33#import "CCSpriteBatchNode.h"
34
35
36@class CCTMXMapInfo;
37@class CCTMXLayerInfo;
38@class CCTMXTilesetInfo;
39
40/** CCTMXLayer represents the TMX layer.
41
42 It is a subclass of CCSpriteBatchNode. By default the tiles are rendered using a CCTextureAtlas.
43 If you mofify a tile on runtime, then, that tile will become a CCSprite, otherwise no CCSprite objects are created.
44 The benefits of using CCSprite objects as tiles are:
45 - tiles (CCSprite) can be rotated/scaled/moved with a nice API
46
47 If the layer contains a property named "cc_vertexz" with an integer (in can be positive or negative),
48 then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
49
50 On the other hand, if the "cc_vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
51 Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be:
52
53 glAlphaFunc( GL_GREATER, value )
54
55 "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
56 The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a differnt
57 value, like 0.5.
58
59 For further information, please see the programming guide:
60
61 http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps
62
63 @since v0.8.1
64 */
65@interface CCTMXLayer : CCSpriteBatchNode
66{
67 CCTMXTilesetInfo *tileset_;
68 NSString *layerName_;
69 CGSize layerSize_;
70 CGSize mapTileSize_;
71 uint32_t *tiles_; // GID are 32 bit
72 NSUInteger layerOrientation_;
73 NSMutableArray *properties_;
74
75 unsigned char opacity_; // TMX Layer supports opacity
76
77 NSUInteger minGID_;
78 NSUInteger maxGID_;
79
80 // Only used when vertexZ is used
81 NSInteger vertexZvalue_;
82 BOOL useAutomaticVertexZ_;
83 float alphaFuncValue_;
84
85 // used for optimization
86 CCSprite *reusedTile_;
87 ccCArray *atlasIndexArray_;
88}
89/** name of the layer */
90@property (nonatomic,readwrite,retain) NSString *layerName;
91/** size of the layer in tiles */
92@property (nonatomic,readwrite) CGSize layerSize;
93/** size of the map's tile (could be differnt from the tile's size) */
94@property (nonatomic,readwrite) CGSize mapTileSize;
95/** pointer to the map of tiles */
96@property (nonatomic,readwrite) uint32_t *tiles;
97/** Tilset information for the layer */
98@property (nonatomic,readwrite,retain) CCTMXTilesetInfo *tileset;
99/** Layer orientation, which is the same as the map orientation */
100@property (nonatomic,readwrite) NSUInteger layerOrientation;
101/** properties from the layer. They can be added using Tiled */
102@property (nonatomic,readwrite,retain) NSMutableArray *properties;
103
104/** creates a CCTMXLayer with an tileset info, a layer info and a map info */
105+(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo;
106/** initializes a CCTMXLayer with a tileset info, a layer info and a map info */
107-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo;
108
109/** dealloc the map that contains the tile position from memory.
110 Unless you want to know at runtime the tiles positions, you can safely call this method.
111 If you are going to call [layer tileGIDAt:] then, don't release the map
112 */
113-(void) releaseMap;
114
115/** returns the tile (CCSprite) at a given a tile coordinate.
116 The returned CCSprite will be already added to the CCTMXLayer. Don't add it again.
117 The CCSprite can be treated like any other CCSprite: rotated, scaled, translated, opacity, color, etc.
118 You can remove either by calling:
119 - [layer removeChild:sprite cleanup:cleanup];
120 - or [layer removeTileAt:ccp(x,y)];
121 */
122-(CCSprite*) tileAt:(CGPoint)tileCoordinate;
123
124/** returns the tile gid at a given tile coordinate.
125 if it returns 0, it means that the tile is empty.
126 This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap])
127 */
128-(uint32_t) tileGIDAt:(CGPoint)tileCoordinate;
129
130/** sets the tile gid (gid = tile global id) at a given tile coordinate.
131 The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
132 If a tile is already placed at that position, then it will be removed.
133 */
134-(void) setTileGID:(uint32_t)gid at:(CGPoint)tileCoordinate;
135
136/** removes a tile at given tile coordinate */
137-(void) removeTileAt:(CGPoint)tileCoordinate;
138
139/** returns the position in pixels of a given tile coordinate */
140-(CGPoint) positionAt:(CGPoint)tileCoordinate;
141
142/** return the value for the specific property name */
143-(id) propertyNamed:(NSString *)propertyName;
144
145/** Creates the tiles */
146-(void) setupTiles;
147
148/** CCTMXLayer doesn't support adding a CCSprite manually.
149 @warning addchild:z:tag: is not supported on CCTMXLayer. Instead of setTileGID:at:/tileAt:
150 */
151-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag;
152@end
diff --git a/libs/cocos2d/CCTMXLayer.m b/libs/cocos2d/CCTMXLayer.m new file mode 100755 index 0000000..bb2ba60 --- /dev/null +++ b/libs/cocos2d/CCTMXLayer.m
@@ -0,0 +1,670 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31#import "CCTMXLayer.h"
32#import "CCTMXTiledMap.h"
33#import "CCTMXXMLParser.h"
34#import "CCSprite.h"
35#import "CCSpriteBatchNode.h"
36#import "CCTextureCache.h"
37#import "Support/CGPointExtension.h"
38
39#pragma mark -
40#pragma mark CCSpriteBatchNode Extension
41
42@interface CCSpriteBatchNode (TMXTiledMapExtensions)
43-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag;
44-(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index;
45@end
46
47/* IMPORTANT XXX IMPORTNAT:
48 * These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteBatchNode#add SHALL not be called
49 */
50@implementation CCSpriteBatchNode (TMXTiledMapExtension)
51
52/* Adds a quad into the texture atlas but it won't be added into the children array.
53 This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated.
54 For example: a tile map (CCTMXMap) or a label with lots of characgers (CCLabelBMFont)
55 */
56-(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index
57{
58 NSAssert( sprite != nil, @"Argument must be non-nil");
59 NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children");
60
61
62 while(index >= textureAtlas_.capacity || textureAtlas_.capacity == textureAtlas_.totalQuads )
63 [self increaseAtlasCapacity];
64
65 //
66 // update the quad directly. Don't add the sprite to the scene graph
67 //
68
69 [sprite useBatchNode:self];
70 [sprite setAtlasIndex:index];
71
72 ccV3F_C4B_T2F_Quad quad = [sprite quad];
73 [textureAtlas_ insertQuad:&quad atIndex:index];
74
75 // XXX: updateTransform will update the textureAtlas too using updateQuad.
76 // XXX: so, it should be AFTER the insertQuad
77 [sprite setDirty:YES];
78 [sprite updateTransform];
79}
80
81/* This is the opposite of "addQuadFromSprite.
82 It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas
83 */
84-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag
85{
86 NSAssert( child != nil, @"Argument must be non-nil");
87 NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children");
88
89 // quad index is Z
90 [child setAtlasIndex:z];
91
92 // XXX: optimize with a binary search
93 int i=0;
94 for( CCSprite *c in descendants_ ) {
95 if( c.atlasIndex >= z )
96 break;
97 i++;
98 }
99 [descendants_ insertObject:child atIndex:i];
100
101
102 // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
103 [super addChild:child z:z tag:aTag];
104 return self;
105}
106@end
107
108
109#pragma mark -
110#pragma mark CCTMXLayer
111
112int compareInts (const void * a, const void * b);
113
114
115@interface CCTMXLayer ()
116-(CGPoint) positionForIsoAt:(CGPoint)pos;
117-(CGPoint) positionForOrthoAt:(CGPoint)pos;
118-(CGPoint) positionForHexAt:(CGPoint)pos;
119
120-(CGPoint) calculateLayerOffset:(CGPoint)offset;
121
122/* optimization methos */
123-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos;
124-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos;
125-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos;
126
127/* The layer recognizes some special properties, like cc_vertez */
128-(void) parseInternalProperties;
129
130-(NSInteger) vertexZForPos:(CGPoint)pos;
131
132// index
133-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z;
134-(NSUInteger) atlasIndexForNewZ:(NSUInteger)z;
135@end
136
137@implementation CCTMXLayer
138@synthesize layerSize = layerSize_, layerName = layerName_, tiles = tiles_;
139@synthesize tileset = tileset_;
140@synthesize layerOrientation = layerOrientation_;
141@synthesize mapTileSize = mapTileSize_;
142@synthesize properties = properties_;
143
144#pragma mark CCTMXLayer - init & alloc & dealloc
145
146+(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo
147{
148 return [[[self alloc] initWithTilesetInfo:tilesetInfo layerInfo:layerInfo mapInfo:mapInfo] autorelease];
149}
150
151-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo
152{
153 // XXX: is 35% a good estimate ?
154 CGSize size = layerInfo.layerSize;
155 float totalNumberOfTiles = size.width * size.height;
156 float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ?
157
158 CCTexture2D *tex = nil;
159 if( tilesetInfo )
160 tex = [[CCTextureCache sharedTextureCache] addImage:tilesetInfo.sourceImage];
161
162 if((self = [super initWithTexture:tex capacity:capacity])) {
163
164 // layerInfo
165 self.layerName = layerInfo.name;
166 layerSize_ = layerInfo.layerSize;
167 tiles_ = layerInfo.tiles;
168 minGID_ = layerInfo.minGID;
169 maxGID_ = layerInfo.maxGID;
170 opacity_ = layerInfo.opacity;
171 self.properties = [NSMutableDictionary dictionaryWithDictionary:layerInfo.properties];
172
173 // tilesetInfo
174 self.tileset = tilesetInfo;
175
176 // mapInfo
177 mapTileSize_ = mapInfo.tileSize;
178 layerOrientation_ = mapInfo.orientation;
179
180 // offset (after layer orientation is set);
181 CGPoint offset = [self calculateLayerOffset:layerInfo.offset];
182 [self setPositionInPixels:offset];
183
184 atlasIndexArray_ = ccCArrayNew(totalNumberOfTiles);
185
186 [self setContentSizeInPixels: CGSizeMake( layerSize_.width * mapTileSize_.width, layerSize_.height * mapTileSize_.height )];
187
188 useAutomaticVertexZ_= NO;
189 vertexZvalue_ = 0;
190 alphaFuncValue_ = 0;
191
192 }
193 return self;
194}
195
196- (void) dealloc
197{
198 [layerName_ release];
199 [tileset_ release];
200 [reusedTile_ release];
201 [properties_ release];
202
203 if( atlasIndexArray_ ) {
204 ccCArrayFree(atlasIndexArray_);
205 atlasIndexArray_ = NULL;
206 }
207
208 if( tiles_ ) {
209 free(tiles_);
210 tiles_ = NULL;
211 }
212
213 [super dealloc];
214}
215
216-(void) releaseMap
217{
218 if( tiles_) {
219 free( tiles_);
220 tiles_ = NULL;
221 }
222
223 if( atlasIndexArray_ ) {
224 ccCArrayFree(atlasIndexArray_);
225 atlasIndexArray_ = NULL;
226 }
227}
228
229#pragma mark CCTMXLayer - setup Tiles
230
231-(void) setupTiles
232{
233 // Optimization: quick hack that sets the image size on the tileset
234 tileset_.imageSize = [textureAtlas_.texture contentSizeInPixels];
235
236 // By default all the tiles are aliased
237 // pros:
238 // - easier to render
239 // cons:
240 // - difficult to scale / rotate / etc.
241 [textureAtlas_.texture setAliasTexParameters];
242
243 CFByteOrder o = CFByteOrderGetCurrent();
244
245 // Parse cocos2d properties
246 [self parseInternalProperties];
247
248 for( NSUInteger y=0; y < layerSize_.height; y++ ) {
249 for( NSUInteger x=0; x < layerSize_.width; x++ ) {
250
251 NSUInteger pos = x + layerSize_.width * y;
252 uint32_t gid = tiles_[ pos ];
253
254 // gid are stored in little endian.
255 // if host is big endian, then swap
256 if( o == CFByteOrderBigEndian )
257 gid = CFSwapInt32( gid );
258
259 // XXX: gid == 0 --> empty tile
260 if( gid != 0 ) {
261 [self appendTileForGID:gid at:ccp(x,y)];
262
263 // Optimization: update min and max GID rendered by the layer
264 minGID_ = MIN(gid, minGID_);
265 maxGID_ = MAX(gid, maxGID_);
266 }
267 }
268 }
269
270 NSAssert( maxGID_ >= tileset_.firstGid &&
271 minGID_ >= tileset_.firstGid, @"TMX: Only 1 tilset per layer is supported");
272}
273
274#pragma mark CCTMXLayer - Properties
275
276-(id) propertyNamed:(NSString *)propertyName
277{
278 return [properties_ valueForKey:propertyName];
279}
280
281-(void) parseInternalProperties
282{
283 // if cc_vertex=automatic, then tiles will be rendered using vertexz
284
285 NSString *vertexz = [self propertyNamed:@"cc_vertexz"];
286 if( vertexz ) {
287 if( [vertexz isEqualToString:@"automatic"] )
288 useAutomaticVertexZ_ = YES;
289 else
290 vertexZvalue_ = [vertexz intValue];
291 }
292
293 NSString *alphaFuncVal = [self propertyNamed:@"cc_alpha_func"];
294 alphaFuncValue_ = [alphaFuncVal floatValue];
295}
296
297#pragma mark CCTMXLayer - obtaining tiles/gids
298
299-(CCSprite*) tileAt:(CGPoint)pos
300{
301 NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
302 NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
303
304 CCSprite *tile = nil;
305 uint32_t gid = [self tileGIDAt:pos];
306
307 // if GID == 0, then no tile is present
308 if( gid ) {
309 int z = pos.x + pos.y * layerSize_.width;
310 tile = (CCSprite*) [self getChildByTag:z];
311
312 // tile not created yet. create it
313 if( ! tile ) {
314 CGRect rect = [tileset_ rectForGID:gid];
315 tile = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
316 [tile setPositionInPixels: [self positionAt:pos]];
317 [tile setVertexZ: [self vertexZForPos:pos]];
318 tile.anchorPoint = CGPointZero;
319 [tile setOpacity:opacity_];
320
321 NSUInteger indexForZ = [self atlasIndexForExistantZ:z];
322 [self addSpriteWithoutQuad:tile z:indexForZ tag:z];
323 [tile release];
324 }
325 }
326 return tile;
327}
328
329-(uint32_t) tileGIDAt:(CGPoint)pos
330{
331 NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
332 NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
333
334 NSInteger idx = pos.x + pos.y * layerSize_.width;
335 return tiles_[ idx ];
336}
337
338#pragma mark CCTMXLayer - adding helper methods
339
340-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos
341{
342 CGRect rect = [tileset_ rectForGID:gid];
343
344 NSInteger z = pos.x + pos.y * layerSize_.width;
345
346 if( ! reusedTile_ )
347 reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
348 else
349 [reusedTile_ initWithBatchNode:self rectInPixels:rect];
350
351 [reusedTile_ setPositionInPixels: [self positionAt:pos]];
352 [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
353 reusedTile_.anchorPoint = CGPointZero;
354 [reusedTile_ setOpacity:opacity_];
355
356 // get atlas index
357 NSUInteger indexForZ = [self atlasIndexForNewZ:z];
358
359 // Optimization: add the quad without adding a child
360 [self addQuadFromSprite:reusedTile_ quadIndex:indexForZ];
361
362 // insert it into the local atlasindex array
363 ccCArrayInsertValueAtIndex(atlasIndexArray_, (void*)z, indexForZ);
364
365 // update possible children
366 CCSprite *sprite;
367 CCARRAY_FOREACH(children_, sprite) {
368 NSUInteger ai = [sprite atlasIndex];
369 if( ai >= indexForZ)
370 [sprite setAtlasIndex: ai+1];
371 }
372
373 tiles_[z] = gid;
374
375 return reusedTile_;
376}
377
378-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos
379{
380 CGRect rect = [tileset_ rectForGID:gid];
381
382 int z = pos.x + pos.y * layerSize_.width;
383
384 if( ! reusedTile_ )
385 reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
386 else
387 [reusedTile_ initWithBatchNode:self rectInPixels:rect];
388
389 [reusedTile_ setPositionInPixels: [self positionAt:pos]];
390 [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
391 reusedTile_.anchorPoint = CGPointZero;
392 [reusedTile_ setOpacity:opacity_];
393
394 // get atlas index
395 NSUInteger indexForZ = [self atlasIndexForExistantZ:z];
396
397 [reusedTile_ setAtlasIndex:indexForZ];
398 [reusedTile_ setDirty:YES];
399 [reusedTile_ updateTransform];
400 tiles_[z] = gid;
401
402 return reusedTile_;
403}
404
405
406// used only when parsing the map. useless after the map was parsed
407// since lot's of assumptions are no longer true
408-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos
409{
410 CGRect rect = [tileset_ rectForGID:gid];
411
412 NSInteger z = pos.x + pos.y * layerSize_.width;
413
414 if( ! reusedTile_ )
415 reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
416 else
417 [reusedTile_ initWithBatchNode:self rectInPixels:rect];
418
419 [reusedTile_ setPositionInPixels: [self positionAt:pos]];
420 [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
421 reusedTile_.anchorPoint = CGPointZero;
422 [reusedTile_ setOpacity:opacity_];
423
424 // optimization:
425 // The difference between appendTileForGID and insertTileforGID is that append is faster, since
426 // it appends the tile at the end of the texture atlas
427 NSUInteger indexForZ = atlasIndexArray_->num;
428
429
430 // don't add it using the "standard" way.
431 [self addQuadFromSprite:reusedTile_ quadIndex:indexForZ];
432
433
434 // append should be after addQuadFromSprite since it modifies the quantity values
435 ccCArrayInsertValueAtIndex(atlasIndexArray_, (void*)z, indexForZ);
436
437 return reusedTile_;
438}
439
440#pragma mark CCTMXLayer - atlasIndex and Z
441
442int compareInts (const void * a, const void * b)
443{
444 return ( *(int*)a - *(int*)b );
445}
446
447-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z
448{
449 NSInteger key = z;
450 NSInteger *item = bsearch((void*)&key, (void*)&atlasIndexArray_->arr[0], atlasIndexArray_->num, sizeof(void*), compareInts);
451
452 NSAssert( item, @"TMX atlas index not found. Shall not happen");
453
454 NSUInteger index = ((NSInteger)item - (NSInteger)atlasIndexArray_->arr) / sizeof(void*);
455 return index;
456}
457
458-(NSUInteger)atlasIndexForNewZ:(NSUInteger)z
459{
460 // XXX: This can be improved with a sort of binary search
461 NSUInteger i = 0;
462 for(i = 0; i< atlasIndexArray_->num; i++) {
463 NSUInteger val = (NSUInteger) atlasIndexArray_->arr[i];
464 if( z < val )
465 break;
466 }
467 return i;
468}
469
470#pragma mark CCTMXLayer - adding / remove tiles
471
472-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos
473{
474 NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
475 NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
476 NSAssert( gid == 0 || gid >= tileset_.firstGid, @"TMXLayer: invalid gid" );
477
478 uint32_t currentGID = [self tileGIDAt:pos];
479
480 if( currentGID != gid ) {
481
482 // setting gid=0 is equal to remove the tile
483 if( gid == 0 )
484 [self removeTileAt:pos];
485
486 // empty tile. create a new one
487 else if( currentGID == 0 )
488 [self insertTileForGID:gid at:pos];
489
490 // modifying an existing tile with a non-empty tile
491 else {
492
493 NSUInteger z = pos.x + pos.y * layerSize_.width;
494 id sprite = [self getChildByTag:z];
495 if( sprite ) {
496 CGRect rect = [tileset_ rectForGID:gid];
497 [sprite setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size];
498 tiles_[z] = gid;
499 } else
500 [self updateTileForGID:gid at:pos];
501 }
502 }
503}
504
505-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag
506{
507 NSAssert(NO, @"addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:");
508}
509
510-(void) removeChild:(CCSprite*)sprite cleanup:(BOOL)cleanup
511{
512 // allows removing nil objects
513 if( ! sprite )
514 return;
515
516 NSAssert( [children_ containsObject:sprite], @"Tile does not belong to TMXLayer");
517
518 NSUInteger atlasIndex = [sprite atlasIndex];
519 NSUInteger zz = (NSUInteger) atlasIndexArray_->arr[atlasIndex];
520 tiles_[zz] = 0;
521 ccCArrayRemoveValueAtIndex(atlasIndexArray_, atlasIndex);
522 [super removeChild:sprite cleanup:cleanup];
523}
524
525-(void) removeTileAt:(CGPoint)pos
526{
527 NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
528 NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
529
530 uint32_t gid = [self tileGIDAt:pos];
531
532 if( gid ) {
533
534 NSUInteger z = pos.x + pos.y * layerSize_.width;
535 NSUInteger atlasIndex = [self atlasIndexForExistantZ:z];
536
537 // remove tile from GID map
538 tiles_[z] = 0;
539
540 // remove tile from atlas position array
541 ccCArrayRemoveValueAtIndex(atlasIndexArray_, atlasIndex);
542
543 // remove it from sprites and/or texture atlas
544 id sprite = [self getChildByTag:z];
545 if( sprite )
546 [super removeChild:sprite cleanup:YES];
547 else {
548 [textureAtlas_ removeQuadAtIndex:atlasIndex];
549
550 // update possible children
551 CCARRAY_FOREACH(children_, sprite) {
552 NSUInteger ai = [sprite atlasIndex];
553 if( ai >= atlasIndex) {
554 [sprite setAtlasIndex: ai-1];
555 }
556 }
557 }
558 }
559}
560
561#pragma mark CCTMXLayer - obtaining positions, offset
562
563-(CGPoint) calculateLayerOffset:(CGPoint)pos
564{
565 CGPoint ret = CGPointZero;
566 switch( layerOrientation_ ) {
567 case CCTMXOrientationOrtho:
568 ret = ccp( pos.x * mapTileSize_.width, -pos.y *mapTileSize_.height);
569 break;
570 case CCTMXOrientationIso:
571 ret = ccp( (mapTileSize_.width /2) * (pos.x - pos.y),
572 (mapTileSize_.height /2 ) * (-pos.x - pos.y) );
573 break;
574 case CCTMXOrientationHex:
575 NSAssert(CGPointEqualToPoint(pos, CGPointZero), @"offset for hexagonal map not implemented yet");
576 break;
577 }
578 return ret;
579}
580
581-(CGPoint) positionAt:(CGPoint)pos
582{
583 CGPoint ret = CGPointZero;
584 switch( layerOrientation_ ) {
585 case CCTMXOrientationOrtho:
586 ret = [self positionForOrthoAt:pos];
587 break;
588 case CCTMXOrientationIso:
589 ret = [self positionForIsoAt:pos];
590 break;
591 case CCTMXOrientationHex:
592 ret = [self positionForHexAt:pos];
593 break;
594 }
595 return ret;
596}
597
598-(CGPoint) positionForOrthoAt:(CGPoint)pos
599{
600 CGPoint xy = {
601 pos.x * mapTileSize_.width,
602 (layerSize_.height - pos.y - 1) * mapTileSize_.height,
603 };
604 return xy;
605}
606
607-(CGPoint) positionForIsoAt:(CGPoint)pos
608{
609 CGPoint xy = {
610 mapTileSize_.width /2 * ( layerSize_.width + pos.x - pos.y - 1),
611 mapTileSize_.height /2 * (( layerSize_.height * 2 - pos.x - pos.y) - 2),
612 };
613 return xy;
614}
615
616-(CGPoint) positionForHexAt:(CGPoint)pos
617{
618 float diffY = 0;
619 if( (int)pos.x % 2 == 1 )
620 diffY = -mapTileSize_.height/2 ;
621
622 CGPoint xy = {
623 pos.x * mapTileSize_.width*3/4,
624 (layerSize_.height - pos.y - 1) * mapTileSize_.height + diffY
625 };
626 return xy;
627}
628
629-(NSInteger) vertexZForPos:(CGPoint)pos
630{
631 NSInteger ret = 0;
632 NSUInteger maxVal = 0;
633 if( useAutomaticVertexZ_ ) {
634 switch( layerOrientation_ ) {
635 case CCTMXOrientationIso:
636 maxVal = layerSize_.width + layerSize_.height;
637 ret = -(maxVal - (pos.x + pos.y));
638 break;
639 case CCTMXOrientationOrtho:
640 ret = -(layerSize_.height-pos.y);
641 break;
642 case CCTMXOrientationHex:
643 NSAssert(NO,@"TMX Hexa zOrder not supported");
644 break;
645 default:
646 NSAssert(NO,@"TMX invalid value");
647 break;
648 }
649 } else
650 ret = vertexZvalue_;
651
652 return ret;
653}
654
655#pragma mark CCTMXLayer - draw
656
657-(void) draw
658{
659 if( useAutomaticVertexZ_ ) {
660 glEnable(GL_ALPHA_TEST);
661 glAlphaFunc(GL_GREATER, alphaFuncValue_);
662 }
663
664 [super draw];
665
666 if( useAutomaticVertexZ_ )
667 glDisable(GL_ALPHA_TEST);
668}
669@end
670
diff --git a/libs/cocos2d/CCTMXObjectGroup.h b/libs/cocos2d/CCTMXObjectGroup.h new file mode 100755 index 0000000..02feadf --- /dev/null +++ b/libs/cocos2d/CCTMXObjectGroup.h
@@ -0,0 +1,67 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Neophit
5 *
6 * Copyright (c) 2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 *
28 * TMX Tiled Map support:
29 * http://www.mapeditor.org
30 *
31 */
32
33#import "CCNode.h"
34
35
36@class CCTMXObjectGroup;
37
38
39/** CCTMXObjectGroup represents the TMX object group.
40@since v0.99.0
41*/
42@interface CCTMXObjectGroup : NSObject
43{
44 NSString *groupName_;
45 CGPoint positionOffset_;
46 NSMutableArray *objects_;
47 NSMutableDictionary *properties_;
48}
49
50/** name of the group */
51@property (nonatomic,readwrite,retain) NSString *groupName;
52/** offset position of child objects */
53@property (nonatomic,readwrite,assign) CGPoint positionOffset;
54/** array of the objects */
55@property (nonatomic,readwrite,retain) NSMutableArray *objects;
56/** list of properties stored in a dictionary */
57@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
58
59/** return the value for the specific property name */
60-(id) propertyNamed:(NSString *)propertyName;
61
62/** return the dictionary for the specific object name.
63 It will return the 1st object found on the array for the given name.
64 */
65-(NSMutableDictionary*) objectNamed:(NSString *)objectName;
66
67@end
diff --git a/libs/cocos2d/CCTMXObjectGroup.m b/libs/cocos2d/CCTMXObjectGroup.m new file mode 100755 index 0000000..648cda4 --- /dev/null +++ b/libs/cocos2d/CCTMXObjectGroup.m
@@ -0,0 +1,86 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Neophit
5 *
6 * Copyright (c) 2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 *
28 * TMX Tiled Map support:
29 * http://www.mapeditor.org
30 *
31 */
32
33#import "CCTMXObjectGroup.h"
34#import "CCTMXXMLParser.h"
35#import "ccMacros.h"
36#import "Support/CGPointExtension.h"
37
38
39#pragma mark -
40#pragma mark TMXObjectGroup
41
42@implementation CCTMXObjectGroup
43
44@synthesize groupName = groupName_;
45@synthesize objects = objects_;
46@synthesize positionOffset = positionOffset_;
47@synthesize properties = properties_;
48
49-(id) init
50{
51 if (( self=[super init] )) {
52 self.groupName = nil;
53 self.positionOffset = CGPointZero;
54 self.objects = [NSMutableArray arrayWithCapacity:10];
55 self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
56 }
57 return self;
58}
59
60-(void) dealloc
61{
62 CCLOGINFO( @"cocos2d: deallocing %@", self );
63
64 [groupName_ release];
65 [objects_ release];
66 [properties_ release];
67 [super dealloc];
68}
69
70-(NSMutableDictionary*) objectNamed:(NSString *)objectName
71{
72 for( id object in objects_ ) {
73 if( [[object valueForKey:@"name"] isEqual:objectName] )
74 return object;
75 }
76
77 // object not found
78 return nil;
79}
80
81-(id) propertyNamed:(NSString *)propertyName
82{
83 return [properties_ valueForKey:propertyName];
84}
85
86@end
diff --git a/libs/cocos2d/CCTMXTiledMap.h b/libs/cocos2d/CCTMXTiledMap.h new file mode 100755 index 0000000..8f48da3 --- /dev/null +++ b/libs/cocos2d/CCTMXTiledMap.h
@@ -0,0 +1,145 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31#import "CCNode.h"
32
33
34@class CCTMXLayer;
35@class CCTMXObjectGroup;
36
37/** Possible oritentations of the TMX map */
38enum
39{
40 /** Orthogonal orientation */
41 CCTMXOrientationOrtho,
42
43 /** Hexagonal orientation */
44 CCTMXOrientationHex,
45
46 /** Isometric orientation */
47 CCTMXOrientationIso,
48};
49
50/** CCTMXTiledMap knows how to parse and render a TMX map.
51
52 It adds support for the TMX tiled map format used by http://www.mapeditor.org
53 It supports isometric, hexagonal and orthogonal tiles.
54 It also supports object groups, objects, and properties.
55
56 Features:
57 - Each tile will be treated as an CCSprite
58 - The sprites are created on demand. They will be created only when you call "[layer tileAt:]"
59 - Each tile can be rotated / moved / scaled / tinted / "opacitied", since each tile is a CCSprite
60 - Tiles can be added/removed in runtime
61 - The z-order of the tiles can be modified in runtime
62 - Each tile has an anchorPoint of (0,0)
63 - The anchorPoint of the TMXTileMap is (0,0)
64 - The TMX layers will be added as a child
65 - The TMX layers will be aliased by default
66 - The tileset image will be loaded using the CCTextureCache
67 - Each tile will have a unique tag
68 - Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z
69 - Each object group will be treated as an NSMutableArray
70 - Object class which will contain all the properties in a dictionary
71 - Properties can be assigned to the Map, Layer, Object Group, and Object
72
73 Limitations:
74 - It only supports one tileset per layer.
75 - Embeded images are not supported
76 - It only supports the XML format (the JSON format is not supported)
77
78 Technical description:
79 Each layer is created using an CCTMXLayer (subclass of CCSpriteBatchNode). If you have 5 layers, then 5 CCTMXLayer will be created,
80 unless the layer visibility is off. In that case, the layer won't be created at all.
81 You can obtain the layers (CCTMXLayer objects) at runtime by:
82 - [map getChildByTag: tag_number]; // 0=1st layer, 1=2nd layer, 2=3rd layer, etc...
83 - [map layerNamed: name_of_the_layer];
84
85 Each object group is created using a CCTMXObjectGroup which is a subclass of NSMutableArray.
86 You can obtain the object groups at runtime by:
87 - [map objectGroupNamed: name_of_the_object_group];
88
89 Each object is a CCTMXObject.
90
91 Each property is stored as a key-value pair in an NSMutableDictionary.
92 You can obtain the properties at runtime by:
93
94 [map propertyNamed: name_of_the_property];
95 [layer propertyNamed: name_of_the_property];
96 [objectGroup propertyNamed: name_of_the_property];
97 [object propertyNamed: name_of_the_property];
98
99 @since v0.8.1
100 */
101@interface CCTMXTiledMap : CCNode
102{
103 CGSize mapSize_;
104 CGSize tileSize_;
105 int mapOrientation_;
106 NSMutableArray *objectGroups_;
107 NSMutableDictionary *properties_;
108 NSMutableDictionary *tileProperties_;
109}
110
111/** the map's size property measured in tiles */
112@property (nonatomic,readonly) CGSize mapSize;
113/** the tiles's size property measured in pixels */
114@property (nonatomic,readonly) CGSize tileSize;
115/** map orientation */
116@property (nonatomic,readonly) int mapOrientation;
117/** object groups */
118@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups;
119/** properties */
120@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
121
122/** creates a TMX Tiled Map with a TMX file.*/
123+(id) tiledMapWithTMXFile:(NSString*)tmxFile;
124
125/** initializes a TMX Tiled Map with a TMX file */
126-(id) initWithTMXFile:(NSString*)tmxFile;
127
128/** return the TMXLayer for the specific layer */
129-(CCTMXLayer*) layerNamed:(NSString *)layerName;
130
131/** return the TMXObjectGroup for the secific group */
132-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName;
133
134/** return the TMXObjectGroup for the secific group
135 @deprecated Use map#objectGroupNamed instead
136 */
137-(CCTMXObjectGroup*) groupNamed:(NSString *)groupName DEPRECATED_ATTRIBUTE;
138
139/** return the value for the specific property name */
140-(id) propertyNamed:(NSString *)propertyName;
141
142/** return properties dictionary for tile GID */
143-(NSDictionary*)propertiesForGID:(unsigned int)GID;
144@end
145
diff --git a/libs/cocos2d/CCTMXTiledMap.m b/libs/cocos2d/CCTMXTiledMap.m new file mode 100755 index 0000000..7f86c6a --- /dev/null +++ b/libs/cocos2d/CCTMXTiledMap.m
@@ -0,0 +1,201 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31#import "CCTMXTiledMap.h"
32#import "CCTMXXMLParser.h"
33#import "CCTMXLayer.h"
34#import "CCTMXObjectGroup.h"
35#import "CCSprite.h"
36#import "CCTextureCache.h"
37#import "Support/CGPointExtension.h"
38
39
40#pragma mark -
41#pragma mark CCTMXTiledMap
42
43@interface CCTMXTiledMap (Private)
44-(id) parseLayer:(CCTMXLayerInfo*)layer map:(CCTMXMapInfo*)mapInfo;
45-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo;
46@end
47
48@implementation CCTMXTiledMap
49@synthesize mapSize = mapSize_;
50@synthesize tileSize = tileSize_;
51@synthesize mapOrientation = mapOrientation_;
52@synthesize objectGroups = objectGroups_;
53@synthesize properties = properties_;
54
55+(id) tiledMapWithTMXFile:(NSString*)tmxFile
56{
57 return [[[self alloc] initWithTMXFile:tmxFile] autorelease];
58}
59
60-(id) initWithTMXFile:(NSString*)tmxFile
61{
62 NSAssert(tmxFile != nil, @"TMXTiledMap: tmx file should not bi nil");
63
64 if ((self=[super init])) {
65
66 [self setContentSize:CGSizeZero];
67
68 CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithTMXFile:tmxFile];
69
70 NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename.");
71
72 mapSize_ = mapInfo.mapSize;
73 tileSize_ = mapInfo.tileSize;
74 mapOrientation_ = mapInfo.orientation;
75 objectGroups_ = [mapInfo.objectGroups retain];
76 properties_ = [mapInfo.properties retain];
77 tileProperties_ = [mapInfo.tileProperties retain];
78
79 int idx=0;
80
81 for( CCTMXLayerInfo *layerInfo in mapInfo.layers ) {
82
83 if( layerInfo.visible ) {
84 CCNode *child = [self parseLayer:layerInfo map:mapInfo];
85 [self addChild:child z:idx tag:idx];
86
87 // update content size with the max size
88 CGSize childSize = [child contentSize];
89 CGSize currentSize = [self contentSize];
90 currentSize.width = MAX( currentSize.width, childSize.width );
91 currentSize.height = MAX( currentSize.height, childSize.height );
92 [self setContentSize:currentSize];
93
94 idx++;
95 }
96 }
97 }
98
99 return self;
100}
101
102-(void) dealloc
103{
104 [objectGroups_ release];
105 [properties_ release];
106 [tileProperties_ release];
107 [super dealloc];
108}
109
110// private
111-(id) parseLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo
112{
113 CCTMXTilesetInfo *tileset = [self tilesetForLayer:layerInfo map:mapInfo];
114 CCTMXLayer *layer = [CCTMXLayer layerWithTilesetInfo:tileset layerInfo:layerInfo mapInfo:mapInfo];
115
116 // tell the layerinfo to release the ownership of the tiles map.
117 layerInfo.ownTiles = NO;
118
119 [layer setupTiles];
120
121 return layer;
122}
123
124-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo
125{
126 CFByteOrder o = CFByteOrderGetCurrent();
127
128 CGSize size = layerInfo.layerSize;
129
130 id iter = [mapInfo.tilesets reverseObjectEnumerator];
131 for( CCTMXTilesetInfo* tileset in iter) {
132 for( unsigned int y = 0; y < size.height; y++ ) {
133 for( unsigned int x = 0; x < size.width; x++ ) {
134
135 unsigned int pos = x + size.width * y;
136 unsigned int gid = layerInfo.tiles[ pos ];
137
138 // gid are stored in little endian.
139 // if host is big endian, then swap
140 if( o == CFByteOrderBigEndian )
141 gid = CFSwapInt32( gid );
142
143 // XXX: gid == 0 --> empty tile
144 if( gid != 0 ) {
145
146 // Optimization: quick return
147 // if the layer is invalid (more than 1 tileset per layer) an assert will be thrown later
148 if( gid >= tileset.firstGid )
149 return tileset;
150 }
151 }
152 }
153 }
154
155 // If all the tiles are 0, return empty tileset
156 CCLOG(@"cocos2d: Warning: TMX Layer '%@' has no tiles", layerInfo.name);
157 return nil;
158}
159
160
161// public
162
163-(CCTMXLayer*) layerNamed:(NSString *)layerName
164{
165 CCTMXLayer *layer;
166 CCARRAY_FOREACH(children_, layer) {
167 if([layer isKindOfClass:[CCTMXLayer class]])
168 if([layer.layerName isEqual:layerName])
169 return layer;
170 }
171
172 // layer not found
173 return nil;
174}
175
176-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName
177{
178 for( CCTMXObjectGroup *objectGroup in objectGroups_ ) {
179 if( [objectGroup.groupName isEqual:groupName] )
180 return objectGroup;
181 }
182
183 // objectGroup not found
184 return nil;
185}
186
187// XXX deprecated
188-(CCTMXObjectGroup*) groupNamed:(NSString *)groupName
189{
190 return [self objectGroupNamed:groupName];
191}
192
193-(id) propertyNamed:(NSString *)propertyName
194{
195 return [properties_ valueForKey:propertyName];
196}
197-(NSDictionary*)propertiesForGID:(unsigned int)GID{
198 return [tileProperties_ objectForKey:[NSNumber numberWithInt:GID]];
199}
200@end
201
diff --git a/libs/cocos2d/CCTMXXMLParser.h b/libs/cocos2d/CCTMXXMLParser.h new file mode 100755 index 0000000..18d7a8a --- /dev/null +++ b/libs/cocos2d/CCTMXXMLParser.h
@@ -0,0 +1,202 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31/*
32 * Internal TMX parser
33 *
34 * IMPORTANT: These classed should not be documented using doxygen strings
35 * since the user should not use them.
36 *
37 */
38
39
40#import <Availability.h>
41#import <Foundation/Foundation.h>
42
43enum {
44 TMXLayerAttribNone = 1 << 0,
45 TMXLayerAttribBase64 = 1 << 1,
46 TMXLayerAttribGzip = 1 << 2,
47 TMXLayerAttribZlib = 1 << 3,
48};
49
50enum {
51 TMXPropertyNone,
52 TMXPropertyMap,
53 TMXPropertyLayer,
54 TMXPropertyObjectGroup,
55 TMXPropertyObject,
56 TMXPropertyTile
57};
58
59/* CCTMXLayerInfo contains the information about the layers like:
60 - Layer name
61 - Layer size
62 - Layer opacity at creation time (it can be modified at runtime)
63 - Whether the layer is visible (if it's not visible, then the CocosNode won't be created)
64
65 This information is obtained from the TMX file.
66 */
67@interface CCTMXLayerInfo : NSObject
68{
69 NSString *name_;
70 CGSize layerSize_;
71 unsigned int *tiles_;
72 BOOL visible_;
73 unsigned char opacity_;
74 BOOL ownTiles_;
75 unsigned int minGID_;
76 unsigned int maxGID_;
77 NSMutableDictionary *properties_;
78 CGPoint offset_;
79}
80
81@property (nonatomic,readwrite,retain) NSString *name;
82@property (nonatomic,readwrite) CGSize layerSize;
83@property (nonatomic,readwrite) unsigned int *tiles;
84@property (nonatomic,readwrite) BOOL visible;
85@property (nonatomic,readwrite) unsigned char opacity;
86@property (nonatomic,readwrite) BOOL ownTiles;
87@property (nonatomic,readwrite) unsigned int minGID;
88@property (nonatomic,readwrite) unsigned int maxGID;
89@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
90@property (nonatomic,readwrite) CGPoint offset;
91@end
92
93/* CCTMXTilesetInfo contains the information about the tilesets like:
94 - Tileset name
95 - Tilset spacing
96 - Tileset margin
97 - size of the tiles
98 - Image used for the tiles
99 - Image size
100
101 This information is obtained from the TMX file.
102 */
103@interface CCTMXTilesetInfo : NSObject
104{
105 NSString *name_;
106 unsigned int firstGid_;
107 CGSize tileSize_;
108 unsigned int spacing_;
109 unsigned int margin_;
110
111 // filename containing the tiles (should be spritesheet / texture atlas)
112 NSString *sourceImage_;
113
114 // size in pixels of the image
115 CGSize imageSize_;
116}
117@property (nonatomic,readwrite,retain) NSString *name;
118@property (nonatomic,readwrite,assign) unsigned int firstGid;
119@property (nonatomic,readwrite,assign) CGSize tileSize;
120@property (nonatomic,readwrite,assign) unsigned int spacing;
121@property (nonatomic,readwrite,assign) unsigned int margin;
122@property (nonatomic,readwrite,retain) NSString *sourceImage;
123@property (nonatomic,readwrite,assign) CGSize imageSize;
124
125-(CGRect) rectForGID:(unsigned int)gid;
126@end
127
128/* CCTMXMapInfo contains the information about the map like:
129 - Map orientation (hexagonal, isometric or orthogonal)
130 - Tile size
131 - Map size
132
133 And it also contains:
134 - Layers (an array of TMXLayerInfo objects)
135 - Tilesets (an array of TMXTilesetInfo objects)
136 - ObjectGroups (an array of TMXObjectGroupInfo objects)
137
138 This information is obtained from the TMX file.
139
140 */
141#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
142#if defined(__IPHONE_4_0)
143@interface CCTMXMapInfo : NSObject <NSXMLParserDelegate>
144#else
145@interface CCTMXMapInfo : NSObject
146#endif
147
148#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
149@interface CCTMXMapInfo : NSObject <NSXMLParserDelegate>
150#endif
151{
152 NSMutableString *currentString;
153 BOOL storingCharacters;
154 int layerAttribs;
155 int parentElement;
156 unsigned int parentGID_;
157
158
159 // tmx filename
160 NSString *filename_;
161
162 // map orientation
163 int orientation_;
164
165 // map width & height
166 CGSize mapSize_;
167
168 // tiles width & height
169 CGSize tileSize_;
170
171 // Layers
172 NSMutableArray *layers_;
173
174 // tilesets
175 NSMutableArray *tilesets_;
176
177 // ObjectGroups
178 NSMutableArray *objectGroups_;
179
180 // properties
181 NSMutableDictionary *properties_;
182
183 // tile properties
184 NSMutableDictionary *tileProperties_;
185}
186
187@property (nonatomic,readwrite,assign) int orientation;
188@property (nonatomic,readwrite,assign) CGSize mapSize;
189@property (nonatomic,readwrite,assign) CGSize tileSize;
190@property (nonatomic,readwrite,retain) NSMutableArray *layers;
191@property (nonatomic,readwrite,retain) NSMutableArray *tilesets;
192@property (nonatomic,readwrite,retain) NSString *filename;
193@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups;
194@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
195@property (nonatomic,readwrite,retain) NSMutableDictionary *tileProperties;
196
197/** creates a TMX Format with a tmx file */
198+(id) formatWithTMXFile:(NSString*)tmxFile;
199/** initializes a TMX format witha tmx file */
200-(id) initWithTMXFile:(NSString*)tmxFile;
201@end
202
diff --git a/libs/cocos2d/CCTMXXMLParser.m b/libs/cocos2d/CCTMXXMLParser.m new file mode 100755 index 0000000..77cea0e --- /dev/null +++ b/libs/cocos2d/CCTMXXMLParser.m
@@ -0,0 +1,456 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * TMX Tiled Map support:
27 * http://www.mapeditor.org
28 *
29 */
30
31
32#import <Foundation/Foundation.h>
33#include <zlib.h>
34
35#import "ccMacros.h"
36#import "Support/CGPointExtension.h"
37#import "CCTMXXMLParser.h"
38#import "CCTMXTiledMap.h"
39#import "CCTMXObjectGroup.h"
40#import "Support/base64.h"
41#import "Support/ZipUtils.h"
42#import "Support/CCFileUtils.h"
43
44#pragma mark -
45#pragma mark TMXLayerInfo
46
47
48@implementation CCTMXLayerInfo
49
50@synthesize name = name_, layerSize = layerSize_, tiles = tiles_, visible = visible_, opacity = opacity_, ownTiles = ownTiles_, minGID = minGID_, maxGID = maxGID_, properties = properties_;
51@synthesize offset = offset_;
52-(id) init
53{
54 if( (self=[super init])) {
55 ownTiles_ = YES;
56 minGID_ = 100000;
57 maxGID_ = 0;
58 self.name = nil;
59 tiles_ = NULL;
60 offset_ = CGPointZero;
61 self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
62 }
63 return self;
64}
65- (void) dealloc
66{
67 CCLOGINFO(@"cocos2d: deallocing %@",self);
68
69 [name_ release];
70 [properties_ release];
71
72 if( ownTiles_ && tiles_ ) {
73 free( tiles_ );
74 tiles_ = NULL;
75 }
76 [super dealloc];
77}
78
79@end
80
81#pragma mark -
82#pragma mark TMXTilesetInfo
83@implementation CCTMXTilesetInfo
84
85@synthesize name = name_, firstGid = firstGid_, tileSize = tileSize_, spacing = spacing_, margin = margin_, sourceImage = sourceImage_, imageSize = imageSize_;
86
87- (void) dealloc
88{
89 CCLOGINFO(@"cocos2d: deallocing %@", self);
90 [sourceImage_ release];
91 [name_ release];
92 [super dealloc];
93}
94
95-(CGRect) rectForGID:(unsigned int)gid
96{
97 CGRect rect;
98 rect.size = tileSize_;
99
100 gid = gid - firstGid_;
101
102 int max_x = (imageSize_.width - margin_*2 + spacing_) / (tileSize_.width + spacing_);
103 // int max_y = (imageSize.height - margin*2 + spacing) / (tileSize.height + spacing);
104
105 rect.origin.x = (gid % max_x) * (tileSize_.width + spacing_) + margin_;
106 rect.origin.y = (gid / max_x) * (tileSize_.height + spacing_) + margin_;
107
108 return rect;
109}
110@end
111
112#pragma mark -
113#pragma mark CCTMXMapInfo
114
115@interface CCTMXMapInfo (Private)
116/* initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file */
117-(void) parseXMLFile:(NSString *)xmlFilename;
118@end
119
120
121@implementation CCTMXMapInfo
122
123@synthesize orientation = orientation_, mapSize = mapSize_, layers = layers_, tilesets = tilesets_, tileSize = tileSize_, filename = filename_, objectGroups = objectGroups_, properties = properties_;
124@synthesize tileProperties = tileProperties_;
125
126+(id) formatWithTMXFile:(NSString*)tmxFile
127{
128 return [[[self alloc] initWithTMXFile:tmxFile] autorelease];
129}
130
131-(id) initWithTMXFile:(NSString*)tmxFile
132{
133 if( (self=[super init])) {
134
135 self.tilesets = [NSMutableArray arrayWithCapacity:4];
136 self.layers = [NSMutableArray arrayWithCapacity:4];
137 self.filename = tmxFile;
138 self.objectGroups = [NSMutableArray arrayWithCapacity:4];
139 self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
140 self.tileProperties = [NSMutableDictionary dictionaryWithCapacity:5];
141
142 // tmp vars
143 currentString = [[NSMutableString alloc] initWithCapacity:1024];
144 storingCharacters = NO;
145 layerAttribs = TMXLayerAttribNone;
146 parentElement = TMXPropertyNone;
147
148 [self parseXMLFile:filename_];
149 }
150 return self;
151}
152- (void) dealloc
153{
154 CCLOGINFO(@"cocos2d: deallocing %@", self);
155 [tilesets_ release];
156 [layers_ release];
157 [filename_ release];
158 [currentString release];
159 [objectGroups_ release];
160 [properties_ release];
161 [tileProperties_ release];
162 [super dealloc];
163}
164
165- (void) parseXMLFile:(NSString *)xmlFilename
166{
167 NSURL *url = [NSURL fileURLWithPath:[CCFileUtils fullPathFromRelativePath:xmlFilename] ];
168 NSData *data = [NSData dataWithContentsOfURL:url];
169 NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
170
171 // we'll do the parsing
172 [parser setDelegate:self];
173 [parser setShouldProcessNamespaces:NO];
174 [parser setShouldReportNamespacePrefixes:NO];
175 [parser setShouldResolveExternalEntities:NO];
176 [parser parse];
177
178 NSAssert1( ! [parser parserError], @"Error parsing file: %@.", xmlFilename );
179
180 [parser release];
181}
182
183// the XML parser calls here with all the elements
184-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
185{
186 if([elementName isEqualToString:@"map"]) {
187 NSString *version = [attributeDict valueForKey:@"version"];
188 if( ! [version isEqualToString:@"1.0"] )
189 CCLOG(@"cocos2d: TMXFormat: Unsupported TMX version: %@", version);
190 NSString *orientationStr = [attributeDict valueForKey:@"orientation"];
191 if( [orientationStr isEqualToString:@"orthogonal"])
192 orientation_ = CCTMXOrientationOrtho;
193 else if ( [orientationStr isEqualToString:@"isometric"])
194 orientation_ = CCTMXOrientationIso;
195 else if( [orientationStr isEqualToString:@"hexagonal"])
196 orientation_ = CCTMXOrientationHex;
197 else
198 CCLOG(@"cocos2d: TMXFomat: Unsupported orientation: %@", orientation_);
199
200 mapSize_.width = [[attributeDict valueForKey:@"width"] intValue];
201 mapSize_.height = [[attributeDict valueForKey:@"height"] intValue];
202 tileSize_.width = [[attributeDict valueForKey:@"tilewidth"] intValue];
203 tileSize_.height = [[attributeDict valueForKey:@"tileheight"] intValue];
204
205 // The parent element is now "map"
206 parentElement = TMXPropertyMap;
207 } else if([elementName isEqualToString:@"tileset"]) {
208
209 // If this is an external tileset then start parsing that
210 NSString *externalTilesetFilename = [attributeDict valueForKey:@"source"];
211 if (externalTilesetFilename) {
212 // Tileset file will be relative to the map file. So we need to convert it to an absolute path
213 NSString *dir = [filename_ stringByDeletingLastPathComponent]; // Directory of map file
214 externalTilesetFilename = [dir stringByAppendingPathComponent:externalTilesetFilename]; // Append path to tileset file
215
216 [self parseXMLFile:externalTilesetFilename];
217 } else {
218
219 CCTMXTilesetInfo *tileset = [CCTMXTilesetInfo new];
220 tileset.name = [attributeDict valueForKey:@"name"];
221 tileset.firstGid = [[attributeDict valueForKey:@"firstgid"] intValue];
222 tileset.spacing = [[attributeDict valueForKey:@"spacing"] intValue];
223 tileset.margin = [[attributeDict valueForKey:@"margin"] intValue];
224 CGSize s;
225 s.width = [[attributeDict valueForKey:@"tilewidth"] intValue];
226 s.height = [[attributeDict valueForKey:@"tileheight"] intValue];
227 tileset.tileSize = s;
228
229 [tilesets_ addObject:tileset];
230 [tileset release];
231 }
232
233 }else if([elementName isEqualToString:@"tile"]){
234 CCTMXTilesetInfo* info = [tilesets_ lastObject];
235 NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:3];
236 parentGID_ = [info firstGid] + [[attributeDict valueForKey:@"id"] intValue];
237 [tileProperties_ setObject:dict forKey:[NSNumber numberWithInt:parentGID_]];
238
239 parentElement = TMXPropertyTile;
240
241 }else if([elementName isEqualToString:@"layer"]) {
242 CCTMXLayerInfo *layer = [CCTMXLayerInfo new];
243 layer.name = [attributeDict valueForKey:@"name"];
244
245 CGSize s;
246 s.width = [[attributeDict valueForKey:@"width"] intValue];
247 s.height = [[attributeDict valueForKey:@"height"] intValue];
248 layer.layerSize = s;
249
250 layer.visible = ![[attributeDict valueForKey:@"visible"] isEqualToString:@"0"];
251
252 if( [attributeDict valueForKey:@"opacity"] )
253 layer.opacity = 255 * [[attributeDict valueForKey:@"opacity"] floatValue];
254 else
255 layer.opacity = 255;
256
257 int x = [[attributeDict valueForKey:@"x"] intValue];
258 int y = [[attributeDict valueForKey:@"y"] intValue];
259 layer.offset = ccp(x,y);
260
261 [layers_ addObject:layer];
262 [layer release];
263
264 // The parent element is now "layer"
265 parentElement = TMXPropertyLayer;
266
267 } else if([elementName isEqualToString:@"objectgroup"]) {
268
269 CCTMXObjectGroup *objectGroup = [[CCTMXObjectGroup alloc] init];
270 objectGroup.groupName = [attributeDict valueForKey:@"name"];
271 CGPoint positionOffset;
272 positionOffset.x = [[attributeDict valueForKey:@"x"] intValue] * tileSize_.width;
273 positionOffset.y = [[attributeDict valueForKey:@"y"] intValue] * tileSize_.height;
274 objectGroup.positionOffset = positionOffset;
275
276 [objectGroups_ addObject:objectGroup];
277 [objectGroup release];
278
279 // The parent element is now "objectgroup"
280 parentElement = TMXPropertyObjectGroup;
281
282 } else if([elementName isEqualToString:@"image"]) {
283
284 CCTMXTilesetInfo *tileset = [tilesets_ lastObject];
285
286 // build full path
287 NSString *imagename = [attributeDict valueForKey:@"source"];
288 NSString *path = [filename_ stringByDeletingLastPathComponent];
289 tileset.sourceImage = [path stringByAppendingPathComponent:imagename];
290
291 } else if([elementName isEqualToString:@"data"]) {
292 NSString *encoding = [attributeDict valueForKey:@"encoding"];
293 NSString *compression = [attributeDict valueForKey:@"compression"];
294
295 if( [encoding isEqualToString:@"base64"] ) {
296 layerAttribs |= TMXLayerAttribBase64;
297 storingCharacters = YES;
298
299 if( [compression isEqualToString:@"gzip"] )
300 layerAttribs |= TMXLayerAttribGzip;
301
302 else if( [compression isEqualToString:@"zlib"] )
303 layerAttribs |= TMXLayerAttribZlib;
304
305 NSAssert( !compression || [compression isEqualToString:@"gzip"] || [compression isEqualToString:@"zlib"], @"TMX: unsupported compression method" );
306 }
307
308 NSAssert( layerAttribs != TMXLayerAttribNone, @"TMX tile map: Only base64 and/or gzip/zlib maps are supported" );
309
310 } else if([elementName isEqualToString:@"object"]) {
311
312 CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
313
314 // The value for "type" was blank or not a valid class name
315 // Create an instance of TMXObjectInfo to store the object and its properties
316 NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:5];
317
318 // Set the name of the object to the value for "name"
319 [dict setValue:[attributeDict valueForKey:@"name"] forKey:@"name"];
320
321 // Assign all the attributes as key/name pairs in the properties dictionary
322 [dict setValue:[attributeDict valueForKey:@"type"] forKey:@"type"];
323 int x = [[attributeDict valueForKey:@"x"] intValue] + objectGroup.positionOffset.x;
324 [dict setValue:[NSNumber numberWithInt:x] forKey:@"x"];
325 int y = [[attributeDict valueForKey:@"y"] intValue] + objectGroup.positionOffset.y;
326 // Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
327 y = (mapSize_.height * tileSize_.height) - y - [[attributeDict valueForKey:@"height"] intValue];
328 [dict setValue:[NSNumber numberWithInt:y] forKey:@"y"];
329 [dict setValue:[attributeDict valueForKey:@"width"] forKey:@"width"];
330 [dict setValue:[attributeDict valueForKey:@"height"] forKey:@"height"];
331
332 // Add the object to the objectGroup
333 [[objectGroup objects] addObject:dict];
334 [dict release];
335
336 // The parent element is now "object"
337 parentElement = TMXPropertyObject;
338
339 } else if([elementName isEqualToString:@"property"]) {
340
341 if ( parentElement == TMXPropertyNone ) {
342
343 CCLOG( @"TMX tile map: Parent element is unsupported. Cannot add property named '%@' with value '%@'",
344 [attributeDict valueForKey:@"name"], [attributeDict valueForKey:@"value"] );
345
346 } else if ( parentElement == TMXPropertyMap ) {
347
348 // The parent element is the map
349 [properties_ setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
350
351 } else if ( parentElement == TMXPropertyLayer ) {
352
353 // The parent element is the last layer
354 CCTMXLayerInfo *layer = [layers_ lastObject];
355 // Add the property to the layer
356 [[layer properties] setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
357
358 } else if ( parentElement == TMXPropertyObjectGroup ) {
359
360 // The parent element is the last object group
361 CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
362 [[objectGroup properties] setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
363
364 } else if ( parentElement == TMXPropertyObject ) {
365
366 // The parent element is the last object
367 CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
368 NSMutableDictionary *dict = [[objectGroup objects] lastObject];
369
370 NSString *propertyName = [attributeDict valueForKey:@"name"];
371 NSString *propertyValue = [attributeDict valueForKey:@"value"];
372
373 [dict setValue:propertyValue forKey:propertyName];
374 } else if ( parentElement == TMXPropertyTile ) {
375
376 NSMutableDictionary* dict = [tileProperties_ objectForKey:[NSNumber numberWithInt:parentGID_]];
377 NSString *propertyName = [attributeDict valueForKey:@"name"];
378 NSString *propertyValue = [attributeDict valueForKey:@"value"];
379 [dict setObject:propertyValue forKey:propertyName];
380
381 }
382 }
383}
384
385- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
386{
387 int len = 0;
388
389 if([elementName isEqualToString:@"data"] && layerAttribs&TMXLayerAttribBase64) {
390 storingCharacters = NO;
391
392 CCTMXLayerInfo *layer = [layers_ lastObject];
393
394 unsigned char *buffer;
395 len = base64Decode((unsigned char*)[currentString UTF8String], (unsigned int) [currentString length], &buffer);
396 if( ! buffer ) {
397 CCLOG(@"cocos2d: TiledMap: decode data error");
398 return;
399 }
400
401 if( layerAttribs & (TMXLayerAttribGzip | TMXLayerAttribZlib) ) {
402 unsigned char *deflated;
403 CGSize s = [layer layerSize];
404 int sizeHint = s.width * s.height * sizeof(uint32_t);
405
406 int inflatedLen = ccInflateMemoryWithHint(buffer, len, &deflated, sizeHint);
407 NSAssert( inflatedLen == sizeHint, @"CCTMXXMLParser: Hint failed!");
408
409 inflatedLen = (int)&inflatedLen; // XXX: to avoid warings in compiler
410
411 free( buffer );
412
413 if( ! deflated ) {
414 CCLOG(@"cocos2d: TiledMap: inflate data error");
415 return;
416 }
417
418 layer.tiles = (unsigned int*) deflated;
419 } else
420 layer.tiles = (unsigned int*) buffer;
421
422 [currentString setString:@""];
423
424 } else if ([elementName isEqualToString:@"map"]) {
425 // The map element has ended
426 parentElement = TMXPropertyNone;
427
428 } else if ([elementName isEqualToString:@"layer"]) {
429 // The layer element has ended
430 parentElement = TMXPropertyNone;
431
432 } else if ([elementName isEqualToString:@"objectgroup"]) {
433 // The objectgroup element has ended
434 parentElement = TMXPropertyNone;
435
436 } else if ([elementName isEqualToString:@"object"]) {
437 // The object element has ended
438 parentElement = TMXPropertyNone;
439 }
440}
441
442- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
443{
444 if (storingCharacters)
445 [currentString appendString:string];
446}
447
448
449//
450// the level did not load, file not found, etc.
451//
452-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
453 CCLOG(@"cocos2d: Error on XML Parse: %@", [parseError localizedDescription] );
454}
455
456@end
diff --git a/libs/cocos2d/CCTexture2D.h b/libs/cocos2d/CCTexture2D.h new file mode 100755 index 0000000..45eea9c --- /dev/null +++ b/libs/cocos2d/CCTexture2D.h
@@ -0,0 +1,328 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentation
14seeds.
15
16=====================
17
18File: Texture2D.h
19Abstract: Creates OpenGL 2D textures from images or text.
20
21Version: 1.6
22
23Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
24("Apple") in consideration of your agreement to the following terms, and your
25use, installation, modification or redistribution of this Apple software
26constitutes acceptance of these terms. If you do not agree with these terms,
27please do not use, install, modify or redistribute this Apple software.
28
29In consideration of your agreement to abide by the following terms, and subject
30to these terms, Apple grants you a personal, non-exclusive license, under
31Apple's copyrights in this original Apple software (the "Apple Software"), to
32use, reproduce, modify and redistribute the Apple Software, with or without
33modifications, in source and/or binary forms; provided that if you redistribute
34the Apple Software in its entirety and without modifications, you must retain
35this notice and the following text and disclaimers in all such redistributions
36of the Apple Software.
37Neither the name, trademarks, service marks or logos of Apple Inc. may be used
38to endorse or promote products derived from the Apple Software without specific
39prior written permission from Apple. Except as expressly stated in this notice,
40no other rights or licenses, express or implied, are granted by Apple herein,
41including but not limited to any patent rights that may be infringed by your
42derivative works or by other works in which the Apple Software may be
43incorporated.
44
45The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
46WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
47WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
49COMBINATION WITH YOUR PRODUCTS.
50
51IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
52CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
53GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
55DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
56CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
57APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58
59Copyright (C) 2008 Apple Inc. All Rights Reserved.
60
61*/
62
63#import <Availability.h>
64
65#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
66#import <UIKit/UIKit.h> // for UIImage
67#endif
68
69#import <Foundation/Foundation.h> // for NSObject
70
71#import "Platforms/CCGL.h" // OpenGL stuff
72#import "Platforms/CCNS.h" // Next-Step stuff
73
74//CONSTANTS:
75
76/** @typedef CCTexture2DPixelFormat
77 Possible texture pixel formats
78 */
79typedef enum {
80 kCCTexture2DPixelFormat_Automatic = 0,
81 //! 32-bit texture: RGBA8888
82 kCCTexture2DPixelFormat_RGBA8888,
83 //! 16-bit texture without Alpha channel
84 kCCTexture2DPixelFormat_RGB565,
85 //! 8-bit textures used as masks
86 kCCTexture2DPixelFormat_A8,
87 //! 8-bit intensity texture
88 kCCTexture2DPixelFormat_I8,
89 //! 16-bit textures used as masks
90 kCCTexture2DPixelFormat_AI88,
91 //! 16-bit textures: RGBA4444
92 kCCTexture2DPixelFormat_RGBA4444,
93 //! 16-bit textures: RGB5A1
94 kCCTexture2DPixelFormat_RGB5A1,
95 //! 4-bit PVRTC-compressed texture: PVRTC4
96 kCCTexture2DPixelFormat_PVRTC4,
97 //! 2-bit PVRTC-compressed texture: PVRTC2
98 kCCTexture2DPixelFormat_PVRTC2,
99
100 //! Default texture format: RGBA8888
101 kCCTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_RGBA8888,
102
103 // backward compatibility stuff
104 kTexture2DPixelFormat_Automatic = kCCTexture2DPixelFormat_Automatic,
105 kTexture2DPixelFormat_RGBA8888 = kCCTexture2DPixelFormat_RGBA8888,
106 kTexture2DPixelFormat_RGB565 = kCCTexture2DPixelFormat_RGB565,
107 kTexture2DPixelFormat_A8 = kCCTexture2DPixelFormat_A8,
108 kTexture2DPixelFormat_RGBA4444 = kCCTexture2DPixelFormat_RGBA4444,
109 kTexture2DPixelFormat_RGB5A1 = kCCTexture2DPixelFormat_RGB5A1,
110 kTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_Default
111
112} CCTexture2DPixelFormat;
113
114//CLASS INTERFACES:
115
116/** CCTexture2D class.
117 * This class allows to easily create OpenGL 2D textures from images, text or raw data.
118 * The created CCTexture2D object will always have power-of-two dimensions.
119 * Depending on how you create the CCTexture2D object, the actual image area of the texture might be smaller than the texture dimensions i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
120 * Be aware that the content of the generated textures will be upside-down!
121 */
122@interface CCTexture2D : NSObject
123{
124 GLuint name_;
125 CGSize size_;
126 NSUInteger width_,
127 height_;
128 CCTexture2DPixelFormat format_;
129 GLfloat maxS_,
130 maxT_;
131 BOOL hasPremultipliedAlpha_;
132}
133/** Intializes with a texture2d with data */
134- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size;
135
136/** These functions are needed to create mutable textures */
137- (void) releaseData:(void*)data;
138- (void*) keepData:(void*)data length:(NSUInteger)length;
139
140/** pixel format of the texture */
141@property(nonatomic,readonly) CCTexture2DPixelFormat pixelFormat;
142/** width in pixels */
143@property(nonatomic,readonly) NSUInteger pixelsWide;
144/** hight in pixels */
145@property(nonatomic,readonly) NSUInteger pixelsHigh;
146
147/** texture name */
148@property(nonatomic,readonly) GLuint name;
149
150/** returns content size of the texture in pixels */
151@property(nonatomic,readonly, nonatomic) CGSize contentSizeInPixels;
152
153/** texture max S */
154@property(nonatomic,readwrite) GLfloat maxS;
155/** texture max T */
156@property(nonatomic,readwrite) GLfloat maxT;
157/** whether or not the texture has their Alpha premultiplied */
158@property(nonatomic,readonly) BOOL hasPremultipliedAlpha;
159
160/** returns the content size of the texture in points */
161-(CGSize) contentSize;
162@end
163
164/**
165Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
166These functions require GL_TEXTURE_2D and both GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY client states to be enabled.
167*/
168@interface CCTexture2D (Drawing)
169/** draws a texture at a given point */
170- (void) drawAtPoint:(CGPoint)point;
171/** draws a texture inside a rect */
172- (void) drawInRect:(CGRect)rect;
173@end
174
175/**
176Extensions to make it easy to create a CCTexture2D object from an image file.
177Note that RGBA type textures will have their alpha premultiplied - use the blending mode (GL_ONE, GL_ONE_MINUS_SRC_ALPHA).
178*/
179@interface CCTexture2D (Image)
180/** Initializes a texture from a UIImage object */
181#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
182- (id) initWithImage:(UIImage *)uiImage;
183#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
184- (id) initWithImage:(CGImageRef)cgImage;
185#endif
186@end
187
188/**
189Extensions to make it easy to create a CCTexture2D object from a string of text.
190Note that the generated textures are of type A8 - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
191*/
192@interface CCTexture2D (Text)
193/** Initializes a texture from a string with dimensions, alignment, line break mode, font name and font size
194 Supported lineBreakModes:
195 - iOS: all UILineBreakMode supported modes
196 - Mac: Only NSLineBreakByWordWrapping is supported.
197 @since v1.0
198 */
199- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size;
200/** Initializes a texture from a string with dimensions, alignment, font name and font size */
201- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size;
202/** Initializes a texture from a string with font name and font size */
203- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size;
204@end
205
206
207/**
208 Extensions to make it easy to create a CCTexture2D object from a PVRTC file
209 Note that the generated textures don't have their alpha premultiplied - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
210 */
211@interface CCTexture2D (PVRSupport)
212/** Initializes a texture from a PVR Texture Compressed (PVRTC) buffer
213 *
214 * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
215 */
216#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
217-(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length pixelFormat:(CCTexture2DPixelFormat)pixelFormat;
218#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
219/** Initializes a texture from a PVR file.
220
221 Supported PVR formats:
222 - BGRA 8888
223 - RGBA 8888
224 - RGBA 4444
225 - RGBA 5551
226 - RBG 565
227 - A 8
228 - I 8
229 - AI 8
230 - PVRTC 2BPP
231 - PVRTC 4BPP
232
233 By default PVR images are treated as if they alpha channel is NOT premultiplied. You can override this behavior with this class method:
234 - PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied;
235
236 IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
237
238 */
239-(id) initWithPVRFile: (NSString*) file;
240
241/** treats (or not) PVR files as if they have alpha premultiplied.
242 Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is
243 possible load them as if they have (or not) the alpha channel premultiplied.
244
245 By default it is disabled.
246
247 @since v0.99.5
248 */
249+(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied;
250@end
251
252/**
253 Extension to set the Min / Mag filter
254 */
255typedef struct _ccTexParams {
256 GLuint minFilter;
257 GLuint magFilter;
258 GLuint wrapS;
259 GLuint wrapT;
260} ccTexParams;
261
262@interface CCTexture2D (GLFilter)
263/** sets the min filter, mag filter, wrap s and wrap t texture parameters.
264 If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}.
265 @since v0.8
266 */
267-(void) setTexParameters: (ccTexParams*) texParams;
268
269/** sets antialias texture parameters:
270 - GL_TEXTURE_MIN_FILTER = GL_LINEAR
271 - GL_TEXTURE_MAG_FILTER = GL_LINEAR
272
273 @since v0.8
274 */
275- (void) setAntiAliasTexParameters;
276
277/** sets alias texture parameters:
278 - GL_TEXTURE_MIN_FILTER = GL_NEAREST
279 - GL_TEXTURE_MAG_FILTER = GL_NEAREST
280
281 @since v0.8
282 */
283- (void) setAliasTexParameters;
284
285
286/** Generates mipmap images for the texture.
287 It only works if the texture size is POT (power of 2).
288 @since v0.99.0
289 */
290-(void) generateMipmap;
291
292
293@end
294
295@interface CCTexture2D (PixelFormat)
296/** sets the default pixel format for UIImages that contains alpha channel.
297 If the UIImage contains alpha channel, then the options are:
298 - generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one)
299 - generate 16-bit textures: kCCTexture2DPixelFormat_RGBA4444
300 - generate 16-bit textures: kCCTexture2DPixelFormat_RGB5A1
301 - generate 16-bit textures: kCCTexture2DPixelFormat_RGB565
302 - generate 8-bit textures: kCCTexture2DPixelFormat_A8 (only use it if you use just 1 color)
303
304 How does it work ?
305 - If the image is an RGBA (with Alpha) then the default pixel format will be used (it can be a 8-bit, 16-bit or 32-bit texture)
306 - If the image is an RGB (without Alpha) then an RGB565 texture will be used (16-bit texture)
307
308 This parameter is not valid for PVR images.
309
310 @since v0.8
311 */
312+(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format;
313
314/** returns the alpha pixel format
315 @since v0.8
316 */
317+(CCTexture2DPixelFormat) defaultAlphaPixelFormat;
318
319/** returns the bits-per-pixel of the in-memory OpenGL texture
320 @since v1.0
321 */
322-(NSUInteger) bitsPerPixelForFormat;
323@end
324
325
326
327
328
diff --git a/libs/cocos2d/CCTexture2D.m b/libs/cocos2d/CCTexture2D.m new file mode 100755 index 0000000..afa64e2 --- /dev/null +++ b/libs/cocos2d/CCTexture2D.m
@@ -0,0 +1,814 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentationd
14seeds.
15
16=====================
17
18File: Texture2D.m
19Abstract: Creates OpenGL 2D textures from images or text.
20
21Version: 1.6
22
23Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
24("Apple") in consideration of your agreement to the following terms, and your
25use, installation, modification or redistribution of this Apple software
26constitutes acceptance of these terms. If you do not agree with these terms,
27please do not use, install, modify or redistribute this Apple software.
28
29In consideration of your agreement to abide by the following terms, and subject
30to these terms, Apple grants you a personal, non-exclusive license, under
31Apple's copyrights in this original Apple software (the "Apple Software"), to
32use, reproduce, modify and redistribute the Apple Software, with or without
33modifications, in source and/or binary forms; provided that if you redistribute
34the Apple Software in its entirety and without modifications, you must retain
35this notice and the following text and disclaimers in all such redistributions
36of the Apple Software.
37Neither the name, trademarks, service marks or logos of Apple Inc. may be used
38to endorse or promote products derived from the Apple Software without specific
39prior written permission from Apple. Except as expressly stated in this notice,
40no other rights or licenses, express or implied, are granted by Apple herein,
41including but not limited to any patent rights that may be infringed by your
42derivative works or by other works in which the Apple Software may be
43incorporated.
44
45The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
46WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
47WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
49COMBINATION WITH YOUR PRODUCTS.
50
51IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
52CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
53GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
55DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
56CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
57APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58
59Copyright (C) 2008 Apple Inc. All Rights Reserved.
60
61*/
62
63/*
64 * Support for RGBA_4_4_4_4 and RGBA_5_5_5_1 was copied from:
65 * https://devforums.apple.com/message/37855#37855 by a1studmuffin
66 */
67
68
69#import <Availability.h>
70
71#import "Platforms/CCGL.h"
72#import "Platforms/CCNS.h"
73
74
75#import "CCTexture2D.h"
76#import "ccConfig.h"
77#import "ccMacros.h"
78#import "CCConfiguration.h"
79#import "Support/ccUtils.h"
80#import "CCTexturePVR.h"
81
82#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && CC_FONT_LABEL_SUPPORT
83// FontLabel support
84#import "FontManager.h"
85#import "FontLabelStringDrawing.h"
86#endif// CC_FONT_LABEL_SUPPORT
87
88
89// For Labels use 16-bit textures on iPhone 3GS / iPads since A8 textures are very slow
90#if (defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR) && CC_USE_LA88_LABELS_ON_NEON_ARCH
91#define USE_TEXT_WITH_A8_TEXTURES 0
92
93#else
94#define USE_TEXT_WITH_A8_TEXTURES 1
95#endif
96
97//CLASS IMPLEMENTATIONS:
98
99
100// If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit)
101// Default is: RGBA8888 (32-bit textures)
102static CCTexture2DPixelFormat defaultAlphaPixelFormat_ = kCCTexture2DPixelFormat_Default;
103
104#pragma mark -
105#pragma mark CCTexture2D - Main
106
107@implementation CCTexture2D
108
109@synthesize contentSizeInPixels = size_, pixelFormat = format_, pixelsWide = width_, pixelsHigh = height_, name = name_, maxS = maxS_, maxT = maxT_;
110@synthesize hasPremultipliedAlpha = hasPremultipliedAlpha_;
111
112- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
113{
114 if((self = [super init])) {
115 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
116 glGenTextures(1, &name_);
117 glBindTexture(GL_TEXTURE_2D, name_);
118
119 [self setAntiAliasTexParameters];
120
121 // Specify OpenGL texture image
122
123 switch(pixelFormat)
124 {
125 case kCCTexture2DPixelFormat_RGBA8888:
126 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
127 break;
128 case kCCTexture2DPixelFormat_RGBA4444:
129 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
130 break;
131 case kCCTexture2DPixelFormat_RGB5A1:
132 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data);
133 break;
134 case kCCTexture2DPixelFormat_RGB565:
135 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
136 break;
137 case kCCTexture2DPixelFormat_AI88:
138 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
139 break;
140 case kCCTexture2DPixelFormat_A8:
141 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
142 break;
143 default:
144 [NSException raise:NSInternalInconsistencyException format:@""];
145
146 }
147
148 size_ = size;
149 width_ = width;
150 height_ = height;
151 format_ = pixelFormat;
152 maxS_ = size.width / (float)width;
153 maxT_ = size.height / (float)height;
154
155 hasPremultipliedAlpha_ = NO;
156 }
157 return self;
158}
159
160- (void) releaseData:(void*)data
161{
162 //Free data
163 free(data);
164}
165
166- (void*) keepData:(void*)data length:(NSUInteger)length
167{
168 //The texture data mustn't be saved becuase it isn't a mutable texture.
169 return data;
170}
171
172- (void) dealloc
173{
174 CCLOGINFO(@"cocos2d: deallocing %@", self);
175 if(name_)
176 glDeleteTextures(1, &name_);
177
178 [super dealloc];
179}
180
181- (NSString*) description
182{
183 return [NSString stringWithFormat:@"<%@ = %08X | Name = %i | Dimensions = %ix%i | Coordinates = (%.2f, %.2f)>", [self class], self, name_, width_, height_, maxS_, maxT_];
184}
185
186-(CGSize) contentSize
187{
188 CGSize ret;
189 ret.width = size_.width / CC_CONTENT_SCALE_FACTOR();
190 ret.height = size_.height / CC_CONTENT_SCALE_FACTOR();
191
192 return ret;
193}
194@end
195
196#pragma mark -
197#pragma mark CCTexture2D - Image
198
199@implementation CCTexture2D (Image)
200#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
201- (id) initWithImage:(UIImage *)uiImage
202#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
203- (id) initWithImage:(CGImageRef)CGImage
204#endif
205{
206 NSUInteger POTWide, POTHigh;
207 CGContextRef context = nil;
208 void* data = nil;;
209 CGColorSpaceRef colorSpace;
210 void* tempData;
211 unsigned int* inPixel32;
212 unsigned short* outPixel16;
213 BOOL hasAlpha;
214 CGImageAlphaInfo info;
215 CGSize imageSize;
216 CCTexture2DPixelFormat pixelFormat;
217
218#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
219 CGImageRef CGImage = uiImage.CGImage;
220#endif
221
222 if(CGImage == NULL) {
223 CCLOG(@"cocos2d: CCTexture2D. Can't create Texture. UIImage is nil");
224 [self release];
225 return nil;
226 }
227
228 CCConfiguration *conf = [CCConfiguration sharedConfiguration];
229
230#if CC_TEXTURE_NPOT_SUPPORT
231 if( [conf supportsNPOT] ) {
232 POTWide = CGImageGetWidth(CGImage);
233 POTHigh = CGImageGetHeight(CGImage);
234
235 } else
236#endif
237 {
238 POTWide = ccNextPOT(CGImageGetWidth(CGImage));
239 POTHigh = ccNextPOT(CGImageGetHeight(CGImage));
240 }
241
242 NSUInteger maxTextureSize = [conf maxTextureSize];
243 if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) {
244 CCLOG(@"cocos2d: WARNING: Image (%lu x %lu) is bigger than the supported %ld x %ld",
245 (long)POTWide, (long)POTHigh,
246 (long)maxTextureSize, (long)maxTextureSize);
247 [self release];
248 return nil;
249 }
250
251 info = CGImageGetAlphaInfo(CGImage);
252 hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
253
254 size_t bpp = CGImageGetBitsPerComponent(CGImage);
255 colorSpace = CGImageGetColorSpace(CGImage);
256
257 if(colorSpace) {
258 if(hasAlpha || bpp >= 8)
259 pixelFormat = defaultAlphaPixelFormat_;
260 else {
261 CCLOG(@"cocos2d: CCTexture2D: Using RGB565 texture since image has no alpha");
262 pixelFormat = kCCTexture2DPixelFormat_RGB565;
263 }
264 } else {
265 // NOTE: No colorspace means a mask image
266 CCLOG(@"cocos2d: CCTexture2D: Using A8 texture since image is a mask");
267 pixelFormat = kCCTexture2DPixelFormat_A8;
268 }
269
270 imageSize = CGSizeMake(CGImageGetWidth(CGImage), CGImageGetHeight(CGImage));
271
272 // Create the bitmap graphics context
273
274 switch(pixelFormat) {
275 case kCCTexture2DPixelFormat_RGBA8888:
276 case kCCTexture2DPixelFormat_RGBA4444:
277 case kCCTexture2DPixelFormat_RGB5A1:
278 colorSpace = CGColorSpaceCreateDeviceRGB();
279 data = malloc(POTHigh * POTWide * 4);
280 info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast;
281// info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images.
282 context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
283 CGColorSpaceRelease(colorSpace);
284 break;
285
286 case kCCTexture2DPixelFormat_RGB565:
287 colorSpace = CGColorSpaceCreateDeviceRGB();
288 data = malloc(POTHigh * POTWide * 4);
289 info = kCGImageAlphaNoneSkipLast;
290 context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
291 CGColorSpaceRelease(colorSpace);
292 break;
293 case kCCTexture2DPixelFormat_A8:
294 data = malloc(POTHigh * POTWide);
295 info = kCGImageAlphaOnly;
296 context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, NULL, info);
297 break;
298 default:
299 [NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"];
300 }
301
302
303 CGContextClearRect(context, CGRectMake(0, 0, POTWide, POTHigh));
304 CGContextTranslateCTM(context, 0, POTHigh - imageSize.height);
305 CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(CGImage), CGImageGetHeight(CGImage)), CGImage);
306
307 // Repack the pixel data into the right format
308
309 if(pixelFormat == kCCTexture2DPixelFormat_RGB565) {
310 //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
311 tempData = malloc(POTHigh * POTWide * 2);
312 inPixel32 = (unsigned int*)data;
313 outPixel16 = (unsigned short*)tempData;
314 for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
315 *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
316 free(data);
317 data = tempData;
318
319 }
320 else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) {
321 //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
322 tempData = malloc(POTHigh * POTWide * 2);
323 inPixel32 = (unsigned int*)data;
324 outPixel16 = (unsigned short*)tempData;
325 for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
326 *outPixel16++ =
327 ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R
328 ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G
329 ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B
330 ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A
331
332
333 free(data);
334 data = tempData;
335
336 }
337 else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) {
338 //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
339 tempData = malloc(POTHigh * POTWide * 2);
340 inPixel32 = (unsigned int*)data;
341 outPixel16 = (unsigned short*)tempData;
342 for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
343 *outPixel16++ =
344 ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R
345 ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G
346 ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B
347 ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A
348
349
350 free(data);
351 data = tempData;
352 }
353 self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:POTWide pixelsHigh:POTHigh contentSize:imageSize];
354
355 // should be after calling super init
356 hasPremultipliedAlpha_ = (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst);
357
358 CGContextRelease(context);
359 [self releaseData:data];
360
361 return self;
362}
363@end
364
365#pragma mark -
366#pragma mark CCTexture2D - Text
367
368@implementation CCTexture2D (Text)
369
370#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
371
372- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode font:(id)uifont
373{
374 NSAssert( uifont, @"Invalid font");
375
376 NSUInteger POTWide = ccNextPOT(dimensions.width);
377 NSUInteger POTHigh = ccNextPOT(dimensions.height);
378 unsigned char* data;
379
380 CGContextRef context;
381 CGColorSpaceRef colorSpace;
382
383#if USE_TEXT_WITH_A8_TEXTURES
384 data = calloc(POTHigh, POTWide);
385#else
386 data = calloc(POTHigh, POTWide * 2);
387#endif
388
389 colorSpace = CGColorSpaceCreateDeviceGray();
390 context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, colorSpace, kCGImageAlphaNone);
391 CGColorSpaceRelease(colorSpace);
392
393 if( ! context ) {
394 free(data);
395 [self release];
396 return nil;
397 }
398
399 CGContextSetGrayFillColor(context, 1.0f, 1.0f);
400 CGContextTranslateCTM(context, 0.0f, POTHigh);
401 CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
402
403 UIGraphicsPushContext(context);
404
405 // normal fonts
406 if( [uifont isKindOfClass:[UIFont class] ] )
407 [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:uifont lineBreakMode:lineBreakMode alignment:alignment];
408
409#if CC_FONT_LABEL_SUPPORT
410 else // ZFont class
411 [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withZFont:uifont lineBreakMode:lineBreakMode alignment:alignment];
412#endif
413
414 UIGraphicsPopContext();
415
416#if USE_TEXT_WITH_A8_TEXTURES
417 self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
418
419#else // ! USE_TEXT_WITH_A8_TEXTURES
420 NSUInteger textureSize = POTWide*POTHigh;
421 unsigned short *la88_data = (unsigned short*)data;
422 for(int i = textureSize-1; i>=0; i--) //Convert A8 to AI88
423 la88_data[i] = (data[i] << 8) | 0xff;
424
425 self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_AI88 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
426#endif // ! USE_TEXT_WITH_A8_TEXTURES
427
428 CGContextRelease(context);
429 [self releaseData:data];
430
431 return self;
432}
433
434
435
436#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
437
438- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment attributedString:(NSAttributedString*)stringWithAttributes
439{
440 NSAssert( stringWithAttributes, @"Invalid stringWithAttributes");
441
442 NSUInteger POTWide = ccNextPOT(dimensions.width);
443 NSUInteger POTHigh = ccNextPOT(dimensions.height);
444 unsigned char* data;
445
446 NSSize realDimensions = [stringWithAttributes size];
447
448 //Alignment
449 float xPadding = 0;
450
451 // Mac crashes if the width or height is 0
452 if( realDimensions.width > 0 && realDimensions.height > 0 ) {
453 switch (alignment) {
454 case CCTextAlignmentLeft: xPadding = 0; break;
455 case CCTextAlignmentCenter: xPadding = (dimensions.width-realDimensions.width)/2.0f; break;
456 case CCTextAlignmentRight: xPadding = dimensions.width-realDimensions.width; break;
457 default: break;
458 }
459
460 //Disable antialias
461 [[NSGraphicsContext currentContext] setShouldAntialias:NO];
462
463 NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)];
464 [image lockFocus];
465
466 [stringWithAttributes drawAtPoint:NSMakePoint(xPadding, POTHigh-dimensions.height)]; // draw at offset position
467
468 NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)];
469 [image unlockFocus];
470
471 data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance.
472
473 NSUInteger textureSize = POTWide*POTHigh;
474 for(int i = 0; i<textureSize; i++) //Convert RGBA8888 to A8
475 data[i] = data[i*4+3];
476
477 data = [self keepData:data length:textureSize];
478 self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
479
480 [bitmap release];
481 [image release];
482
483 } else {
484 [self release];
485 return nil;
486 }
487
488 return self;
489}
490#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
491
492- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size
493{
494 CGSize dim;
495
496#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
497 id font;
498 font = [UIFont fontWithName:name size:size];
499 if( font )
500 dim = [string sizeWithFont:font];
501
502#if CC_FONT_LABEL_SUPPORT
503 if( ! font ){
504 font = [[FontManager sharedManager] zFontWithName:name pointSize:size];
505 if (font)
506 dim = [string sizeWithZFont:font];
507 }
508#endif // CC_FONT_LABEL_SUPPORT
509
510 if( ! font ) {
511 CCLOG(@"cocos2d: Unable to load font %@", name);
512 [self release];
513 return nil;
514 }
515
516 return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter lineBreakMode:UILineBreakModeWordWrap font:font];
517
518#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
519 {
520
521 NSFont *font = [[NSFontManager sharedFontManager]
522 fontWithFamily:name
523 traits:NSUnboldFontMask | NSUnitalicFontMask
524 weight:0
525 size:size];
526
527 NSDictionary *dict = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
528
529 NSAttributedString *stringWithAttributes = [[[NSAttributedString alloc] initWithString:string attributes:dict] autorelease];
530
531 dim = NSSizeToCGSize( [stringWithAttributes size] );
532
533 return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter attributedString:stringWithAttributes];
534 }
535#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
536
537}
538
539- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
540{
541 return [self initWithString:string dimensions:dimensions alignment:alignment lineBreakMode:CCLineBreakModeWordWrap fontName:name fontSize:size];
542}
543
544- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size
545{
546#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
547 id uifont = nil;
548
549 uifont = [UIFont fontWithName:name size:size];
550
551#if CC_FONT_LABEL_SUPPORT
552 if( ! uifont )
553 uifont = [[FontManager sharedManager] zFontWithName:name pointSize:size];
554#endif // CC_FONT_LABEL_SUPPORT
555 if( ! uifont ) {
556 CCLOG(@"cocos2d: Texture2d: Invalid Font: %@. Verify the .ttf name", name);
557 [self release];
558 return nil;
559 }
560
561 return [self initWithString:string dimensions:dimensions alignment:alignment lineBreakMode:lineBreakMode font:uifont];
562
563#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
564
565 NSAssert( lineBreakMode == CCLineBreakModeWordWrap, @"CCTexture2D: unsupported line break mode for Mac OS X");
566
567 //String with attributes
568 NSAttributedString *stringWithAttributes =
569 [[[NSAttributedString alloc] initWithString:string
570 attributes:[NSDictionary dictionaryWithObject:[[NSFontManager sharedFontManager]
571 fontWithFamily:name
572 traits:NSUnboldFontMask | NSUnitalicFontMask
573 weight:0
574 size:size]
575 forKey:NSFontAttributeName]
576 ]
577 autorelease];
578
579 return [self initWithString:string dimensions:dimensions alignment:alignment attributedString:stringWithAttributes];
580
581#endif // Mac
582}
583@end
584
585#pragma mark -
586#pragma mark CCTexture2D - PVRSupport
587
588@implementation CCTexture2D (PVRSupport)
589
590// By default PVR images are treated as if they don't have the alpha channel premultiplied
591static BOOL PVRHaveAlphaPremultiplied_ = NO;
592
593#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
594-(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length pixelFormat:(CCTexture2DPixelFormat)pixelFormat
595{
596 // GLint saveName;
597
598 if( ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) {
599 CCLOG(@"cocos2d: WARNING: PVRTC images is not supported");
600 [self release];
601 return nil;
602 }
603
604 if((self = [super init])) {
605 glGenTextures(1, &name_);
606 glBindTexture(GL_TEXTURE_2D, name_);
607
608 [self setAntiAliasTexParameters];
609
610 GLenum format;
611 GLsizei size = length * length * bpp / 8;
612 if(hasAlpha)
613 format = (bpp == 4) ? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
614 else
615 format = (bpp == 4) ? GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
616
617 if(size < 32)
618 size = 32;
619
620 glCompressedTexImage2D(GL_TEXTURE_2D, level, format, length, length, 0, size, data);
621
622 size_ = CGSizeMake(length, length);
623 width_ = length;
624 height_ = length;
625 maxS_ = 1.0f;
626 maxT_ = 1.0f;
627 hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_;
628 format_ = pixelFormat;
629 }
630 return self;
631}
632#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
633
634-(id) initWithPVRFile: (NSString*) file
635{
636 if( (self = [super init]) ) {
637 CCTexturePVR *pvr = [[CCTexturePVR alloc] initWithContentsOfFile:file];
638 if( pvr ) {
639 pvr.retainName = YES; // don't dealloc texture on release
640
641 name_ = pvr.name; // texture id
642 maxS_ = 1; // only POT texture are supported
643 maxT_ = 1;
644 width_ = pvr.width;
645 height_ = pvr.height;
646 size_ = CGSizeMake(width_, height_);
647 hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_;
648 format_ = pvr.format;
649
650 [pvr release];
651
652 [self setAntiAliasTexParameters];
653 } else {
654
655 CCLOG(@"cocos2d: Couldn't load PVR image: %@", file);
656 [self release];
657 return nil;
658 }
659 }
660 return self;
661}
662
663+(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied
664{
665 PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
666}
667@end
668
669#pragma mark -
670#pragma mark CCTexture2D - Drawing
671
672@implementation CCTexture2D (Drawing)
673
674- (void) drawAtPoint:(CGPoint)point
675{
676 GLfloat coordinates[] = { 0.0f, maxT_,
677 maxS_, maxT_,
678 0.0f, 0.0f,
679 maxS_, 0.0f };
680 GLfloat width = (GLfloat)width_ * maxS_,
681 height = (GLfloat)height_ * maxT_;
682
683 GLfloat vertices[] = { point.x, point.y, 0.0f,
684 width + point.x, point.y, 0.0f,
685 point.x, height + point.y, 0.0f,
686 width + point.x, height + point.y, 0.0f };
687
688 glBindTexture(GL_TEXTURE_2D, name_);
689 glVertexPointer(3, GL_FLOAT, 0, vertices);
690 glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
691 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
692}
693
694
695- (void) drawInRect:(CGRect)rect
696{
697 GLfloat coordinates[] = { 0.0f, maxT_,
698 maxS_, maxT_,
699 0.0f, 0.0f,
700 maxS_, 0.0f };
701 GLfloat vertices[] = { rect.origin.x, rect.origin.y, /*0.0f,*/
702 rect.origin.x + rect.size.width, rect.origin.y, /*0.0f,*/
703 rect.origin.x, rect.origin.y + rect.size.height, /*0.0f,*/
704 rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, /*0.0f*/ };
705
706 glBindTexture(GL_TEXTURE_2D, name_);
707 glVertexPointer(2, GL_FLOAT, 0, vertices);
708 glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
709 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
710}
711
712@end
713
714
715#pragma mark -
716#pragma mark CCTexture2D - GLFilter
717
718//
719// Use to apply MIN/MAG filter
720//
721@implementation CCTexture2D (GLFilter)
722
723-(void) generateMipmap
724{
725 NSAssert( width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_), @"Mimpap texture only works in POT textures");
726 glBindTexture( GL_TEXTURE_2D, name_ );
727 ccglGenerateMipmap(GL_TEXTURE_2D);
728}
729
730-(void) setTexParameters: (ccTexParams*) texParams
731{
732 NSAssert( (width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_)) ||
733 (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
734 @"GL_CLAMP_TO_EDGE should be used in NPOT textures");
735 glBindTexture( GL_TEXTURE_2D, name_ );
736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams->minFilter );
737 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams->magFilter );
738 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams->wrapS );
739 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParams->wrapT );
740}
741
742-(void) setAliasTexParameters
743{
744 ccTexParams texParams = { GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
745 [self setTexParameters: &texParams];
746}
747
748-(void) setAntiAliasTexParameters
749{
750 ccTexParams texParams = { GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
751 [self setTexParameters: &texParams];
752}
753@end
754
755
756#pragma mark -
757#pragma mark CCTexture2D - Pixel Format
758
759//
760// Texture options for images that contains alpha
761//
762@implementation CCTexture2D (PixelFormat)
763+(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format
764{
765 defaultAlphaPixelFormat_ = format;
766}
767
768+(CCTexture2DPixelFormat) defaultAlphaPixelFormat
769{
770 return defaultAlphaPixelFormat_;
771}
772
773-(NSUInteger) bitsPerPixelForFormat
774{
775 NSUInteger ret=0;
776
777 switch (format_) {
778 case kCCTexture2DPixelFormat_RGBA8888:
779 ret = 32;
780 break;
781 case kCCTexture2DPixelFormat_RGB565:
782 ret = 16;
783 break;
784 case kCCTexture2DPixelFormat_A8:
785 ret = 8;
786 break;
787 case kCCTexture2DPixelFormat_RGBA4444:
788 ret = 16;
789 break;
790 case kCCTexture2DPixelFormat_RGB5A1:
791 ret = 16;
792 break;
793 case kCCTexture2DPixelFormat_PVRTC4:
794 ret = 4;
795 break;
796 case kCCTexture2DPixelFormat_PVRTC2:
797 ret = 2;
798 break;
799 case kCCTexture2DPixelFormat_I8:
800 ret = 8;
801 break;
802 case kCCTexture2DPixelFormat_AI88:
803 ret = 16;
804 break;
805 default:
806 ret = -1;
807 NSAssert1(NO , @"bitsPerPixelForFormat: %ld, unrecognised pixel format", (long)format_);
808 CCLOG(@"bitsPerPixelForFormat: %ld, cannot give useful result", (long)format_);
809 break;
810 }
811 return ret;
812}
813@end
814
diff --git a/libs/cocos2d/CCTextureAtlas.h b/libs/cocos2d/CCTextureAtlas.h new file mode 100755 index 0000000..f70bb54 --- /dev/null +++ b/libs/cocos2d/CCTextureAtlas.h
@@ -0,0 +1,147 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCTexture2D.h"
28#import "ccTypes.h"
29#import "ccConfig.h"
30
31/** A class that implements a Texture Atlas.
32 Supported features:
33 * The atlas file can be a PVRTC, PNG or any other fomrat supported by Texture2D
34 * Quads can be udpated in runtime
35 * Quads can be added in runtime
36 * Quads can be removed in runtime
37 * Quads can be re-ordered in runtime
38 * The TextureAtlas capacity can be increased or decreased in runtime
39 * OpenGL component: V3F, C4B, T2F.
40 The quads are rendered using an OpenGL ES VBO.
41 To render the quads using an interleaved vertex array list, you should modify the ccConfig.h file
42 */
43@interface CCTextureAtlas : NSObject
44{
45 NSUInteger totalQuads_;
46 NSUInteger capacity_;
47 ccV3F_C4B_T2F_Quad *quads_; // quads to be rendered
48 GLushort *indices_;
49 CCTexture2D *texture_;
50#if CC_USES_VBO
51 GLuint buffersVBO_[2]; //0: vertex 1: indices
52 BOOL dirty_; //indicates whether or not the array buffer of the VBO needs to be updated
53#endif // CC_USES_VBO
54}
55
56/** quantity of quads that are going to be drawn */
57@property (nonatomic,readonly) NSUInteger totalQuads;
58/** quantity of quads that can be stored with the current texture atlas size */
59@property (nonatomic,readonly) NSUInteger capacity;
60/** Texture of the texture atlas */
61@property (nonatomic,retain) CCTexture2D *texture;
62/** Quads that are going to be rendered */
63@property (nonatomic,readwrite) ccV3F_C4B_T2F_Quad *quads;
64
65/** creates a TextureAtlas with an filename and with an initial capacity for Quads.
66 * The TextureAtlas capacity can be increased in runtime.
67 */
68+(id) textureAtlasWithFile:(NSString*)file capacity:(NSUInteger)capacity;
69
70/** initializes a TextureAtlas with a filename and with a certain capacity for Quads.
71 * The TextureAtlas capacity can be increased in runtime.
72 *
73 * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706)
74 */
75-(id) initWithFile: (NSString*) file capacity:(NSUInteger)capacity;
76
77/** creates a TextureAtlas with a previously initialized Texture2D object, and
78 * with an initial capacity for n Quads.
79 * The TextureAtlas capacity can be increased in runtime.
80 */
81+(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
82
83/** initializes a TextureAtlas with a previously initialized Texture2D object, and
84 * with an initial capacity for Quads.
85 * The TextureAtlas capacity can be increased in runtime.
86 *
87 * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706)
88 */
89-(id) initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
90
91/** updates a Quad (texture, vertex and color) at a certain index
92 * index must be between 0 and the atlas capacity - 1
93 @since v0.8
94 */
95-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index;
96
97/** Inserts a Quad (texture, vertex and color) at a certain index
98 index must be between 0 and the atlas capacity - 1
99 @since v0.8
100 */
101-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index;
102
103/** Removes the quad that is located at a certain index and inserts it at a new index
104 This operation is faster than removing and inserting in a quad in 2 different steps
105 @since v0.7.2
106*/
107-(void) insertQuadFromIndex:(NSUInteger)fromIndex atIndex:(NSUInteger)newIndex;
108
109/** removes a quad at a given index number.
110 The capacity remains the same, but the total number of quads to be drawn is reduced in 1
111 @since v0.7.2
112 */
113-(void) removeQuadAtIndex:(NSUInteger) index;
114
115/** removes all Quads.
116 The TextureAtlas capacity remains untouched. No memory is freed.
117 The total number of quads to be drawn will be 0
118 @since v0.7.2
119 */
120-(void) removeAllQuads;
121
122/** resize the capacity of the CCTextureAtlas.
123 * The new capacity can be lower or higher than the current one
124 * It returns YES if the resize was successful.
125 * If it fails to resize the capacity it will return NO with a new capacity of 0.
126 */
127-(BOOL) resizeCapacity: (NSUInteger) n;
128
129
130/** draws n quads
131 * n can't be greater than the capacity of the Atlas
132 */
133-(void) drawNumberOfQuads: (NSUInteger) n;
134
135
136/** draws n quads from an index (offset).
137 n + start can't be greater than the capacity of the atlas
138
139 @since v1.0
140 */
141-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start;
142
143/** draws all the Atlas's Quads
144 */
145-(void) drawQuads;
146
147@end
diff --git a/libs/cocos2d/CCTextureAtlas.m b/libs/cocos2d/CCTextureAtlas.m new file mode 100755 index 0000000..7c7df75 --- /dev/null +++ b/libs/cocos2d/CCTextureAtlas.m
@@ -0,0 +1,369 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28// cocos2d
29#import "CCTextureAtlas.h"
30#import "ccMacros.h"
31#import "CCTexture2D.h"
32#import "CCTextureCache.h"
33
34
35@interface CCTextureAtlas (Private)
36-(void) initIndices;
37@end
38
39//According to some tests GL_TRIANGLE_STRIP is slower, MUCH slower. Probably I'm doing something very wrong
40
41@implementation CCTextureAtlas
42
43@synthesize totalQuads = totalQuads_, capacity = capacity_;
44@synthesize texture = texture_;
45@synthesize quads = quads_;
46
47#pragma mark TextureAtlas - alloc & init
48
49+(id) textureAtlasWithFile:(NSString*) file capacity: (NSUInteger) n
50{
51 return [[[self alloc] initWithFile:file capacity:n] autorelease];
52}
53
54+(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)n
55{
56 return [[[self alloc] initWithTexture:tex capacity:n] autorelease];
57}
58
59-(id) initWithFile:(NSString*)file capacity:(NSUInteger)n
60{
61 // retained in property
62 CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:file];
63 if( tex )
64 return [self initWithTexture:tex capacity:n];
65
66 // else
67 {
68 CCLOG(@"cocos2d: Could not open file: %@", file);
69 [self release];
70 return nil;
71 }
72}
73
74-(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n
75{
76 if( (self=[super init]) ) {
77
78 capacity_ = n;
79 totalQuads_ = 0;
80
81 // retained in property
82 self.texture = tex;
83
84 // Re-initialization is not allowed
85 NSAssert(quads_==nil && indices_==nil, @"CCTextureAtlas re-initialization is not allowed");
86
87 quads_ = calloc( sizeof(quads_[0]) * capacity_, 1 );
88 indices_ = calloc( sizeof(indices_[0]) * capacity_ * 6, 1 );
89
90 if( ! ( quads_ && indices_) ) {
91 CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
92 if( quads_ )
93 free(quads_);
94 if( indices_ )
95 free(indices_);
96 return nil;
97 }
98
99#if CC_USES_VBO
100 // initial binding
101 glGenBuffers(2, &buffersVBO_[0]);
102 dirty_ = YES;
103#endif // CC_USES_VBO
104
105 [self initIndices];
106 }
107
108 return self;
109}
110
111- (NSString*) description
112{
113 return [NSString stringWithFormat:@"<%@ = %08X | totalQuads = %i>", [self class], self, totalQuads_];
114}
115
116-(void) dealloc
117{
118 CCLOGINFO(@"cocos2d: deallocing %@",self);
119
120 free(quads_);
121 free(indices_);
122
123#if CC_USES_VBO
124 glDeleteBuffers(2, buffersVBO_);
125#endif // CC_USES_VBO
126
127
128 [texture_ release];
129
130 [super dealloc];
131}
132
133-(void) initIndices
134{
135 for( NSUInteger i=0;i< capacity_;i++) {
136#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
137 indices_[i*6+0] = i*4+0;
138 indices_[i*6+1] = i*4+0;
139 indices_[i*6+2] = i*4+2;
140 indices_[i*6+3] = i*4+1;
141 indices_[i*6+4] = i*4+3;
142 indices_[i*6+5] = i*4+3;
143#else
144 indices_[i*6+0] = i*4+0;
145 indices_[i*6+1] = i*4+1;
146 indices_[i*6+2] = i*4+2;
147
148 // inverted index. issue #179
149 indices_[i*6+3] = i*4+3;
150 indices_[i*6+4] = i*4+2;
151 indices_[i*6+5] = i*4+1;
152// indices_[i*6+3] = i*4+2;
153// indices_[i*6+4] = i*4+3;
154// indices_[i*6+5] = i*4+1;
155#endif
156 }
157
158#if CC_USES_VBO
159 glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]);
160 glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * capacity_, quads_, GL_DYNAMIC_DRAW);
161 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
162 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_[0]) * capacity_ * 6, indices_, GL_STATIC_DRAW);
163 glBindBuffer(GL_ARRAY_BUFFER, 0);
164 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
165#endif // CC_USES_VBO
166}
167
168#pragma mark TextureAtlas - Update, Insert, Move & Remove
169
170-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger) n
171{
172 NSAssert(n < capacity_, @"updateQuadWithTexture: Invalid index");
173
174 totalQuads_ = MAX( n+1, totalQuads_);
175
176 quads_[n] = *quad;
177
178#if CC_USES_VBO
179 dirty_ = YES;
180#endif
181}
182
183
184-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index
185{
186 NSAssert(index < capacity_, @"insertQuadWithTexture: Invalid index");
187
188 totalQuads_++;
189 NSAssert( totalQuads_ <= capacity_, @"invalid totalQuads");
190
191 // issue #575. index can be > totalQuads
192 NSInteger remaining = (totalQuads_-1) - index;
193
194 // last object doesn't need to be moved
195 if( remaining > 0)
196 // tex coordinates
197 memmove( &quads_[index+1],&quads_[index], sizeof(quads_[0]) * remaining );
198
199 quads_[index] = *quad;
200
201#if CC_USES_VBO
202 dirty_ = YES;
203#endif
204}
205
206
207-(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex
208{
209 NSAssert(newIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
210 NSAssert(oldIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
211
212 if( oldIndex == newIndex )
213 return;
214
215 NSUInteger howMany = labs( oldIndex - newIndex);
216 NSUInteger dst = oldIndex;
217 NSUInteger src = oldIndex + 1;
218 if( oldIndex > newIndex) {
219 dst = newIndex+1;
220 src = newIndex;
221 }
222
223 // tex coordinates
224 ccV3F_C4B_T2F_Quad quadsBackup = quads_[oldIndex];
225 memmove( &quads_[dst],&quads_[src], sizeof(quads_[0]) * howMany );
226 quads_[newIndex] = quadsBackup;
227
228#if CC_USES_VBO
229 dirty_ = YES;
230#endif
231}
232
233-(void) removeQuadAtIndex:(NSUInteger) index
234{
235 NSAssert(index < totalQuads_, @"removeQuadAtIndex: Invalid index");
236
237 NSUInteger remaining = (totalQuads_-1) - index;
238
239
240 // last object doesn't need to be moved
241 if( remaining )
242 // tex coordinates
243 memmove( &quads_[index],&quads_[index+1], sizeof(quads_[0]) * remaining );
244
245 totalQuads_--;
246
247#if CC_USES_VBO
248 dirty_ = YES;
249#endif
250}
251
252-(void) removeAllQuads
253{
254 totalQuads_ = 0;
255}
256
257#pragma mark TextureAtlas - Resize
258
259-(BOOL) resizeCapacity: (NSUInteger) newCapacity
260{
261 if( newCapacity == capacity_ )
262 return YES;
263
264 // update capacity and totolQuads
265 totalQuads_ = MIN(totalQuads_,newCapacity);
266 capacity_ = newCapacity;
267
268 void * tmpQuads = realloc( quads_, sizeof(quads_[0]) * capacity_ );
269 void * tmpIndices = realloc( indices_, sizeof(indices_[0]) * capacity_ * 6 );
270
271 if( ! ( tmpQuads && tmpIndices) ) {
272 CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
273 if( tmpQuads )
274 free(tmpQuads);
275 else
276 free(quads_);
277
278 if( tmpIndices )
279 free(tmpIndices);
280 else
281 free(indices_);
282
283 indices_ = nil;
284 quads_ = nil;
285 capacity_ = totalQuads_ = 0;
286 return NO;
287 }
288
289 quads_ = tmpQuads;
290 indices_ = tmpIndices;
291
292 [self initIndices];
293
294#if CC_USES_VBO
295 dirty_ = YES;
296#endif
297 return YES;
298}
299
300#pragma mark TextureAtlas - Drawing
301
302-(void) drawQuads
303{
304 [self drawNumberOfQuads: totalQuads_ fromIndex:0];
305}
306
307-(void) drawNumberOfQuads: (NSUInteger) n
308{
309 [self drawNumberOfQuads:n fromIndex:0];
310}
311
312-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start
313{
314 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
315 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
316 // Unneeded states: -
317
318 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
319#define kQuadSize sizeof(quads_[0].bl)
320#if CC_USES_VBO
321 glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]);
322
323 // XXX: update is done in draw... perhaps it should be done in a timer
324 if (dirty_) {
325 glBufferSubData(GL_ARRAY_BUFFER, sizeof(quads_[0])*start, sizeof(quads_[0]) * n , &quads_[start] );
326 dirty_ = NO;
327 }
328
329 // vertices
330 glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
331
332 // colors
333 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
334
335 // tex coords
336 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
337
338 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
339#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
340 glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
341#else
342 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
343#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
344
345 glBindBuffer(GL_ARRAY_BUFFER, 0);
346 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
347#else // ! CC_USES_VBO
348
349 NSUInteger offset = (NSUInteger)quads_;
350 // vertex
351 NSUInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
352 glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) );
353 // color
354 diff = offsetof( ccV3F_C4B_T2F, colors);
355 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
356
357 // tex coords
358 diff = offsetof( ccV3F_C4B_T2F, texCoords);
359 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
360
361#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
362 glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 );
363#else
364 glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 );
365#endif
366
367#endif // CC_USES_VBO
368}
369@end
diff --git a/libs/cocos2d/CCTextureCache.h b/libs/cocos2d/CCTextureCache.h new file mode 100755 index 0000000..7084793 --- /dev/null +++ b/libs/cocos2d/CCTextureCache.h
@@ -0,0 +1,149 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Availability.h>
28
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30#import <CoreGraphics/CGImage.h>
31#endif
32
33#import <Foundation/Foundation.h>
34
35@class CCTexture2D;
36
37/** Singleton that handles the loading of textures
38 * Once the texture is loaded, the next time it will return
39 * a reference of the previously loaded texture reducing GPU & CPU memory
40 */
41@interface CCTextureCache : NSObject
42{
43 NSMutableDictionary *textures_;
44 NSLock *dictLock_;
45 NSLock *contextLock_;
46}
47
48/** Retruns ths shared instance of the cache */
49+ (CCTextureCache *) sharedTextureCache;
50
51/** purges the cache. It releases the retained instance.
52 @since v0.99.0
53 */
54+(void)purgeSharedTextureCache;
55
56
57/** Returns a Texture2D object given an file image
58 * If the file image was not previously loaded, it will create a new CCTexture2D
59 * object and it will return it. It will use the filename as a key.
60 * Otherwise it will return a reference of a previosly loaded image.
61 * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif
62 */
63-(CCTexture2D*) addImage: (NSString*) fileimage;
64
65/** Returns a Texture2D object given a file image
66 * If the file image was not previously loaded, it will create a new CCTexture2D object and it will return it.
67 * Otherwise it will load a texture in a new thread, and when the image is loaded, the callback will be called with the Texture2D as a parameter.
68 * The callback will be called from the main thread, so it is safe to create any cocos2d object from the callback.
69 * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif
70 * @since v0.8
71 */
72-(void) addImageAsync:(NSString*) filename target:(id)target selector:(SEL)selector;
73
74/** Returns a Texture2D object given an CGImageRef image
75 * If the image was not previously loaded, it will create a new CCTexture2D object and it will return it.
76 * Otherwise it will return a reference of a previously loaded image
77 * The "key" parameter will be used as the "key" for the cache.
78 * If "key" is nil, then a new texture will be created each time.
79 * @since v0.8
80 */
81-(CCTexture2D*) addCGImage: (CGImageRef) image forKey: (NSString *)key;
82
83/** Returns an already created texture. Returns nil if the texture doesn't exist.
84 @since v0.99.5
85 */
86-(CCTexture2D *) textureForKey:(NSString *)key;
87
88/** Purges the dictionary of loaded textures.
89 * Call this method if you receive the "Memory Warning"
90 * In the short term: it will free some resources preventing your app from being killed
91 * In the medium term: it will allocate more resources
92 * In the long term: it will be the same
93 */
94-(void) removeAllTextures;
95
96/** Removes unused textures
97 * Textures that have a retain count of 1 will be deleted
98 * It is convinient to call this method after when starting a new Scene
99 * @since v0.8
100 */
101-(void) removeUnusedTextures;
102
103/** Deletes a texture from the cache given a texture
104 */
105-(void) removeTexture: (CCTexture2D*) tex;
106
107/** Deletes a texture from the cache given a its key name
108 @since v0.99.4
109 */
110-(void) removeTextureForKey: (NSString*) textureKeyName;
111
112@end
113
114
115@interface CCTextureCache (PVRSupport)
116
117/** Returns a Texture2D object given an PVRTC RAW filename
118 * If the file image was not previously loaded, it will create a new CCTexture2D
119 * object and it will return it. Otherwise it will return a reference of a previosly loaded image
120 *
121 * It can only load square images: width == height, and it must be a power of 2 (128,256,512...)
122 * bpp can only be 2 or 4. 2 means more compression but lower quality.
123 * hasAlpha: whether or not the image contains alpha channel
124 *
125 * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
126 */
127#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
128-(CCTexture2D*) addPVRTCImage:(NSString*)fileimage bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w;
129#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
130
131/** Returns a Texture2D object given an PVR filename.
132 * If the file image was not previously loaded, it will create a new CCTexture2D
133 * object and it will return it. Otherwise it will return a reference of a previosly loaded image
134 *
135 */
136-(CCTexture2D*) addPVRImage:(NSString*) filename;
137
138@end
139
140
141@interface CCTextureCache (Debug)
142/** Output to CCLOG the current contents of this CCTextureCache
143 * This will attempt to calculate the size of each texture, and the total texture memory in use
144 *
145 * @since v1.0
146 */
147-(void) dumpCachedTextureInfo;
148
149@end
diff --git a/libs/cocos2d/CCTextureCache.m b/libs/cocos2d/CCTextureCache.m new file mode 100755 index 0000000..080770a --- /dev/null +++ b/libs/cocos2d/CCTextureCache.m
@@ -0,0 +1,498 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import <Availability.h>
28
29#import "Platforms/CCGL.h"
30#import "CCTextureCache.h"
31#import "CCTexture2D.h"
32#import "CCTexturePVR.h"
33#import "ccMacros.h"
34#import "CCConfiguration.h"
35#import "Support/CCFileUtils.h"
36#import "CCDirector.h"
37#import "ccConfig.h"
38
39// needed for CCCallFuncO in Mac-display_link version
40#import "CCActionManager.h"
41#import "CCActionInstant.h"
42
43#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
44static EAGLContext *auxGLcontext = nil;
45#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
46static NSOpenGLContext *auxGLcontext = nil;
47#endif
48
49
50@interface CCAsyncObject : NSObject
51{
52 SEL selector_;
53 id target_;
54 id data_;
55}
56@property (readwrite,assign) SEL selector;
57@property (readwrite,retain) id target;
58@property (readwrite,retain) id data;
59@end
60
61@implementation CCAsyncObject
62@synthesize selector = selector_;
63@synthesize target = target_;
64@synthesize data = data_;
65- (void) dealloc
66{
67 CCLOGINFO(@"cocos2d: deallocing %@", self);
68 [target_ release];
69 [data_ release];
70 [super dealloc];
71}
72@end
73
74
75@implementation CCTextureCache
76
77#pragma mark TextureCache - Alloc, Init & Dealloc
78static CCTextureCache *sharedTextureCache;
79
80+ (CCTextureCache *)sharedTextureCache
81{
82 if (!sharedTextureCache)
83 sharedTextureCache = [[CCTextureCache alloc] init];
84
85 return sharedTextureCache;
86}
87
88+(id)alloc
89{
90 NSAssert(sharedTextureCache == nil, @"Attempted to allocate a second instance of a singleton.");
91 return [super alloc];
92}
93
94+(void)purgeSharedTextureCache
95{
96 [sharedTextureCache release];
97 sharedTextureCache = nil;
98}
99
100-(id) init
101{
102 if( (self=[super init]) ) {
103 textures_ = [[NSMutableDictionary dictionaryWithCapacity: 10] retain];
104 dictLock_ = [[NSLock alloc] init];
105 contextLock_ = [[NSLock alloc] init];
106 }
107
108 return self;
109}
110
111- (NSString*) description
112{
113 return [NSString stringWithFormat:@"<%@ = %08X | num of textures = %i | keys: %@>",
114 [self class],
115 self,
116 [textures_ count],
117 [textures_ allKeys]
118 ];
119
120}
121
122-(void) dealloc
123{
124 CCLOGINFO(@"cocos2d: deallocing %@", self);
125
126 [textures_ release];
127 [dictLock_ release];
128 [contextLock_ release];
129 [auxGLcontext release];
130 auxGLcontext = nil;
131 sharedTextureCache = nil;
132 [super dealloc];
133}
134
135#pragma mark TextureCache - Add Images
136
137-(void) addImageWithAsyncObject:(CCAsyncObject*)async
138{
139 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
140
141#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
142 // textures will be created on the main OpenGL context
143 // it seems that in SDK 2.2.x there can't be 2 threads creating textures at the same time
144 // the lock is used for this purpose: issue #472
145 [contextLock_ lock];
146 if( auxGLcontext == nil ) {
147 auxGLcontext = [[EAGLContext alloc]
148 initWithAPI:kEAGLRenderingAPIOpenGLES1
149 sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]];
150
151 if( ! auxGLcontext )
152 CCLOG(@"cocos2d: TextureCache: Could not create EAGL context");
153 }
154
155 if( [EAGLContext setCurrentContext:auxGLcontext] ) {
156
157 // load / create the texture
158 CCTexture2D *tex = [self addImage:async.data];
159
160 // The callback will be executed on the main thread
161 [async.target performSelectorOnMainThread:async.selector withObject:tex waitUntilDone:NO];
162
163 [EAGLContext setCurrentContext:nil];
164 } else {
165 CCLOG(@"cocos2d: TetureCache: EAGLContext error");
166 }
167 [contextLock_ unlock];
168
169 [autoreleasepool release];
170
171#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
172
173 [contextLock_ lock];
174 if( auxGLcontext == nil ) {
175
176 MacGLView *view = [[CCDirector sharedDirector] openGLView];
177
178 NSOpenGLPixelFormat *pf = [view pixelFormat];
179 NSOpenGLContext *share = [view openGLContext];
180
181 auxGLcontext = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:share];
182
183 if( ! auxGLcontext )
184 CCLOG(@"cocos2d: TextureCache: Could not create NSOpenGLContext");
185 }
186
187 [auxGLcontext makeCurrentContext];
188
189 // load / create the texture
190 CCTexture2D *tex = [self addImage:async.data];
191
192#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
193 id action = [CCCallFuncO actionWithTarget:async.target selector:async.selector object:tex];
194 [[CCActionManager sharedManager] addAction:action target:async.target paused:NO];
195#else
196 // The callback will be executed on the main thread
197 [async.target performSelector:async.selector
198 onThread:[[CCDirector sharedDirector] runningThread]
199 withObject:tex
200 waitUntilDone:NO];
201#endif
202
203
204 [NSOpenGLContext clearCurrentContext];
205
206 [contextLock_ unlock];
207
208 [autoreleasepool release];
209
210#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
211}
212
213-(void) addImageAsync: (NSString*)path target:(id)target selector:(SEL)selector
214{
215 NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
216
217 // optimization
218
219 CCTexture2D * tex;
220
221 path = ccRemoveHDSuffixFromFile(path);
222
223 if( (tex=[textures_ objectForKey: path] ) ) {
224 [target performSelector:selector withObject:tex];
225 return;
226 }
227
228 // schedule the load
229
230 CCAsyncObject *asyncObject = [[CCAsyncObject alloc] init];
231 asyncObject.selector = selector;
232 asyncObject.target = target;
233 asyncObject.data = path;
234
235 [NSThread detachNewThreadSelector:@selector(addImageWithAsyncObject:) toTarget:self withObject:asyncObject];
236 [asyncObject release];
237}
238
239-(CCTexture2D*) addImage: (NSString*) path
240{
241 NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
242
243 CCTexture2D * tex = nil;
244
245 // MUTEX:
246 // Needed since addImageAsync calls this method from a different thread
247 [dictLock_ lock];
248
249 // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
250 path = ccRemoveHDSuffixFromFile( path );
251
252 tex=[textures_ objectForKey: path];
253
254 if( ! tex ) {
255
256 NSString *lowerCase = [path lowercaseString];
257 // all images are handled by UIImage except PVR extension that is handled by our own handler
258
259 if ( [lowerCase hasSuffix:@".pvr"] || [lowerCase hasSuffix:@".pvr.gz"] || [lowerCase hasSuffix:@".pvr.ccz"] )
260 tex = [self addPVRImage:path];
261
262 // Only iPhone
263#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
264
265 // Issue #886: TEMPORARY FIX FOR TRANSPARENT JPEGS IN IOS4
266 else if ( ( [[CCConfiguration sharedConfiguration] OSVersion] >= kCCiOSVersion_4_0) &&
267 ( [lowerCase hasSuffix:@".jpg"] || [lowerCase hasSuffix:@".jpeg"] )
268 ) {
269 // convert jpg to png before loading the texture
270
271 NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
272
273 UIImage *jpg = [[UIImage alloc] initWithContentsOfFile:fullpath];
274 UIImage *png = [[UIImage alloc] initWithData:UIImagePNGRepresentation(jpg)];
275 tex = [ [CCTexture2D alloc] initWithImage: png ];
276 [png release];
277 [jpg release];
278
279 if( tex )
280 [textures_ setObject: tex forKey:path];
281 else
282 CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
283
284 // autorelease prevents possible crash in multithreaded environments
285 [tex autorelease];
286 }
287
288 else {
289
290 // prevents overloading the autorelease pool
291 NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
292
293 UIImage *image = [ [UIImage alloc] initWithContentsOfFile: fullpath ];
294 tex = [ [CCTexture2D alloc] initWithImage: image ];
295 [image release];
296
297 if( tex )
298 [textures_ setObject: tex forKey:path];
299 else
300 CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
301
302 // autorelease prevents possible crash in multithreaded environments
303 [tex autorelease];
304 }
305
306 // Only in Mac
307#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
308 else {
309 NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
310
311 NSData *data = [[NSData alloc] initWithContentsOfFile:fullpath];
312 NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data];
313 tex = [ [CCTexture2D alloc] initWithImage:[image CGImage]];
314
315 [data release];
316 [image release];
317
318 if( tex )
319 [textures_ setObject: tex forKey:path];
320 else
321 CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
322
323 // autorelease prevents possible crash in multithreaded environments
324 [tex autorelease];
325 }
326#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
327
328 }
329
330 [dictLock_ unlock];
331
332 return tex;
333}
334
335
336-(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (NSString *)key
337{
338 NSAssert(imageref != nil, @"TextureCache: image MUST not be nill");
339
340 CCTexture2D * tex = nil;
341
342 // If key is nil, then create a new texture each time
343 if( key && (tex=[textures_ objectForKey: key] ) ) {
344 return tex;
345 }
346
347#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
348 // prevents overloading the autorelease pool
349 UIImage *image = [[UIImage alloc] initWithCGImage:imageref];
350 tex = [[CCTexture2D alloc] initWithImage: image];
351 [image release];
352
353#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
354 tex = [[CCTexture2D alloc] initWithImage: imageref];
355#endif
356
357 if(tex && key)
358 [textures_ setObject: tex forKey:key];
359 else
360 CCLOG(@"cocos2d: Couldn't add CGImage in CCTextureCache");
361
362 return [tex autorelease];
363}
364
365#pragma mark TextureCache - Remove
366
367-(void) removeAllTextures
368{
369 [textures_ removeAllObjects];
370}
371
372-(void) removeUnusedTextures
373{
374 NSArray *keys = [textures_ allKeys];
375 for( id key in keys ) {
376 id value = [textures_ objectForKey:key];
377 if( [value retainCount] == 1 ) {
378 CCLOG(@"cocos2d: CCTextureCache: removing unused texture: %@", key);
379 [textures_ removeObjectForKey:key];
380 }
381 }
382}
383
384-(void) removeTexture: (CCTexture2D*) tex
385{
386 if( ! tex )
387 return;
388
389 NSArray *keys = [textures_ allKeysForObject:tex];
390
391 for( NSUInteger i = 0; i < [keys count]; i++ )
392 [textures_ removeObjectForKey:[keys objectAtIndex:i]];
393}
394
395-(void) removeTextureForKey:(NSString*)name
396{
397 if( ! name )
398 return;
399
400 [textures_ removeObjectForKey:name];
401}
402
403#pragma mark TextureCache - Get
404- (CCTexture2D *)textureForKey:(NSString *)key
405{
406 return [textures_ objectForKey:key];
407}
408
409@end
410
411
412@implementation CCTextureCache (PVRSupport)
413
414#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
415-(CCTexture2D*) addPVRTCImage:(NSString*)path bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w
416{
417 NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
418 NSAssert( bpp==2 || bpp==4, @"TextureCache: bpp must be either 2 or 4");
419
420 CCTexture2D * tex;
421
422 // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
423 path = ccRemoveHDSuffixFromFile( path );
424
425 if( (tex=[textures_ objectForKey: path] ) ) {
426 return tex;
427 }
428
429 // Split up directory and filename
430 NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path];
431
432 NSData *nsdata = [[NSData alloc] initWithContentsOfFile:fullpath];
433 tex = [[CCTexture2D alloc] initWithPVRTCData:[nsdata bytes] level:0 bpp:bpp hasAlpha:alpha length:w pixelFormat:bpp==2?kCCTexture2DPixelFormat_PVRTC2:kCCTexture2DPixelFormat_PVRTC4];
434 if( tex )
435 [textures_ setObject: tex forKey:path];
436 else
437 CCLOG(@"cocos2d: Couldn't add PVRTCImage:%@ in CCTextureCache",path);
438
439 [nsdata release];
440
441 return [tex autorelease];
442}
443#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
444
445-(CCTexture2D*) addPVRImage:(NSString*)path
446{
447 NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
448
449 CCTexture2D * tex;
450
451 // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
452 path = ccRemoveHDSuffixFromFile( path );
453
454 if( (tex=[textures_ objectForKey: path] ) ) {
455 return tex;
456 }
457
458 // Split up directory and filename
459 NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path];
460
461 tex = [[CCTexture2D alloc] initWithPVRFile: fullpath];
462 if( tex )
463 [textures_ setObject: tex forKey:path];
464 else
465 CCLOG(@"cocos2d: Couldn't add PVRImage:%@ in CCTextureCache",path);
466
467 return [tex autorelease];
468}
469
470@end
471
472
473@implementation CCTextureCache (Debug)
474
475-(void) dumpCachedTextureInfo
476{
477 NSUInteger count = 0;
478 NSUInteger totalBytes = 0;
479 for (NSString* texKey in textures_) {
480 CCTexture2D* tex = [textures_ objectForKey:texKey];
481 NSUInteger bpp = [tex bitsPerPixelForFormat];
482 // Each texture takes up width * height * bytesPerPixel bytes.
483 NSUInteger bytes = tex.pixelsWide * tex.pixelsWide * bpp / 8;
484 totalBytes += bytes;
485 count++;
486 CCLOG( @"cocos2d: \"%@\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB",
487 texKey,
488 (long)[tex retainCount],
489 (long)tex.name,
490 (long)tex.pixelsWide,
491 (long)tex.pixelsHigh,
492 (long)bpp,
493 (long)bytes / 1024 );
494 }
495 CCLOG( @"cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f));
496}
497
498@end
diff --git a/libs/cocos2d/CCTexturePVR.h b/libs/cocos2d/CCTexturePVR.h new file mode 100755 index 0000000..66f8286 --- /dev/null +++ b/libs/cocos2d/CCTexturePVR.h
@@ -0,0 +1,127 @@
1/*
2
3File: PVRTexture.h
4Abstract: The PVRTexture class is responsible for loading .pvr files.
5
6Version: 1.0
7
8Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
9("Apple") in consideration of your agreement to the following terms, and your
10use, installation, modification or redistribution of this Apple software
11constitutes acceptance of these terms. If you do not agree with these terms,
12please do not use, install, modify or redistribute this Apple software.
13
14In consideration of your agreement to abide by the following terms, and subject
15to these terms, Apple grants you a personal, non-exclusive license, under
16Apple's copyrights in this original Apple software (the "Apple Software"), to
17use, reproduce, modify and redistribute the Apple Software, with or without
18modifications, in source and/or binary forms; provided that if you redistribute
19the Apple Software in its entirety and without modifications, you must retain
20this notice and the following text and disclaimers in all such redistributions
21of the Apple Software.
22Neither the name, trademarks, service marks or logos of Apple Inc. may be used
23to endorse or promote products derived from the Apple Software without specific
24prior written permission from Apple. Except as expressly stated in this notice,
25no other rights or licenses, express or implied, are granted by Apple herein,
26including but not limited to any patent rights that may be infringed by your
27derivative works or by other works in which the Apple Software may be
28incorporated.
29
30The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
31WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
32WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
34COMBINATION WITH YOUR PRODUCTS.
35
36IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
37CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
40DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
41CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
44Copyright (C) 2008 Apple Inc. All Rights Reserved.
45
46*/
47
48#import <Foundation/Foundation.h>
49
50#import "Platforms/CCGL.h"
51#import "CCTexture2D.h"
52
53
54#pragma mark -
55#pragma mark CCTexturePVR
56
57struct CCPVRMipmap {
58 unsigned char *address;
59 unsigned int len;
60};
61
62enum {
63 CC_PVRMIPMAP_MAX = 16,
64};
65
66/** CCTexturePVR
67
68 Object that loads PVR images.
69
70 Supported PVR formats:
71 - RGBA8888
72 - BGRA8888
73 - RGBA4444
74 - RGBA5551
75 - RGB565
76 - A8
77 - I8
78 - AI88
79 - PVRTC 4BPP
80 - PVRTC 2BPP
81
82 Limitations:
83 Pre-generated mipmaps, such as PVR textures with mipmap levels embedded in file,
84 are only supported if all individual sprites are of _square_ size.
85 To use mipmaps with non-square textures, instead call CCTexture2D#generateMipmap on the sheet texture itself
86 (and to save space, save the PVR sprite sheet without mip maps included).
87 */
88@interface CCTexturePVR : NSObject
89{
90 struct CCPVRMipmap mipmaps_[CC_PVRMIPMAP_MAX]; // pointer to mipmap images
91 int numberOfMipmaps_; // number of mipmap used
92
93 unsigned int tableFormatIndex_;
94 uint32_t width_, height_;
95 GLuint name_;
96 BOOL hasAlpha_;
97
98 // cocos2d integration
99 BOOL retainName_;
100 CCTexture2DPixelFormat format_;
101}
102
103/** initializes a CCTexturePVR with a path */
104- (id)initWithContentsOfFile:(NSString *)path;
105/** initializes a CCTexturePVR with an URL */
106- (id)initWithContentsOfURL:(NSURL *)url;
107/** creates and initializes a CCTexturePVR with a path */
108+ (id)pvrTextureWithContentsOfFile:(NSString *)path;
109/** creates and initializes a CCTexturePVR with an URL */
110+ (id)pvrTextureWithContentsOfURL:(NSURL *)url;
111
112/** texture id name */
113@property (nonatomic,readonly) GLuint name;
114/** texture width */
115@property (nonatomic,readonly) uint32_t width;
116/** texture height */
117@property (nonatomic,readonly) uint32_t height;
118/** whether or not the texture has alpha */
119@property (nonatomic,readonly) BOOL hasAlpha;
120
121// cocos2d integration
122@property (nonatomic,readwrite) BOOL retainName;
123@property (nonatomic,readonly) CCTexture2DPixelFormat format;
124
125@end
126
127
diff --git a/libs/cocos2d/CCTexturePVR.m b/libs/cocos2d/CCTexturePVR.m new file mode 100755 index 0000000..692d5f9 --- /dev/null +++ b/libs/cocos2d/CCTexturePVR.m
@@ -0,0 +1,428 @@
1/*
2
3File: PVRTexture.m
4Abstract: The PVRTexture class is responsible for loading .pvr files.
5
6Version: 1.0
7
8Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
9("Apple") in consideration of your agreement to the following terms, and your
10use, installation, modification or redistribution of this Apple software
11constitutes acceptance of these terms. If you do not agree with these terms,
12please do not use, install, modify or redistribute this Apple software.
13
14In consideration of your agreement to abide by the following terms, and subject
15to these terms, Apple grants you a personal, non-exclusive license, under
16Apple's copyrights in this original Apple software (the "Apple Software"), to
17use, reproduce, modify and redistribute the Apple Software, with or without
18modifications, in source and/or binary forms; provided that if you redistribute
19the Apple Software in its entirety and without modifications, you must retain
20this notice and the following text and disclaimers in all such redistributions
21of the Apple Software.
22Neither the name, trademarks, service marks or logos of Apple Inc. may be used
23to endorse or promote products derived from the Apple Software without specific
24prior written permission from Apple. Except as expressly stated in this notice,
25no other rights or licenses, express or implied, are granted by Apple herein,
26including but not limited to any patent rights that may be infringed by your
27derivative works or by other works in which the Apple Software may be
28incorporated.
29
30The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
31WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
32WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
34COMBINATION WITH YOUR PRODUCTS.
35
36IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
37CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
40DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
41CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
44Copyright (C) 2008 Apple Inc. All Rights Reserved.
45
46*/
47
48/*
49 * Extended PVR formats for cocos2d project ( http://www.cocos2d-iphone.org )
50 * - RGBA8888
51 * - BGRA8888
52 * - RGBA4444
53 * - RGBA5551
54 * - RGB565
55 * - A8
56 * - I8
57 * - AI88
58 */
59
60#import <Availability.h>
61
62#import <zlib.h>
63
64#import "CCTexturePVR.h"
65#import "ccMacros.h"
66#import "CCConfiguration.h"
67#import "Support/ccUtils.h"
68#import "Support/CCFileUtils.h"
69#import "Support/ZipUtils.h"
70#import "Support/OpenGL_Internal.h"
71
72#pragma mark -
73#pragma mark CCTexturePVR
74
75#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff
76
77// Values taken from PVRTexture.h from http://www.imgtec.com
78enum {
79 kPVRTextureFlagMipmap = (1<<8), // has mip map levels
80 kPVRTextureFlagTwiddle = (1<<9), // is twiddled
81 kPVRTextureFlagBumpmap = (1<<10), // has normals encoded for a bump map
82 kPVRTextureFlagTiling = (1<<11), // is bordered for tiled pvr
83 kPVRTextureFlagCubemap = (1<<12), // is a cubemap/skybox
84 kPVRTextureFlagFalseMipCol = (1<<13), // are there false coloured MIP levels
85 kPVRTextureFlagVolume = (1<<14), // is this a volume texture
86 kPVRTextureFlagAlpha = (1<<15), // v2.1 is there transparency info in the texture
87 kPVRTextureFlagVerticalFlip = (1<<16), // v2.1 is the texture vertically flipped
88};
89
90
91static char gPVRTexIdentifier[4] = "PVR!";
92
93enum
94{
95 kPVRTexturePixelTypeRGBA_4444= 0x10,
96 kPVRTexturePixelTypeRGBA_5551,
97 kPVRTexturePixelTypeRGBA_8888,
98 kPVRTexturePixelTypeRGB_565,
99 kPVRTexturePixelTypeRGB_555, // unsupported
100 kPVRTexturePixelTypeRGB_888, // unsupported
101 kPVRTexturePixelTypeI_8,
102 kPVRTexturePixelTypeAI_88,
103 kPVRTexturePixelTypePVRTC_2,
104 kPVRTexturePixelTypePVRTC_4,
105 kPVRTexturePixelTypeBGRA_8888,
106 kPVRTexturePixelTypeA_8,
107};
108
109static const uint32_t tableFormats[][7] = {
110
111 // - PVR texture format
112 // - OpenGL internal format
113 // - OpenGL format
114 // - OpenGL type
115 // - bpp
116 // - compressed
117 // - Cocos2d texture format constant
118 { kPVRTexturePixelTypeRGBA_4444, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, NO, kCCTexture2DPixelFormat_RGBA4444 },
119 { kPVRTexturePixelTypeRGBA_5551, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, NO, kCCTexture2DPixelFormat_RGB5A1 },
120 { kPVRTexturePixelTypeRGBA_8888, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, NO, kCCTexture2DPixelFormat_RGBA8888 },
121 { kPVRTexturePixelTypeRGB_565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, NO, kCCTexture2DPixelFormat_RGB565 },
122 { kPVRTexturePixelTypeA_8, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, NO, kCCTexture2DPixelFormat_A8 },
123 { kPVRTexturePixelTypeI_8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, NO, kCCTexture2DPixelFormat_I8 },
124 { kPVRTexturePixelTypeAI_88, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, NO, kCCTexture2DPixelFormat_AI88 },
125#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
126 { kPVRTexturePixelTypePVRTC_2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, YES, kCCTexture2DPixelFormat_PVRTC2 },
127 { kPVRTexturePixelTypePVRTC_4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, YES, kCCTexture2DPixelFormat_PVRTC4 },
128#endif // iphone only
129 { kPVRTexturePixelTypeBGRA_8888, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, NO, kCCTexture2DPixelFormat_RGBA8888 },
130};
131#define MAX_TABLE_ELEMENTS (sizeof(tableFormats) / sizeof(tableFormats[0]))
132
133enum {
134 kCCInternalPVRTextureFormat,
135 kCCInternalOpenGLInternalFormat,
136 kCCInternalOpenGLFormat,
137 kCCInternalOpenGLType,
138 kCCInternalBPP,
139 kCCInternalCompressedImage,
140 kCCInternalCCTexture2DPixelFormat,
141};
142
143typedef struct _PVRTexHeader
144{
145 uint32_t headerLength;
146 uint32_t height;
147 uint32_t width;
148 uint32_t numMipmaps;
149 uint32_t flags;
150 uint32_t dataLength;
151 uint32_t bpp;
152 uint32_t bitmaskRed;
153 uint32_t bitmaskGreen;
154 uint32_t bitmaskBlue;
155 uint32_t bitmaskAlpha;
156 uint32_t pvrTag;
157 uint32_t numSurfs;
158} PVRTexHeader;
159
160
161@implementation CCTexturePVR
162
163@synthesize name = name_;
164@synthesize width = width_;
165@synthesize height = height_;
166@synthesize hasAlpha = hasAlpha_;
167
168// cocos2d integration
169@synthesize retainName = retainName_;
170@synthesize format = format_;
171
172
173- (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(NSUInteger)len
174{
175 BOOL success = FALSE;
176 PVRTexHeader *header = NULL;
177 uint32_t flags, pvrTag;
178 uint32_t dataLength = 0, dataOffset = 0, dataSize = 0;
179 uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
180 uint32_t width = 0, height = 0, bpp = 4;
181 uint8_t *bytes = NULL;
182 uint32_t formatFlags;
183
184 header = (PVRTexHeader *)data;
185
186 pvrTag = CFSwapInt32LittleToHost(header->pvrTag);
187
188 if ((uint32_t)gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) ||
189 (uint32_t)gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) ||
190 (uint32_t)gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) ||
191 (uint32_t)gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff))
192 {
193 return FALSE;
194 }
195
196 CCConfiguration *configuration = [CCConfiguration sharedConfiguration];
197
198 flags = CFSwapInt32LittleToHost(header->flags);
199 formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK;
200 BOOL flipped = flags & kPVRTextureFlagVerticalFlip;
201 if( flipped )
202 CCLOG(@"cocos2d: WARNING: Image is flipped. Regenerate it using PVRTexTool");
203
204 if( ! [configuration supportsNPOT] &&
205 ( header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height ) ) ) {
206 CCLOG(@"cocos2d: ERROR: Loding an NPOT texture (%dx%d) but is not supported on this device", header->width, header->height);
207 return FALSE;
208 }
209
210 for( tableFormatIndex_=0; tableFormatIndex_ < (unsigned int)MAX_TABLE_ELEMENTS ; tableFormatIndex_++) {
211 if( tableFormats[tableFormatIndex_][kCCInternalPVRTextureFormat] == formatFlags ) {
212
213 numberOfMipmaps_ = 0;
214
215 width_ = width = CFSwapInt32LittleToHost(header->width);
216 height_ = height = CFSwapInt32LittleToHost(header->height);
217
218 if (CFSwapInt32LittleToHost(header->bitmaskAlpha))
219 hasAlpha_ = TRUE;
220 else
221 hasAlpha_ = FALSE;
222
223 dataLength = CFSwapInt32LittleToHost(header->dataLength);
224 bytes = ((uint8_t *)data) + sizeof(PVRTexHeader);
225 format_ = tableFormats[tableFormatIndex_][kCCInternalCCTexture2DPixelFormat];
226 bpp = tableFormats[tableFormatIndex_][kCCInternalBPP];
227
228 // Calculate the data size for each texture level and respect the minimum number of blocks
229 while (dataOffset < dataLength)
230 {
231 switch (formatFlags) {
232 case kPVRTexturePixelTypePVRTC_2:
233 blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
234 widthBlocks = width / 8;
235 heightBlocks = height / 4;
236 break;
237 case kPVRTexturePixelTypePVRTC_4:
238 blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
239 widthBlocks = width / 4;
240 heightBlocks = height / 4;
241 break;
242 case kPVRTexturePixelTypeBGRA_8888:
243 if( ! [[CCConfiguration sharedConfiguration] supportsBGRA8888] ) {
244 CCLOG(@"cocos2d: TexturePVR. BGRA8888 not supported on this device");
245 return FALSE;
246 }
247 default:
248 blockSize = 1;
249 widthBlocks = width;
250 heightBlocks = height;
251 break;
252 }
253
254 // Clamp to minimum number of blocks
255 if (widthBlocks < 2)
256 widthBlocks = 2;
257 if (heightBlocks < 2)
258 heightBlocks = 2;
259
260 dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
261 float packetLength = (dataLength-dataOffset);
262 packetLength = packetLength > dataSize ? dataSize : packetLength;
263
264 mipmaps_[numberOfMipmaps_].address = bytes+dataOffset;
265 mipmaps_[numberOfMipmaps_].len = packetLength;
266 numberOfMipmaps_++;
267
268 NSAssert( numberOfMipmaps_ < CC_PVRMIPMAP_MAX, @"TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value");
269
270 dataOffset += packetLength;
271
272 width = MAX(width >> 1, 1);
273 height = MAX(height >> 1, 1);
274 }
275
276 success = TRUE;
277 break;
278 }
279 }
280
281 if( ! success )
282 CCLOG(@"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%2x. Re-encode it with a OpenGL pixel format variant", formatFlags);
283
284 return success;
285}
286
287
288- (BOOL)createGLTexture
289{
290 GLsizei width = width_;
291 GLsizei height = height_;
292 GLenum err;
293
294 if (numberOfMipmaps_ > 0)
295 {
296 if (name_ != 0)
297 glDeleteTextures(1, &name_);
298
299 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
300 glGenTextures(1, &name_);
301 glBindTexture(GL_TEXTURE_2D, name_);
302 }
303
304 CHECK_GL_ERROR(); // clean possible GL error
305
306 // Generate textures with mipmaps
307 for (GLint i=0; i < numberOfMipmaps_; i++)
308 {
309 GLenum internalFormat = tableFormats[tableFormatIndex_][kCCInternalOpenGLInternalFormat];
310 GLenum format = tableFormats[tableFormatIndex_][kCCInternalOpenGLFormat];
311 GLenum type = tableFormats[tableFormatIndex_][kCCInternalOpenGLType];
312 BOOL compressed = tableFormats[tableFormatIndex_][kCCInternalCompressedImage];
313
314 if( compressed && ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) {
315 CCLOG(@"cocos2d: WARNING: PVRTC images are not supported");
316 return FALSE;
317 }
318
319 unsigned char *data = mipmaps_[i].address;
320 unsigned int datalen = mipmaps_[i].len;
321
322 if( compressed)
323 glCompressedTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, datalen, data);
324 else
325 glTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, format, type, data);
326
327 if( i > 0 && (width != height || ccNextPOT(width) != width ) )
328 CCLOG(@"cocos2d: TexturePVR. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%u != height=%u", i, width, height);
329
330 err = glGetError();
331 if (err != GL_NO_ERROR)
332 {
333 CCLOG(@"cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", i, err);
334 return FALSE;
335 }
336
337 width = MAX(width >> 1, 1);
338 height = MAX(height >> 1, 1);
339 }
340
341 return TRUE;
342}
343
344
345- (id)initWithContentsOfFile:(NSString *)path
346{
347 if((self = [super init]))
348 {
349 unsigned char *pvrdata = NULL;
350 NSInteger pvrlen = 0;
351 NSString *lowerCase = [path lowercaseString];
352
353 if ( [lowerCase hasSuffix:@".ccz"])
354 pvrlen = ccInflateCCZFile( [path UTF8String], &pvrdata );
355
356 else if( [lowerCase hasSuffix:@".gz"] )
357 pvrlen = ccInflateGZipFile( [path UTF8String], &pvrdata );
358
359 else
360 pvrlen = ccLoadFileIntoMemory( [path UTF8String], &pvrdata );
361
362 if( pvrlen < 0 ) {
363 [self release];
364 return nil;
365 }
366
367
368 numberOfMipmaps_ = 0;
369
370 name_ = 0;
371 width_ = height_ = 0;
372 tableFormatIndex_ = -1;
373 hasAlpha_ = FALSE;
374
375 retainName_ = NO; // cocos2d integration
376
377 if( ! [self unpackPVRData:pvrdata PVRLen:pvrlen] || ![self createGLTexture] ) {
378 free(pvrdata);
379 [self release];
380 return nil;
381 }
382
383 free(pvrdata);
384 }
385
386 return self;
387}
388
389- (id)initWithContentsOfURL:(NSURL *)url
390{
391 if (![url isFileURL])
392 {
393 CCLOG(@"cocos2d: CCPVRTexture: Only files are supported");
394 [self release];
395 return nil;
396 }
397
398 return [self initWithContentsOfFile:[url path]];
399}
400
401
402+ (id)pvrTextureWithContentsOfFile:(NSString *)path
403{
404 return [[[self alloc] initWithContentsOfFile:path] autorelease];
405}
406
407
408+ (id)pvrTextureWithContentsOfURL:(NSURL *)url
409{
410 if (![url isFileURL])
411 return nil;
412
413 return [CCTexturePVR pvrTextureWithContentsOfFile:[url path]];
414}
415
416
417- (void)dealloc
418{
419 CCLOGINFO( @"cocos2d: deallocing %@", self);
420
421 if (name_ != 0 && ! retainName_ )
422 glDeleteTextures(1, &name_);
423
424 [super dealloc];
425}
426
427@end
428
diff --git a/libs/cocos2d/CCTileMapAtlas.h b/libs/cocos2d/CCTileMapAtlas.h new file mode 100755 index 0000000..102ae46 --- /dev/null +++ b/libs/cocos2d/CCTileMapAtlas.h
@@ -0,0 +1,83 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "CCTextureAtlas.h"
28#import "CCAtlasNode.h"
29#import "Support/TGAlib.h"
30
31/** CCTileMapAtlas is a subclass of CCAtlasNode.
32
33 It knows how to render a map based of tiles.
34 The tiles must be in a .PNG format while the map must be a .TGA file.
35
36 For more information regarding the format, please see this post:
37 http://www.cocos2d-iphone.org/archives/27
38
39 All features from CCAtlasNode are valid in CCTileMapAtlas
40
41 IMPORTANT:
42 This class is deprecated. It is maintained for compatibility reasons only.
43 You SHOULD not use this class.
44 Instead, use the newer TMX file format: CCTMXTiledMap
45 */
46@interface CCTileMapAtlas : CCAtlasNode
47{
48
49 /// info about the map file
50 tImageTGA *tgaInfo;
51
52 /// x,y to altas dicctionary
53 NSMutableDictionary *posToAtlasIndex;
54
55 /// numbers of tiles to render
56 int itemsToRender;
57}
58
59/** TileMap info */
60@property (nonatomic,readonly) tImageTGA *tgaInfo;
61
62/** creates a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
63 The tile file will be loaded using the TextureMgr.
64 */
65+(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h;
66
67/** initializes a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
68 The file will be loaded using the TextureMgr.
69 */
70-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h;
71
72/** returns a tile from position x,y.
73 For the moment only channel R is used
74 */
75-(ccColor3B) tileAt: (ccGridSize) position;
76
77/** sets a tile at position x,y.
78 For the moment only channel R is used
79 */
80-(void) setTile:(ccColor3B)tile at:(ccGridSize)position;
81/** dealloc the map from memory */
82-(void) releaseMap;
83@end
diff --git a/libs/cocos2d/CCTileMapAtlas.m b/libs/cocos2d/CCTileMapAtlas.m new file mode 100755 index 0000000..aef6fe0 --- /dev/null +++ b/libs/cocos2d/CCTileMapAtlas.m
@@ -0,0 +1,234 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27#import "ccConfig.h"
28#import "CCTileMapAtlas.h"
29#import "ccMacros.h"
30#import "Support/CCFileUtils.h"
31
32@interface CCTileMapAtlas (Private)
33-(void) loadTGAfile:(NSString*)file;
34-(void) calculateItemsToRender;
35-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx;
36@end
37
38
39@implementation CCTileMapAtlas
40
41@synthesize tgaInfo;
42
43#pragma mark CCTileMapAtlas - Creation & Init
44+(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h
45{
46 return [[[self alloc] initWithTileFile:tile mapFile:map tileWidth:w tileHeight:h] autorelease];
47}
48
49
50-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h
51{
52 [self loadTGAfile: map];
53 [self calculateItemsToRender];
54
55 if( (self=[super initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender: itemsToRender]) ) {
56
57 posToAtlasIndex = [[NSMutableDictionary dictionaryWithCapacity:itemsToRender] retain];
58
59 [self updateAtlasValues];
60
61 [self setContentSize: CGSizeMake(tgaInfo->width*itemWidth_, tgaInfo->height*itemHeight_)];
62 }
63
64 return self;
65}
66
67-(void) dealloc
68{
69 if( tgaInfo )
70 tgaDestroy(tgaInfo);
71
72 [posToAtlasIndex release];
73
74 [super dealloc];
75}
76
77-(void) releaseMap
78{
79 if( tgaInfo )
80 tgaDestroy(tgaInfo);
81
82 tgaInfo = nil;
83
84 [posToAtlasIndex release];
85 posToAtlasIndex = nil;
86}
87
88-(void) calculateItemsToRender
89{
90 NSAssert( tgaInfo != nil, @"tgaInfo must be non-nil");
91
92 itemsToRender = 0;
93 for(int x = 0;x < tgaInfo->width; x++ ) {
94 for(int y = 0; y < tgaInfo->height; y++ ) {
95 ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
96 ccColor3B value = ptr[x + y * tgaInfo->width];
97 if( value.r )
98 itemsToRender++;
99 }
100 }
101}
102
103-(void) loadTGAfile:(NSString*)file
104{
105 NSAssert( file != nil, @"file must be non-nil");
106
107 NSString *path = [CCFileUtils fullPathFromRelativePath:file ];
108
109// //Find the path of the file
110// NSBundle *mainBndl = [CCDirector sharedDirector].loadingBundle;
111// NSString *resourcePath = [mainBndl resourcePath];
112// NSString * path = [resourcePath stringByAppendingPathComponent:file];
113
114 tgaInfo = tgaLoad( [path UTF8String] );
115#if 1
116 if( tgaInfo->status != TGA_OK )
117 [NSException raise:@"TileMapAtlasLoadTGA" format:@"TileMapAtas cannot load TGA file"];
118
119#endif
120}
121
122#pragma mark CCTileMapAtlas - Atlas generation / updates
123
124-(void) setTile:(ccColor3B) tile at:(ccGridSize) pos
125{
126 NSAssert( tgaInfo != nil, @"tgaInfo must not be nil");
127 NSAssert( posToAtlasIndex != nil, @"posToAtlasIndex must not be nil");
128 NSAssert( pos.x < tgaInfo->width, @"Invalid position.x");
129 NSAssert( pos.y < tgaInfo->height, @"Invalid position.x");
130 NSAssert( tile.r != 0, @"R component must be non 0");
131
132 ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
133 ccColor3B value = ptr[pos.x + pos.y * tgaInfo->width];
134 if( value.r == 0 )
135 CCLOG(@"cocos2d: Value.r must be non 0.");
136 else {
137 ptr[pos.x + pos.y * tgaInfo->width] = tile;
138
139 // XXX: this method consumes a lot of memory
140 // XXX: a tree of something like that shall be impolemented
141 NSNumber *num = [posToAtlasIndex objectForKey: [NSString stringWithFormat:@"%d,%d", pos.x, pos.y]];
142 [self updateAtlasValueAt:pos withValue:tile withIndex: [num integerValue]];
143 }
144}
145
146-(ccColor3B) tileAt:(ccGridSize) pos
147{
148 NSAssert( tgaInfo != nil, @"tgaInfo must not be nil");
149 NSAssert( pos.x < tgaInfo->width, @"Invalid position.x");
150 NSAssert( pos.y < tgaInfo->height, @"Invalid position.y");
151
152 ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
153 ccColor3B value = ptr[pos.x + pos.y * tgaInfo->width];
154
155 return value;
156}
157
158-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx
159{
160 ccV3F_C4B_T2F_Quad quad;
161
162 NSInteger x = pos.x;
163 NSInteger y = pos.y;
164 float row = (value.r % itemsPerRow_);
165 float col = (value.r / itemsPerRow_);
166
167 float textureWide = [[textureAtlas_ texture] pixelsWide];
168 float textureHigh = [[textureAtlas_ texture] pixelsHigh];
169
170#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
171 float left = (2*row*itemWidth_+1)/(2*textureWide);
172 float right = left+(itemWidth_*2-2)/(2*textureWide);
173 float top = (2*col*itemHeight_+1)/(2*textureHigh);
174 float bottom = top+(itemHeight_*2-2)/(2*textureHigh);
175#else
176 float left = (row*itemWidth_)/textureWide;
177 float right = left+itemWidth_/textureWide;
178 float top = (col*itemHeight_)/textureHigh;
179 float bottom = top+itemHeight_/textureHigh;
180#endif
181
182
183 quad.tl.texCoords.u = left;
184 quad.tl.texCoords.v = top;
185 quad.tr.texCoords.u = right;
186 quad.tr.texCoords.v = top;
187 quad.bl.texCoords.u = left;
188 quad.bl.texCoords.v = bottom;
189 quad.br.texCoords.u = right;
190 quad.br.texCoords.v = bottom;
191
192 quad.bl.vertices.x = (int) (x * itemWidth_);
193 quad.bl.vertices.y = (int) (y * itemHeight_);
194 quad.bl.vertices.z = 0.0f;
195 quad.br.vertices.x = (int)(x * itemWidth_ + itemWidth_);
196 quad.br.vertices.y = (int)(y * itemHeight_);
197 quad.br.vertices.z = 0.0f;
198 quad.tl.vertices.x = (int)(x * itemWidth_);
199 quad.tl.vertices.y = (int)(y * itemHeight_ + itemHeight_);
200 quad.tl.vertices.z = 0.0f;
201 quad.tr.vertices.x = (int)(x * itemWidth_ + itemWidth_);
202 quad.tr.vertices.y = (int)(y * itemHeight_ + itemHeight_);
203 quad.tr.vertices.z = 0.0f;
204
205 [textureAtlas_ updateQuad:&quad atIndex:idx];
206}
207
208-(void) updateAtlasValues
209{
210 NSAssert( tgaInfo != nil, @"tgaInfo must be non-nil");
211
212
213 int total = 0;
214
215 for(int x = 0;x < tgaInfo->width; x++ ) {
216 for(int y = 0; y < tgaInfo->height; y++ ) {
217 if( total < itemsToRender ) {
218 ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
219 ccColor3B value = ptr[x + y * tgaInfo->width];
220
221 if( value.r != 0 ) {
222 [self updateAtlasValueAt:ccg(x,y) withValue:value withIndex:total];
223
224 NSString *key = [NSString stringWithFormat:@"%d,%d", x,y];
225 NSNumber *num = [NSNumber numberWithInt:total];
226 [posToAtlasIndex setObject:num forKey:key];
227
228 total++;
229 }
230 }
231 }
232 }
233}
234@end
diff --git a/libs/cocos2d/CCTransition.h b/libs/cocos2d/CCTransition.h new file mode 100755 index 0000000..e37d3e8 --- /dev/null +++ b/libs/cocos2d/CCTransition.h
@@ -0,0 +1,296 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCScene.h"
29@class CCActionInterval;
30@class CCNode;
31
32/** CCTransitionEaseScene can ease the actions of the scene protocol.
33 @since v0.8.2
34 */
35@protocol CCTransitionEaseScene <NSObject>
36/** returns the Ease action that will be performed on a linear action.
37 @since v0.8.2
38 */
39-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action;
40@end
41
42/** Orientation Type used by some transitions
43 */
44typedef enum {
45 /// An horizontal orientation where the Left is nearer
46 kOrientationLeftOver = 0,
47 /// An horizontal orientation where the Right is nearer
48 kOrientationRightOver = 1,
49 /// A vertical orientation where the Up is nearer
50 kOrientationUpOver = 0,
51 /// A vertical orientation where the Bottom is nearer
52 kOrientationDownOver = 1,
53} tOrientation;
54
55/** Base class for CCTransition scenes
56 */
57@interface CCTransitionScene : CCScene
58{
59 CCScene *inScene_;
60 CCScene *outScene_;
61 ccTime duration_;
62 BOOL inSceneOnTop_;
63 BOOL sendCleanupToScene_;
64}
65/** creates a base transition with duration and incoming scene */
66+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s;
67/** initializes a transition with duration and incoming scene */
68-(id) initWithDuration:(ccTime) t scene:(CCScene*)s;
69/** called after the transition finishes */
70-(void) finish;
71/** used by some transitions to hide the outter scene */
72-(void) hideOutShowIn;
73@end
74
75/** A CCTransition that supports orientation like.
76 * Possible orientation: LeftOver, RightOver, UpOver, DownOver
77 */
78@interface CCTransitionSceneOriented : CCTransitionScene
79{
80 tOrientation orientation;
81}
82/** creates a base transition with duration and incoming scene */
83+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o;
84/** initializes a transition with duration and incoming scene */
85-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o;
86@end
87
88
89/** CCTransitionRotoZoom:
90 Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming
91 */
92@interface CCTransitionRotoZoom : CCTransitionScene
93{}
94@end
95
96/** CCTransitionJumpZoom:
97 Zoom out and jump the outgoing scene, and then jump and zoom in the incoming
98*/
99@interface CCTransitionJumpZoom : CCTransitionScene
100{}
101@end
102
103/** CCTransitionMoveInL:
104 Move in from to the left the incoming scene.
105*/
106@interface CCTransitionMoveInL : CCTransitionScene <CCTransitionEaseScene>
107{}
108/** initializes the scenes */
109-(void) initScenes;
110/** returns the action that will be performed */
111-(CCActionInterval*) action;
112@end
113
114/** CCTransitionMoveInR:
115 Move in from to the right the incoming scene.
116 */
117@interface CCTransitionMoveInR : CCTransitionMoveInL
118{}
119@end
120
121/** CCTransitionMoveInT:
122 Move in from to the top the incoming scene.
123 */
124@interface CCTransitionMoveInT : CCTransitionMoveInL
125{}
126@end
127
128/** CCTransitionMoveInB:
129 Move in from to the bottom the incoming scene.
130 */
131@interface CCTransitionMoveInB : CCTransitionMoveInL
132{}
133@end
134
135/** CCTransitionSlideInL:
136 Slide in the incoming scene from the left border.
137 */
138@interface CCTransitionSlideInL : CCTransitionScene <CCTransitionEaseScene>
139{}
140/** initializes the scenes */
141-(void) initScenes;
142/** returns the action that will be performed by the incomming and outgoing scene */
143-(CCActionInterval*) action;
144@end
145
146/** CCTransitionSlideInR:
147 Slide in the incoming scene from the right border.
148 */
149@interface CCTransitionSlideInR : CCTransitionSlideInL
150{}
151@end
152
153/** CCTransitionSlideInB:
154 Slide in the incoming scene from the bottom border.
155 */
156@interface CCTransitionSlideInB : CCTransitionSlideInL
157{}
158@end
159
160/** CCTransitionSlideInT:
161 Slide in the incoming scene from the top border.
162 */
163@interface CCTransitionSlideInT : CCTransitionSlideInL
164{}
165@end
166
167/**
168 Shrink the outgoing scene while grow the incoming scene
169 */
170@interface CCTransitionShrinkGrow : CCTransitionScene <CCTransitionEaseScene>
171{}
172@end
173
174/** CCTransitionFlipX:
175 Flips the screen horizontally.
176 The front face is the outgoing scene and the back face is the incoming scene.
177 */
178@interface CCTransitionFlipX : CCTransitionSceneOriented
179{}
180@end
181
182/** CCTransitionFlipY:
183 Flips the screen vertically.
184 The front face is the outgoing scene and the back face is the incoming scene.
185 */
186@interface CCTransitionFlipY : CCTransitionSceneOriented
187{}
188@end
189
190/** CCTransitionFlipAngular:
191 Flips the screen half horizontally and half vertically.
192 The front face is the outgoing scene and the back face is the incoming scene.
193 */
194@interface CCTransitionFlipAngular : CCTransitionSceneOriented
195{}
196@end
197
198/** CCTransitionZoomFlipX:
199 Flips the screen horizontally doing a zoom out/in
200 The front face is the outgoing scene and the back face is the incoming scene.
201 */
202@interface CCTransitionZoomFlipX : CCTransitionSceneOriented
203{}
204@end
205
206/** CCTransitionZoomFlipY:
207 Flips the screen vertically doing a little zooming out/in
208 The front face is the outgoing scene and the back face is the incoming scene.
209 */
210@interface CCTransitionZoomFlipY : CCTransitionSceneOriented
211{}
212@end
213
214/** CCTransitionZoomFlipAngular:
215 Flips the screen half horizontally and half vertically doing a little zooming out/in.
216 The front face is the outgoing scene and the back face is the incoming scene.
217 */
218@interface CCTransitionZoomFlipAngular : CCTransitionSceneOriented
219{}
220@end
221
222/** CCTransitionFade:
223 Fade out the outgoing scene and then fade in the incoming scene.'''
224 */
225@interface CCTransitionFade : CCTransitionScene
226{
227 ccColor4B color;
228}
229/** creates the transition with a duration and with an RGB color
230 * Example: [FadeTransition transitionWithDuration:2 scene:s withColor:ccc3(255,0,0)]; // red color
231 */
232+(id) transitionWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color;
233/** initializes the transition with a duration and with an RGB color */
234-(id) initWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color;
235@end
236
237
238/**
239 CCTransitionCrossFade:
240 Cross fades two scenes using the CCRenderTexture object.
241 */
242@class CCRenderTexture;
243@interface CCTransitionCrossFade : CCTransitionScene
244{}
245@end
246
247/** CCTransitionTurnOffTiles:
248 Turn off the tiles of the outgoing scene in random order
249 */
250@interface CCTransitionTurnOffTiles : CCTransitionScene <CCTransitionEaseScene>
251{}
252@end
253
254/** CCTransitionSplitCols:
255 The odd columns goes upwards while the even columns goes downwards.
256 */
257@interface CCTransitionSplitCols : CCTransitionScene <CCTransitionEaseScene>
258{}
259-(CCActionInterval*) action;
260@end
261
262/** CCTransitionSplitRows:
263 The odd rows goes to the left while the even rows goes to the right.
264 */
265@interface CCTransitionSplitRows : CCTransitionSplitCols
266{}
267@end
268
269/** CCTransitionFadeTR:
270 Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
271 */
272@interface CCTransitionFadeTR : CCTransitionScene <CCTransitionEaseScene>
273{}
274-(CCActionInterval*) actionWithSize:(ccGridSize) vector;
275@end
276
277/** CCTransitionFadeBL:
278 Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
279 */
280@interface CCTransitionFadeBL : CCTransitionFadeTR
281{}
282@end
283
284/** CCTransitionFadeUp:
285 * Fade the tiles of the outgoing scene from the bottom to the top.
286 */
287@interface CCTransitionFadeUp : CCTransitionFadeTR
288{}
289@end
290
291/** CCTransitionFadeDown:
292 * Fade the tiles of the outgoing scene from the top to the bottom.
293 */
294@interface CCTransitionFadeDown : CCTransitionFadeTR
295{}
296@end
diff --git a/libs/cocos2d/CCTransition.m b/libs/cocos2d/CCTransition.m new file mode 100755 index 0000000..22eed50 --- /dev/null +++ b/libs/cocos2d/CCTransition.m
@@ -0,0 +1,1059 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import "CCTransition.h"
30#import "CCNode.h"
31#import "CCDirector.h"
32#import "CCActionInterval.h"
33#import "CCActionInstant.h"
34#import "CCActionCamera.h"
35#import "CCLayer.h"
36#import "CCCamera.h"
37#import "CCActionTiledGrid.h"
38#import "CCActionEase.h"
39#import "CCRenderTexture.h"
40#import "Support/CGPointExtension.h"
41
42#import <Availability.h>
43#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
44#import "Platforms/iOS/CCTouchDispatcher.h"
45#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
46#import "Platforms/Mac/CCEventDispatcher.h"
47#endif
48
49const uint32_t kSceneFade = 0xFADEFADE;
50
51
52@interface CCTransitionScene (Private)
53-(void) sceneOrder;
54- (void)setNewScene:(ccTime)dt;
55@end
56
57@implementation CCTransitionScene
58+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s
59{
60 return [[[self alloc] initWithDuration:t scene:s] autorelease];
61}
62
63-(id) initWithDuration:(ccTime) t scene:(CCScene*)s
64{
65 NSAssert( s != nil, @"Argument scene must be non-nil");
66
67 if( (self=[super init]) ) {
68
69 duration_ = t;
70
71 // retain
72 inScene_ = [s retain];
73 outScene_ = [[CCDirector sharedDirector] runningScene];
74 [outScene_ retain];
75
76 NSAssert( inScene_ != outScene_, @"Incoming scene must be different from the outgoing scene" );
77
78 // disable events while transitions
79#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
80 [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: NO];
81#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
82 [[CCEventDispatcher sharedDispatcher] setDispatchEvents: NO];
83#endif
84
85 [self sceneOrder];
86 }
87 return self;
88}
89-(void) sceneOrder
90{
91 inSceneOnTop_ = YES;
92}
93
94-(void) draw
95{
96 [super draw];
97
98 if( inSceneOnTop_ ) {
99 [outScene_ visit];
100 [inScene_ visit];
101 } else {
102 [inScene_ visit];
103 [outScene_ visit];
104 }
105}
106
107-(void) finish
108{
109 /* clean up */
110 [inScene_ setVisible:YES];
111 [inScene_ setPosition:ccp(0,0)];
112 [inScene_ setScale:1.0f];
113 [inScene_ setRotation:0.0f];
114 [inScene_.camera restore];
115
116 [outScene_ setVisible:NO];
117 [outScene_ setPosition:ccp(0,0)];
118 [outScene_ setScale:1.0f];
119 [outScene_ setRotation:0.0f];
120 [outScene_.camera restore];
121
122 [self schedule:@selector(setNewScene:) interval:0];
123}
124
125-(void) setNewScene: (ccTime) dt
126{
127 [self unschedule:_cmd];
128
129 CCDirector *director = [CCDirector sharedDirector];
130
131 // Before replacing, save the "send cleanup to scene"
132 sendCleanupToScene_ = [director sendCleanupToScene];
133
134 [director replaceScene: inScene_];
135
136 // enable events while transitions
137#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
138 [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: YES];
139#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
140 [[CCEventDispatcher sharedDispatcher] setDispatchEvents: YES];
141#endif
142
143 // issue #267
144 [outScene_ setVisible:YES];
145}
146
147-(void) hideOutShowIn
148{
149 [inScene_ setVisible:YES];
150 [outScene_ setVisible:NO];
151}
152
153// custom onEnter
154-(void) onEnter
155{
156 [super onEnter];
157 [inScene_ onEnter];
158 // outScene_ should not receive the onEnter callback
159}
160
161// custom onExit
162-(void) onExit
163{
164 [super onExit];
165 [outScene_ onExit];
166
167 // inScene_ should not receive the onExit callback
168 // only the onEnterTransitionDidFinish
169 [inScene_ onEnterTransitionDidFinish];
170}
171
172// custom cleanup
173-(void) cleanup
174{
175 [super cleanup];
176
177 if( sendCleanupToScene_ )
178 [outScene_ cleanup];
179}
180
181-(void) dealloc
182{
183 [inScene_ release];
184 [outScene_ release];
185 [super dealloc];
186}
187@end
188
189//
190// Oriented Transition
191//
192@implementation CCTransitionSceneOriented
193+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o
194{
195 return [[[self alloc] initWithDuration:t scene:s orientation:o] autorelease];
196}
197
198-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o
199{
200 if( (self=[super initWithDuration:t scene:s]) )
201 orientation = o;
202 return self;
203}
204@end
205
206
207//
208// RotoZoom
209//
210@implementation CCTransitionRotoZoom
211-(void) onEnter
212{
213 [super onEnter];
214
215 [inScene_ setScale:0.001f];
216 [outScene_ setScale:1.0f];
217
218 [inScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
219 [outScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
220
221 CCActionInterval *rotozoom = [CCSequence actions: [CCSpawn actions:
222 [CCScaleBy actionWithDuration:duration_/2 scale:0.001f],
223 [CCRotateBy actionWithDuration:duration_/2 angle:360 *2],
224 nil],
225 [CCDelayTime actionWithDuration:duration_/2],
226 nil];
227
228
229 [outScene_ runAction: rotozoom];
230 [inScene_ runAction: [CCSequence actions:
231 [rotozoom reverse],
232 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
233 nil]];
234}
235@end
236
237//
238// JumpZoom
239//
240@implementation CCTransitionJumpZoom
241-(void) onEnter
242{
243 [super onEnter];
244 CGSize s = [[CCDirector sharedDirector] winSize];
245
246 [inScene_ setScale:0.5f];
247 [inScene_ setPosition:ccp( s.width,0 )];
248
249 [inScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
250 [outScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
251
252 CCActionInterval *jump = [CCJumpBy actionWithDuration:duration_/4 position:ccp(-s.width,0) height:s.width/4 jumps:2];
253 CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:duration_/4 scale:1.0f];
254 CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:duration_/4 scale:0.5f];
255
256 CCActionInterval *jumpZoomOut = [CCSequence actions: scaleOut, jump, nil];
257 CCActionInterval *jumpZoomIn = [CCSequence actions: jump, scaleIn, nil];
258
259 CCActionInterval *delay = [CCDelayTime actionWithDuration:duration_/2];
260
261 [outScene_ runAction: jumpZoomOut];
262 [inScene_ runAction: [CCSequence actions: delay,
263 jumpZoomIn,
264 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
265 nil] ];
266}
267@end
268
269//
270// MoveInL
271//
272@implementation CCTransitionMoveInL
273-(void) onEnter
274{
275 [super onEnter];
276
277 [self initScenes];
278
279 CCActionInterval *a = [self action];
280
281 [inScene_ runAction: [CCSequence actions:
282 [self easeActionWithAction:a],
283 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
284 nil]
285 ];
286
287}
288-(CCActionInterval*) action
289{
290 return [CCMoveTo actionWithDuration:duration_ position:ccp(0,0)];
291}
292
293-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
294{
295 return [CCEaseOut actionWithAction:action rate:2.0f];
296// return [EaseElasticOut actionWithAction:action period:0.4f];
297}
298
299-(void) initScenes
300{
301 CGSize s = [[CCDirector sharedDirector] winSize];
302 [inScene_ setPosition: ccp( -s.width,0) ];
303}
304@end
305
306//
307// MoveInR
308//
309@implementation CCTransitionMoveInR
310-(void) initScenes
311{
312 CGSize s = [[CCDirector sharedDirector] winSize];
313 [inScene_ setPosition: ccp( s.width,0) ];
314}
315@end
316
317//
318// MoveInT
319//
320@implementation CCTransitionMoveInT
321-(void) initScenes
322{
323 CGSize s = [[CCDirector sharedDirector] winSize];
324 [inScene_ setPosition: ccp( 0, s.height) ];
325}
326@end
327
328//
329// MoveInB
330//
331@implementation CCTransitionMoveInB
332-(void) initScenes
333{
334 CGSize s = [[CCDirector sharedDirector] winSize];
335 [inScene_ setPosition: ccp( 0, -s.height) ];
336}
337@end
338
339//
340// SlideInL
341//
342
343// The adjust factor is needed to prevent issue #442
344// One solution is to use DONT_RENDER_IN_SUBPIXELS images, but NO
345// The other issue is that in some transitions (and I don't know why)
346// the order should be reversed (In in top of Out or vice-versa).
347#define ADJUST_FACTOR 0.5f
348@implementation CCTransitionSlideInL
349-(void) onEnter
350{
351 [super onEnter];
352
353 [self initScenes];
354
355 CCActionInterval *in = [self action];
356 CCActionInterval *out = [self action];
357
358 id inAction = [self easeActionWithAction:in];
359 id outAction = [CCSequence actions:
360 [self easeActionWithAction:out],
361 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
362 nil];
363
364 [inScene_ runAction: inAction];
365 [outScene_ runAction: outAction];
366}
367-(void) sceneOrder
368{
369 inSceneOnTop_ = NO;
370}
371-(void) initScenes
372{
373 CGSize s = [[CCDirector sharedDirector] winSize];
374 [inScene_ setPosition: ccp( -(s.width-ADJUST_FACTOR),0) ];
375}
376-(CCActionInterval*) action
377{
378 CGSize s = [[CCDirector sharedDirector] winSize];
379 return [CCMoveBy actionWithDuration:duration_ position:ccp(s.width-ADJUST_FACTOR,0)];
380}
381
382-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
383{
384 return [CCEaseOut actionWithAction:action rate:2.0f];
385// return [EaseElasticOut actionWithAction:action period:0.4f];
386}
387
388@end
389
390//
391// SlideInR
392//
393@implementation CCTransitionSlideInR
394-(void) sceneOrder
395{
396 inSceneOnTop_ = YES;
397}
398-(void) initScenes
399{
400 CGSize s = [[CCDirector sharedDirector] winSize];
401 [inScene_ setPosition: ccp( s.width-ADJUST_FACTOR,0) ];
402}
403
404-(CCActionInterval*) action
405{
406 CGSize s = [[CCDirector sharedDirector] winSize];
407 return [CCMoveBy actionWithDuration:duration_ position:ccp(-(s.width-ADJUST_FACTOR),0)];
408}
409
410@end
411
412//
413// SlideInT
414//
415@implementation CCTransitionSlideInT
416-(void) sceneOrder
417{
418 inSceneOnTop_ = NO;
419}
420-(void) initScenes
421{
422 CGSize s = [[CCDirector sharedDirector] winSize];
423 [inScene_ setPosition: ccp(0,s.height-ADJUST_FACTOR) ];
424}
425
426-(CCActionInterval*) action
427{
428 CGSize s = [[CCDirector sharedDirector] winSize];
429 return [CCMoveBy actionWithDuration:duration_ position:ccp(0,-(s.height-ADJUST_FACTOR))];
430}
431
432@end
433
434//
435// SlideInB
436//
437@implementation CCTransitionSlideInB
438-(void) sceneOrder
439{
440 inSceneOnTop_ = YES;
441}
442
443-(void) initScenes
444{
445 CGSize s = [[CCDirector sharedDirector] winSize];
446 [inScene_ setPosition: ccp(0,-(s.height-ADJUST_FACTOR)) ];
447}
448
449-(CCActionInterval*) action
450{
451 CGSize s = [[CCDirector sharedDirector] winSize];
452 return [CCMoveBy actionWithDuration:duration_ position:ccp(0,s.height-ADJUST_FACTOR)];
453}
454@end
455
456//
457// ShrinkGrow Transition
458//
459@implementation CCTransitionShrinkGrow
460-(void) onEnter
461{
462 [super onEnter];
463
464 [inScene_ setScale:0.001f];
465 [outScene_ setScale:1.0f];
466
467 [inScene_ setAnchorPoint:ccp(2/3.0f,0.5f)];
468 [outScene_ setAnchorPoint:ccp(1/3.0f,0.5f)];
469
470 CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:duration_ scale:0.01f];
471 CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:duration_ scale:1.0f];
472
473 [inScene_ runAction: [self easeActionWithAction:scaleIn]];
474 [outScene_ runAction: [CCSequence actions:
475 [self easeActionWithAction:scaleOut],
476 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
477 nil] ];
478}
479-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
480{
481 return [CCEaseOut actionWithAction:action rate:2.0f];
482// return [EaseElasticOut actionWithAction:action period:0.3f];
483}
484@end
485
486//
487// FlipX Transition
488//
489@implementation CCTransitionFlipX
490-(void) onEnter
491{
492 [super onEnter];
493
494 CCActionInterval *inA, *outA;
495 [inScene_ setVisible: NO];
496
497 float inDeltaZ, inAngleZ;
498 float outDeltaZ, outAngleZ;
499
500 if( orientation == kOrientationRightOver ) {
501 inDeltaZ = 90;
502 inAngleZ = 270;
503 outDeltaZ = 90;
504 outAngleZ = 0;
505 } else {
506 inDeltaZ = -90;
507 inAngleZ = 90;
508 outDeltaZ = -90;
509 outAngleZ = 0;
510 }
511
512 inA = [CCSequence actions:
513 [CCDelayTime actionWithDuration:duration_/2],
514 [CCShow action],
515 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0],
516 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
517 nil ];
518 outA = [CCSequence actions:
519 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0],
520 [CCHide action],
521 [CCDelayTime actionWithDuration:duration_/2],
522 nil ];
523
524 [inScene_ runAction: inA];
525 [outScene_ runAction: outA];
526
527}
528@end
529
530//
531// FlipY Transition
532//
533@implementation CCTransitionFlipY
534-(void) onEnter
535{
536 [super onEnter];
537
538 CCActionInterval *inA, *outA;
539 [inScene_ setVisible: NO];
540
541 float inDeltaZ, inAngleZ;
542 float outDeltaZ, outAngleZ;
543
544 if( orientation == kOrientationUpOver ) {
545 inDeltaZ = 90;
546 inAngleZ = 270;
547 outDeltaZ = 90;
548 outAngleZ = 0;
549 } else {
550 inDeltaZ = -90;
551 inAngleZ = 90;
552 outDeltaZ = -90;
553 outAngleZ = 0;
554 }
555 inA = [CCSequence actions:
556 [CCDelayTime actionWithDuration:duration_/2],
557 [CCShow action],
558 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0],
559 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
560 nil ];
561 outA = [CCSequence actions:
562 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0],
563 [CCHide action],
564 [CCDelayTime actionWithDuration:duration_/2],
565 nil ];
566
567 [inScene_ runAction: inA];
568 [outScene_ runAction: outA];
569
570}
571@end
572
573//
574// FlipAngular Transition
575//
576@implementation CCTransitionFlipAngular
577-(void) onEnter
578{
579 [super onEnter];
580
581 CCActionInterval *inA, *outA;
582 [inScene_ setVisible: NO];
583
584 float inDeltaZ, inAngleZ;
585 float outDeltaZ, outAngleZ;
586
587 if( orientation == kOrientationRightOver ) {
588 inDeltaZ = 90;
589 inAngleZ = 270;
590 outDeltaZ = 90;
591 outAngleZ = 0;
592 } else {
593 inDeltaZ = -90;
594 inAngleZ = 90;
595 outDeltaZ = -90;
596 outAngleZ = 0;
597 }
598 inA = [CCSequence actions:
599 [CCDelayTime actionWithDuration:duration_/2],
600 [CCShow action],
601 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0],
602 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
603 nil ];
604 outA = [CCSequence actions:
605 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0],
606 [CCHide action],
607 [CCDelayTime actionWithDuration:duration_/2],
608 nil ];
609
610 [inScene_ runAction: inA];
611 [outScene_ runAction: outA];
612}
613@end
614
615//
616// ZoomFlipX Transition
617//
618@implementation CCTransitionZoomFlipX
619-(void) onEnter
620{
621 [super onEnter];
622
623 CCActionInterval *inA, *outA;
624 [inScene_ setVisible: NO];
625
626 float inDeltaZ, inAngleZ;
627 float outDeltaZ, outAngleZ;
628
629 if( orientation == kOrientationRightOver ) {
630 inDeltaZ = 90;
631 inAngleZ = 270;
632 outDeltaZ = 90;
633 outAngleZ = 0;
634 } else {
635 inDeltaZ = -90;
636 inAngleZ = 90;
637 outDeltaZ = -90;
638 outAngleZ = 0;
639 }
640 inA = [CCSequence actions:
641 [CCDelayTime actionWithDuration:duration_/2],
642 [CCSpawn actions:
643 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0],
644 [CCScaleTo actionWithDuration:duration_/2 scale:1],
645 [CCShow action],
646 nil],
647 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
648 nil ];
649 outA = [CCSequence actions:
650 [CCSpawn actions:
651 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0],
652 [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
653 nil],
654 [CCHide action],
655 [CCDelayTime actionWithDuration:duration_/2],
656 nil ];
657
658 inScene_.scale = 0.5f;
659 [inScene_ runAction: inA];
660 [outScene_ runAction: outA];
661}
662@end
663
664//
665// ZoomFlipY Transition
666//
667@implementation CCTransitionZoomFlipY
668-(void) onEnter
669{
670 [super onEnter];
671
672 CCActionInterval *inA, *outA;
673 [inScene_ setVisible: NO];
674
675 float inDeltaZ, inAngleZ;
676 float outDeltaZ, outAngleZ;
677
678 if( orientation == kOrientationUpOver ) {
679 inDeltaZ = 90;
680 inAngleZ = 270;
681 outDeltaZ = 90;
682 outAngleZ = 0;
683 } else {
684 inDeltaZ = -90;
685 inAngleZ = 90;
686 outDeltaZ = -90;
687 outAngleZ = 0;
688 }
689
690 inA = [CCSequence actions:
691 [CCDelayTime actionWithDuration:duration_/2],
692 [CCSpawn actions:
693 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0],
694 [CCScaleTo actionWithDuration:duration_/2 scale:1],
695 [CCShow action],
696 nil],
697 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
698 nil ];
699 outA = [CCSequence actions:
700 [CCSpawn actions:
701 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0],
702 [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
703 nil],
704 [CCHide action],
705 [CCDelayTime actionWithDuration:duration_/2],
706 nil ];
707
708 inScene_.scale = 0.5f;
709 [inScene_ runAction: inA];
710 [outScene_ runAction: outA];
711}
712@end
713
714//
715// ZoomFlipAngular Transition
716//
717@implementation CCTransitionZoomFlipAngular
718-(void) onEnter
719{
720 [super onEnter];
721
722 CCActionInterval *inA, *outA;
723 [inScene_ setVisible: NO];
724
725 float inDeltaZ, inAngleZ;
726 float outDeltaZ, outAngleZ;
727
728 if( orientation == kOrientationRightOver ) {
729 inDeltaZ = 90;
730 inAngleZ = 270;
731 outDeltaZ = 90;
732 outAngleZ = 0;
733 } else {
734 inDeltaZ = -90;
735 inAngleZ = 90;
736 outDeltaZ = -90;
737 outAngleZ = 0;
738 }
739
740 inA = [CCSequence actions:
741 [CCDelayTime actionWithDuration:duration_/2],
742 [CCSpawn actions:
743 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0],
744 [CCScaleTo actionWithDuration:duration_/2 scale:1],
745 [CCShow action],
746 nil],
747 [CCShow action],
748 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
749 nil ];
750 outA = [CCSequence actions:
751 [CCSpawn actions:
752 [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0],
753 [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
754 nil],
755 [CCHide action],
756 [CCDelayTime actionWithDuration:duration_/2],
757 nil ];
758
759 inScene_.scale = 0.5f;
760 [inScene_ runAction: inA];
761 [outScene_ runAction: outA];
762}
763@end
764
765
766//
767// Fade Transition
768//
769@implementation CCTransitionFade
770+(id) transitionWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)color
771{
772 return [[[self alloc] initWithDuration:d scene:s withColor:color] autorelease];
773}
774
775-(id) initWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)aColor
776{
777 if( (self=[super initWithDuration:d scene:s]) ) {
778 color.r = aColor.r;
779 color.g = aColor.g;
780 color.b = aColor.b;
781 }
782
783 return self;
784}
785
786-(id) initWithDuration:(ccTime)d scene:(CCScene*)s
787{
788 return [self initWithDuration:d scene:s withColor:ccBLACK];
789}
790
791-(void) onEnter
792{
793 [super onEnter];
794
795 CCLayerColor *l = [CCLayerColor layerWithColor:color];
796 [inScene_ setVisible: NO];
797
798 [self addChild: l z:2 tag:kSceneFade];
799
800
801 CCNode *f = [self getChildByTag:kSceneFade];
802
803 CCActionInterval *a = [CCSequence actions:
804 [CCFadeIn actionWithDuration:duration_/2],
805 [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
806 [CCFadeOut actionWithDuration:duration_/2],
807 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
808 nil ];
809 [f runAction: a];
810}
811
812-(void) onExit
813{
814 [super onExit];
815 [self removeChildByTag:kSceneFade cleanup:NO];
816}
817@end
818
819
820//
821// Cross Fade Transition
822//
823@implementation CCTransitionCrossFade
824
825-(void) draw
826{
827 // override draw since both scenes (textures) are rendered in 1 scene
828}
829
830-(void) onEnter
831{
832 [super onEnter];
833
834 // create a transparent color layer
835 // in which we are going to add our rendertextures
836 ccColor4B color = {0,0,0,0};
837 CGSize size = [[CCDirector sharedDirector] winSize];
838 CCLayerColor * layer = [CCLayerColor layerWithColor:color];
839
840 // create the first render texture for inScene_
841 CCRenderTexture *inTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
842 inTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
843 inTexture.position = ccp(size.width/2, size.height/2);
844 inTexture.anchorPoint = ccp(0.5f,0.5f);
845
846 // render inScene_ to its texturebuffer
847 [inTexture begin];
848 [inScene_ visit];
849 [inTexture end];
850
851 // create the second render texture for outScene_
852 CCRenderTexture *outTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
853 outTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
854 outTexture.position = ccp(size.width/2, size.height/2);
855 outTexture.anchorPoint = ccp(0.5f,0.5f);
856
857 // render outScene_ to its texturebuffer
858 [outTexture begin];
859 [outScene_ visit];
860 [outTexture end];
861
862 // create blend functions
863
864 ccBlendFunc blend1 = {GL_ONE, GL_ONE}; // inScene_ will lay on background and will not be used with alpha
865 ccBlendFunc blend2 = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}; // we are going to blend outScene_ via alpha
866
867 // set blendfunctions
868 [inTexture.sprite setBlendFunc:blend1];
869 [outTexture.sprite setBlendFunc:blend2];
870
871 // add render textures to the layer
872 [layer addChild:inTexture];
873 [layer addChild:outTexture];
874
875 // initial opacity:
876 [inTexture.sprite setOpacity:255];
877 [outTexture.sprite setOpacity:255];
878
879 // create the blend action
880 CCActionInterval * layerAction = [CCSequence actions:
881 [CCFadeTo actionWithDuration:duration_ opacity:0],
882 [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
883 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
884 nil ];
885
886
887 // run the blend action
888 [outTexture.sprite runAction: layerAction];
889
890 // add the layer (which contains our two rendertextures) to the scene
891 [self addChild: layer z:2 tag:kSceneFade];
892}
893
894// clean up on exit
895-(void) onExit
896{
897 // remove our layer and release all containing objects
898 [self removeChildByTag:kSceneFade cleanup:NO];
899
900 [super onExit];
901}
902@end
903
904//
905// TurnOffTilesTransition
906//
907@implementation CCTransitionTurnOffTiles
908
909// override addScenes, and change the order
910-(void) sceneOrder
911{
912 inSceneOnTop_ = NO;
913}
914
915-(void) onEnter
916{
917 [super onEnter];
918 CGSize s = [[CCDirector sharedDirector] winSize];
919 float aspect = s.width / s.height;
920 int x = 12 * aspect;
921 int y = 12;
922
923 id toff = [CCTurnOffTiles actionWithSize: ccg(x,y) duration:duration_];
924 id action = [self easeActionWithAction:toff];
925 [outScene_ runAction: [CCSequence actions: action,
926 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
927 [CCStopGrid action],
928 nil]
929 ];
930
931}
932-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
933{
934 return action;
935// return [EaseIn actionWithAction:action rate:2.0f];
936}
937@end
938
939#pragma mark Split Transitions
940
941//
942// SplitCols Transition
943//
944@implementation CCTransitionSplitCols
945
946-(void) onEnter
947{
948 [super onEnter];
949
950 inScene_.visible = NO;
951
952 id split = [self action];
953 id seq = [CCSequence actions:
954 split,
955 [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
956 [split reverse],
957 nil
958 ];
959 [self runAction: [CCSequence actions:
960 [self easeActionWithAction:seq],
961 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
962 [CCStopGrid action],
963 nil]
964 ];
965}
966
967-(CCActionInterval*) action
968{
969 return [CCSplitCols actionWithCols:3 duration:duration_/2.0f];
970}
971
972-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
973{
974 return [CCEaseInOut actionWithAction:action rate:3.0f];
975}
976@end
977
978//
979// SplitRows Transition
980//
981@implementation CCTransitionSplitRows
982-(CCActionInterval*) action
983{
984 return [CCSplitRows actionWithRows:3 duration:duration_/2.0f];
985}
986@end
987
988
989#pragma mark Fade Grid Transitions
990
991//
992// FadeTR Transition
993//
994@implementation CCTransitionFadeTR
995-(void) sceneOrder
996{
997 inSceneOnTop_ = NO;
998}
999
1000-(void) onEnter
1001{
1002 [super onEnter];
1003
1004 CGSize s = [[CCDirector sharedDirector] winSize];
1005 float aspect = s.width / s.height;
1006 int x = 12 * aspect;
1007 int y = 12;
1008
1009 id action = [self actionWithSize:ccg(x,y)];
1010
1011 [outScene_ runAction: [CCSequence actions:
1012 [self easeActionWithAction:action],
1013 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
1014 [CCStopGrid action],
1015 nil]
1016 ];
1017}
1018
1019-(CCActionInterval*) actionWithSize: (ccGridSize) v
1020{
1021 return [CCFadeOutTRTiles actionWithSize:v duration:duration_];
1022}
1023
1024-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
1025{
1026 return action;
1027// return [EaseIn actionWithAction:action rate:2.0f];
1028}
1029@end
1030
1031//
1032// FadeBL Transition
1033//
1034@implementation CCTransitionFadeBL
1035-(CCActionInterval*) actionWithSize: (ccGridSize) v
1036{
1037 return [CCFadeOutBLTiles actionWithSize:v duration:duration_];
1038}
1039@end
1040
1041//
1042// FadeUp Transition
1043//
1044@implementation CCTransitionFadeUp
1045-(CCActionInterval*) actionWithSize: (ccGridSize) v
1046{
1047 return [CCFadeOutUpTiles actionWithSize:v duration:duration_];
1048}
1049@end
1050
1051//
1052// FadeDown Transition
1053//
1054@implementation CCTransitionFadeDown
1055-(CCActionInterval*) actionWithSize: (ccGridSize) v
1056{
1057 return [CCFadeOutDownTiles actionWithSize:v duration:duration_];
1058}
1059@end
diff --git a/libs/cocos2d/CCTransitionPageTurn.h b/libs/cocos2d/CCTransitionPageTurn.h new file mode 100755 index 0000000..aacb7fc --- /dev/null +++ b/libs/cocos2d/CCTransitionPageTurn.h
@@ -0,0 +1,60 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCTransition.h"
28
29/** CCTransitionPageTurn transition.
30 * A transition which peels back the bottom right hand corner of a scene
31 * to transition to the scene beneath it simulating a page turn
32 *
33 * This uses a 3DAction so it's strongly recommended that depth buffering
34 * is turned on in CCDirector using:
35 *
36 * [[CCDirector sharedDirector] setDepthBufferFormat:kCCDepthBuffer16];
37 *
38 * @since v0.8.2
39 */
40@interface CCTransitionPageTurn : CCTransitionScene
41{
42 BOOL back_;
43}
44/**
45 * creates a base transition with duration and incoming scene
46 * if back is TRUE then the effect is reversed to appear as if the incoming
47 * scene is being turned from left over the outgoing scene
48 */
49+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back;
50
51/**
52 * creates a base transition with duration and incoming scene
53 * if back is TRUE then the effect is reversed to appear as if the incoming
54 * scene is being turned from left over the outgoing scene
55 */
56-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back;
57
58-(CCActionInterval*) actionWithSize:(ccGridSize) vector;
59
60@end
diff --git a/libs/cocos2d/CCTransitionPageTurn.m b/libs/cocos2d/CCTransitionPageTurn.m new file mode 100755 index 0000000..bff43a7 --- /dev/null +++ b/libs/cocos2d/CCTransitionPageTurn.m
@@ -0,0 +1,117 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "CCTransitionPageTurn.h"
28#import "CCActionPageTurn3D.h"
29#import "CCDirector.h"
30
31@implementation CCTransitionPageTurn
32
33/** creates a base transition with duration and incoming scene */
34+(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back
35{
36 return [[[self alloc] initWithDuration:t scene:s backwards:back] autorelease];
37}
38
39/** initializes a transition with duration and incoming scene */
40-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back
41{
42 // XXX: needed before [super init]
43 back_ = back;
44
45 if( ( self = [super initWithDuration:t scene:s] ) )
46 {
47 // do something
48 }
49 return self;
50}
51
52-(void) sceneOrder
53{
54 inSceneOnTop_ = back_;
55}
56
57//
58-(void) onEnter
59{
60 [super onEnter];
61
62 CGSize s = [[CCDirector sharedDirector] winSize];
63 int x, y;
64 if( s.width > s.height)
65 {
66 x = 16;
67 y = 12;
68 }
69 else
70 {
71 x = 12;
72 y = 16;
73 }
74
75 id action = [self actionWithSize:ccg(x,y)];
76
77 if(! back_ )
78 {
79 [outScene_ runAction: [CCSequence actions:
80 action,
81 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
82 [CCStopGrid action],
83 nil]
84 ];
85 }
86 else
87 {
88 // to prevent initial flicker
89 inScene_.visible = NO;
90 [inScene_ runAction: [CCSequence actions:
91 [CCShow action],
92 action,
93 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
94 [CCStopGrid action],
95 nil]
96 ];
97 }
98
99}
100
101-(CCActionInterval*) actionWithSize: (ccGridSize) v
102{
103 if( back_ )
104 {
105 // Get hold of the PageTurn3DAction
106 return [CCReverseTime actionWithAction:
107 [CCPageTurn3D actionWithSize:v duration:duration_]];
108 }
109 else
110 {
111 // Get hold of the PageTurn3DAction
112 return [CCPageTurn3D actionWithSize:v duration:duration_];
113 }
114}
115
116@end
117
diff --git a/libs/cocos2d/CCTransitionRadial.h b/libs/cocos2d/CCTransitionRadial.h new file mode 100755 index 0000000..6d4a5e0 --- /dev/null +++ b/libs/cocos2d/CCTransitionRadial.h
@@ -0,0 +1,40 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "CCTransition.h"
27#import "CCProgressTimer.h"
28#import "CCActionProgressTimer.h"
29
30/** CCTransitionRadialCCW transition.
31 A counter colock-wise radial transition to the next scene
32 */
33@interface CCTransitionRadialCCW : CCTransitionScene
34@end
35
36/** CCTransitionRadialCW transition.
37 A counter colock-wise radial transition to the next scene
38*/
39@interface CCTransitionRadialCW : CCTransitionRadialCCW
40@end
diff --git a/libs/cocos2d/CCTransitionRadial.m b/libs/cocos2d/CCTransitionRadial.m new file mode 100755 index 0000000..a892f35 --- /dev/null +++ b/libs/cocos2d/CCTransitionRadial.m
@@ -0,0 +1,115 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Lam Pham
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27
28#import "CCDirector.h"
29#import "CCTransitionRadial.h"
30#import "CCRenderTexture.h"
31#import "CCLayer.h"
32#import "CCActionInstant.h"
33#import "Support/CGPointExtension.h"
34
35enum {
36 kSceneRadial = 0xc001,
37};
38
39#pragma mark -
40#pragma mark Transition Radial CCW
41
42@implementation CCTransitionRadialCCW
43-(void) sceneOrder
44{
45 inSceneOnTop_ = NO;
46}
47
48-(CCProgressTimerType) radialType
49{
50 return kCCProgressTimerTypeRadialCCW;
51}
52
53-(void) onEnter
54{
55 [super onEnter];
56 // create a transparent color layer
57 // in which we are going to add our rendertextures
58 CGSize size = [[CCDirector sharedDirector] winSize];
59
60 // create the second render texture for outScene
61 CCRenderTexture *outTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
62 outTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
63 outTexture.position = ccp(size.width/2, size.height/2);
64 outTexture.anchorPoint = ccp(0.5f,0.5f);
65
66 // render outScene to its texturebuffer
67 [outTexture clear:0 g:0 b:0 a:1];
68 [outTexture begin];
69 [outScene_ visit];
70 [outTexture end];
71
72 // Since we've passed the outScene to the texture we don't need it.
73 [self hideOutShowIn];
74
75 // We need the texture in RenderTexture.
76 CCProgressTimer *outNode = [CCProgressTimer progressWithTexture:outTexture.sprite.texture];
77 // but it's flipped upside down so we flip the sprite
78 outNode.sprite.flipY = YES;
79 // Return the radial type that we want to use
80 outNode.type = [self radialType];
81 outNode.percentage = 100.f;
82 outNode.position = ccp(size.width/2, size.height/2);
83 outNode.anchorPoint = ccp(0.5f,0.5f);
84
85 // create the blend action
86 CCActionInterval * layerAction = [CCSequence actions:
87 [CCProgressFromTo actionWithDuration:duration_ from:100.f to:0.f],
88 [CCCallFunc actionWithTarget:self selector:@selector(finish)],
89 nil ];
90 // run the blend action
91 [outNode runAction: layerAction];
92
93 // add the layer (which contains our two rendertextures) to the scene
94 [self addChild: outNode z:2 tag:kSceneRadial];
95}
96
97// clean up on exit
98-(void) onExit
99{
100 // remove our layer and release all containing objects
101 [self removeChildByTag:kSceneRadial cleanup:NO];
102 [super onExit];
103}
104@end
105
106#pragma mark -
107#pragma mark Transition Radial CW
108
109@implementation CCTransitionRadialCW
110-(CCProgressTimerType) radialType
111{
112 return kCCProgressTimerTypeRadialCW;
113}
114@end
115
diff --git a/libs/cocos2d/Platforms/CCGL.h b/libs/cocos2d/Platforms/CCGL.h new file mode 100755 index 0000000..0725f89 --- /dev/null +++ b/libs/cocos2d/Platforms/CCGL.h
@@ -0,0 +1,83 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26//
27// Common layer for OpenGL stuff
28//
29
30#import <Availability.h>
31
32#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
33#import <OpenGLES/ES1/gl.h>
34#import <OpenGLES/ES1/glext.h>
35#import <OpenGLES/EAGL.h>
36#import "iOS/glu.h"
37#import "iOS/EAGLView.h"
38
39#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
40#import <OpenGL/gl.h>
41#import <OpenGL/glu.h>
42#import <Cocoa/Cocoa.h> // needed for NSOpenGLView
43#import "Mac/MacGLView.h"
44#endif
45
46
47// iOS
48#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
49#define CC_GLVIEW EAGLView
50#define ccglOrtho glOrthof
51#define ccglClearDepth glClearDepthf
52#define ccglGenerateMipmap glGenerateMipmapOES
53#define ccglGenFramebuffers glGenFramebuffersOES
54#define ccglBindFramebuffer glBindFramebufferOES
55#define ccglFramebufferTexture2D glFramebufferTexture2DOES
56#define ccglDeleteFramebuffers glDeleteFramebuffersOES
57#define ccglCheckFramebufferStatus glCheckFramebufferStatusOES
58#define ccglTranslate glTranslatef
59
60#define CC_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
61#define CC_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
62#define CC_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
63#define CC_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
64
65// Mac
66#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
67#define CC_GLVIEW MacGLView
68#define ccglOrtho glOrtho
69#define ccglClearDepth glClearDepth
70#define ccglGenerateMipmap glGenerateMipmap
71#define ccglGenFramebuffers glGenFramebuffers
72#define ccglBindFramebuffer glBindFramebuffer
73#define ccglFramebufferTexture2D glFramebufferTexture2D
74#define ccglDeleteFramebuffers glDeleteFramebuffers
75#define ccglCheckFramebufferStatus glCheckFramebufferStatus
76#define ccglTranslate glTranslated
77
78#define CC_GL_FRAMEBUFFER GL_FRAMEBUFFER
79#define CC_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
80#define CC_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0
81#define CC_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE
82
83#endif
diff --git a/libs/cocos2d/Platforms/CCNS.h b/libs/cocos2d/Platforms/CCNS.h new file mode 100755 index 0000000..c595a18 --- /dev/null +++ b/libs/cocos2d/Platforms/CCNS.h
@@ -0,0 +1,78 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26//
27// Common layer for NS (Next-Step) stuff
28//
29
30#import <Availability.h>
31
32#import <Foundation/Foundation.h> // for NSObject
33
34#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
35
36#define CCRectFromString(__r__) CGRectFromString(__r__)
37#define CCPointFromString(__p__) CGPointFromString(__p__)
38#define CCSizeFromString(__s__) CGSizeFromString(__s__)
39#define CCNSSizeToCGSize
40#define CCNSRectToCGRect
41#define CCNSPointToCGPoint
42#define CCTextAlignment UITextAlignment
43#define CCTextAlignmentCenter UITextAlignmentCenter
44#define CCTextAlignmentLeft UITextAlignmentLeft
45#define CCTextAlignmentRight UITextAlignmentRight
46#define CCLineBreakMode UILineBreakMode
47#define CCLineBreakModeWordWrap UILineBreakModeWordWrap
48#define CCLineBreakModeCharacterWrap UILineBreakModeCharacterWrap
49#define CCLineBreakModeClip UILineBreakModeClip
50#define CCLineBreakModeHeadTruncation UILineBreakModeHeadTruncation
51#define CCLineBreakModeTailTruncation UILineBreakModeTailTruncation
52#define CCLineBreakModeMiddleTruncation UILineBreakModeMiddleTruncation
53
54
55
56#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
57
58#define CCRectFromString(__r__) NSRectToCGRect( NSRectFromString(__r__) )
59#define CCPointFromString(__p__) NSPointToCGPoint( NSPointFromString(__p__) )
60#define CCSizeFromString(__s__) NSSizeToCGSize( NSSizeFromString(__s__) )
61#define CCNSSizeToCGSize NSSizeToCGSize
62#define CCNSRectToCGRect NSRectToCGRect
63#define CCNSPointToCGPoint NSPointToCGPoint
64#define CCTextAlignment NSTextAlignment
65#define CCTextAlignmentCenter NSCenterTextAlignment
66#define CCTextAlignmentLeft NSLeftTextAlignment
67#define CCTextAlignmentRight NSRightTextAlignment
68#define CCLineBreakMode NSLineBreakMode
69#define CCLineBreakModeWordWrap NSLineBreakByWordWrapping
70#define CCLineBreakModeClip -1
71#define CCLineBreakModeHeadTruncation -1
72#define CCLineBreakModeTailTruncation -1
73#define CCLineBreakModeMiddleTruncation -1
74
75
76#endif
77
78
diff --git a/libs/cocos2d/Platforms/Mac/CCDirectorMac.h b/libs/cocos2d/Platforms/Mac/CCDirectorMac.h new file mode 100755 index 0000000..0d623b4 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/CCDirectorMac.h
@@ -0,0 +1,103 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27// Only compile this code on Mac. These files should not be included on your iOS project.
28// But in case they are included, it won't be compiled.
29#import <Availability.h>
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
32
33#import <QuartzCore/CVDisplayLink.h>
34#import "../../CCDirector.h"
35
36enum {
37 /// If the window is resized, it won't be autoscaled
38 kCCDirectorResize_NoScale,
39 /// If the window is resized, it will be autoscaled (default behavior)
40 kCCDirectorResize_AutoScale,
41};
42
43@interface CCDirector (MacExtension)
44/** converts an NSEvent to GL coordinates */
45-(CGPoint) convertEventToGL:(NSEvent*)event;
46@end
47
48/** Base class of Mac directors
49 @since v0.99.5
50 */
51@interface CCDirectorMac : CCDirector
52{
53 BOOL isFullScreen_;
54 int resizeMode_;
55 CGPoint winOffset_;
56 CGSize originalWinSize_;
57
58 NSWindow *fullScreenWindow_;
59
60 // cache
61 NSWindow *windowGLView_;
62 NSView *superViewGLView_;
63 NSRect originalWinRect_; // Original size and position
64}
65
66// whether or not the view is in fullscreen mode
67@property (nonatomic, readonly) BOOL isFullScreen;
68
69// resize mode: with or without scaling
70@property (nonatomic, readwrite) int resizeMode;
71
72@property (nonatomic, readwrite) CGSize originalWinSize;
73
74/** Sets the view in fullscreen or window mode */
75- (void) setFullScreen:(BOOL)fullscreen;
76
77/** Converts window size coordiantes to logical coordinates.
78 Useful only if resizeMode is kCCDirectorResize_Scale.
79 If resizeMode is kCCDirectorResize_NoScale, then no conversion will be done.
80*/
81- (CGPoint) convertToLogicalCoordinates:(CGPoint)coordinates;
82@end
83
84
85/** DisplayLinkDirector is a Director that synchronizes timers with the refresh rate of the display.
86 *
87 * Features and Limitations:
88 * - Only available on 3.1+
89 * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
90 * - Only supports animation intervals of 1/60 1/30 & 1/15
91 *
92 * It is the recommended Director if the SDK is 3.1 or newer
93 *
94 * @since v0.8.2
95 */
96@interface CCDirectorDisplayLink : CCDirectorMac
97{
98 CVDisplayLinkRef displayLink;
99}
100@end
101
102#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
103
diff --git a/libs/cocos2d/Platforms/Mac/CCDirectorMac.m b/libs/cocos2d/Platforms/Mac/CCDirectorMac.m new file mode 100755 index 0000000..477081e --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/CCDirectorMac.m
@@ -0,0 +1,479 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26// Only compile this code on Mac. These files should not be included on your iOS project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
31
32#import <sys/time.h>
33
34#import "CCDirectorMac.h"
35#import "CCEventDispatcher.h"
36#import "MacGLView.h"
37
38#import "../../CCNode.h"
39#import "../../CCScheduler.h"
40#import "../../ccMacros.h"
41
42#pragma mark -
43#pragma mark Director Mac extensions
44
45
46@interface CCDirector ()
47-(void) setNextScene;
48-(void) showFPS;
49-(void) calculateDeltaTime;
50@end
51
52@implementation CCDirector (MacExtension)
53-(CGPoint) convertEventToGL:(NSEvent*)event
54{
55 NSPoint point = [openGLView_ convertPoint:[event locationInWindow] fromView:nil];
56 CGPoint p = NSPointToCGPoint(point);
57
58 return [(CCDirectorMac*)self convertToLogicalCoordinates:p];
59}
60
61@end
62
63#pragma mark -
64#pragma mark Director Mac
65
66@implementation CCDirectorMac
67
68@synthesize isFullScreen = isFullScreen_;
69@synthesize originalWinSize = originalWinSize_;
70
71-(id) init
72{
73 if( (self = [super init]) ) {
74 isFullScreen_ = NO;
75 resizeMode_ = kCCDirectorResize_AutoScale;
76
77 originalWinSize_ = CGSizeZero;
78 fullScreenWindow_ = nil;
79 windowGLView_ = nil;
80 winOffset_ = CGPointZero;
81 }
82
83 return self;
84}
85
86- (void) dealloc
87{
88 [superViewGLView_ release];
89 [fullScreenWindow_ release];
90 [windowGLView_ release];
91 [super dealloc];
92}
93
94//
95// setFullScreen code taken from GLFullScreen example by Apple
96//
97- (void) setFullScreen:(BOOL)fullscreen
98{
99 // Mac OS X 10.6 and later offer a simplified mechanism to create full-screen contexts
100#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
101
102 if (isFullScreen_ == fullscreen) return;
103
104 if( fullscreen ) {
105 originalWinRect_ = [openGLView_ frame];
106
107 // Cache normal window and superview of openGLView
108 if(!windowGLView_)
109 windowGLView_ = [[openGLView_ window] retain];
110
111 [superViewGLView_ release];
112 superViewGLView_ = [[openGLView_ superview] retain];
113
114
115 // Get screen size
116 NSRect displayRect = [[NSScreen mainScreen] frame];
117
118 // Create a screen-sized window on the display you want to take over
119 fullScreenWindow_ = [[MacWindow alloc] initWithFrame:displayRect fullscreen:YES];
120
121 // Remove glView from window
122 [openGLView_ removeFromSuperview];
123
124 // Set new frame
125 [openGLView_ setFrame:displayRect];
126
127 // Attach glView to fullscreen window
128 [fullScreenWindow_ setContentView:openGLView_];
129
130 // Show the fullscreen window
131 [fullScreenWindow_ makeKeyAndOrderFront:self];
132 [fullScreenWindow_ makeMainWindow];
133
134 } else {
135
136 // Remove glView from fullscreen window
137 [openGLView_ removeFromSuperview];
138
139 // Release fullscreen window
140 [fullScreenWindow_ release];
141 fullScreenWindow_ = nil;
142
143 // Attach glView to superview
144 [superViewGLView_ addSubview:openGLView_];
145
146 // Set new frame
147 [openGLView_ setFrame:originalWinRect_];
148
149 // Show the window
150 [windowGLView_ makeKeyAndOrderFront:self];
151 [windowGLView_ makeMainWindow];
152 }
153 isFullScreen_ = fullscreen;
154
155 [openGLView_ retain]; // Retain +1
156
157 // re-configure glView
158 [self setOpenGLView:openGLView_];
159
160 [openGLView_ release]; // Retain -1
161
162 [openGLView_ setNeedsDisplay:YES];
163#else
164#error Full screen is not supported for Mac OS 10.5 or older yet
165#error If you don't want FullScreen support, you can safely remove these 2 lines
166#endif
167}
168
169-(void) setOpenGLView:(MacGLView *)view
170{
171 [super setOpenGLView:view];
172
173 // cache the NSWindow and NSOpenGLView created from the NIB
174 if( !isFullScreen_ && CGSizeEqualToSize(originalWinSize_, CGSizeZero))
175 {
176 originalWinSize_ = winSizeInPixels_;
177 }
178}
179
180-(int) resizeMode
181{
182 return resizeMode_;
183}
184
185-(void) setResizeMode:(int)mode
186{
187 if( mode != resizeMode_ ) {
188
189 resizeMode_ = mode;
190
191 [self setProjection:projection_];
192 [openGLView_ setNeedsDisplay: YES];
193 }
194}
195
196-(void) setProjection:(ccDirectorProjection)projection
197{
198 CGSize size = winSizeInPixels_;
199
200 CGPoint offset = CGPointZero;
201 float widthAspect = size.width;
202 float heightAspect = size.height;
203
204
205 if( resizeMode_ == kCCDirectorResize_AutoScale && ! CGSizeEqualToSize(originalWinSize_, CGSizeZero ) ) {
206
207 size = originalWinSize_;
208
209 float aspect = originalWinSize_.width / originalWinSize_.height;
210 widthAspect = winSizeInPixels_.width;
211 heightAspect = winSizeInPixels_.width / aspect;
212
213 if( heightAspect > winSizeInPixels_.height ) {
214 widthAspect = winSizeInPixels_.height * aspect;
215 heightAspect = winSizeInPixels_.height;
216 }
217
218 winOffset_.x = (winSizeInPixels_.width - widthAspect) / 2;
219 winOffset_.y = (winSizeInPixels_.height - heightAspect) / 2;
220
221 offset = winOffset_;
222
223 }
224
225 switch (projection) {
226 case kCCDirectorProjection2D:
227 glViewport(offset.x, offset.y, widthAspect, heightAspect);
228 glMatrixMode(GL_PROJECTION);
229 glLoadIdentity();
230 ccglOrtho(0, size.width, 0, size.height, -1024, 1024);
231 glMatrixMode(GL_MODELVIEW);
232 glLoadIdentity();
233 break;
234
235 case kCCDirectorProjection3D:
236 glViewport(offset.x, offset.y, widthAspect, heightAspect);
237 glMatrixMode(GL_PROJECTION);
238 glLoadIdentity();
239 gluPerspective(60, (GLfloat)widthAspect/heightAspect, 0.1f, 1500.0f);
240
241 glMatrixMode(GL_MODELVIEW);
242 glLoadIdentity();
243
244 float eyeZ = size.height * [self getZEye] / winSizeInPixels_.height;
245
246 gluLookAt( size.width/2, size.height/2, eyeZ,
247 size.width/2, size.height/2, 0,
248 0.0f, 1.0f, 0.0f);
249 break;
250
251 case kCCDirectorProjectionCustom:
252 if( projectionDelegate_ )
253 [projectionDelegate_ updateProjection];
254 break;
255
256 default:
257 CCLOG(@"cocos2d: Director: unrecognized projecgtion");
258 break;
259 }
260
261 projection_ = projection;
262}
263
264// If scaling is supported, then it should always return the original size
265// otherwise it should return the "real" size.
266-(CGSize) winSize
267{
268 if( resizeMode_ == kCCDirectorResize_AutoScale )
269 return originalWinSize_;
270
271 return winSizeInPixels_;
272}
273
274-(CGSize) winSizeInPixels
275{
276 return [self winSize];
277}
278
279- (CGPoint) convertToLogicalCoordinates:(CGPoint)coords
280{
281 CGPoint ret;
282
283 if( resizeMode_ == kCCDirectorResize_NoScale )
284 ret = coords;
285
286 else {
287
288 float x_diff = originalWinSize_.width / (winSizeInPixels_.width - winOffset_.x * 2);
289 float y_diff = originalWinSize_.height / (winSizeInPixels_.height - winOffset_.y * 2);
290
291 float adjust_x = (winSizeInPixels_.width * x_diff - originalWinSize_.width ) / 2;
292 float adjust_y = (winSizeInPixels_.height * y_diff - originalWinSize_.height ) / 2;
293
294 ret = CGPointMake( (x_diff * coords.x) - adjust_x, ( y_diff * coords.y ) - adjust_y );
295 }
296
297 return ret;
298}
299@end
300
301
302#pragma mark -
303#pragma mark DirectorDisplayLink
304
305
306@implementation CCDirectorDisplayLink
307
308- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
309{
310#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
311 if( ! runningThread_ )
312 runningThread_ = [NSThread currentThread];
313
314 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
315
316 [self drawScene];
317 [[CCEventDispatcher sharedDispatcher] dispatchQueuedEvents];
318
319 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:nil];
320
321 [pool release];
322
323#else
324 [self performSelector:@selector(drawScene) onThread:runningThread_ withObject:nil waitUntilDone:YES];
325#endif
326
327 return kCVReturnSuccess;
328}
329
330// This is the renderer output callback function
331static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
332{
333 CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime];
334 return result;
335}
336
337- (void) startAnimation
338{
339#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
340 runningThread_ = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil];
341 [runningThread_ start];
342#endif
343
344 gettimeofday( &lastUpdate_, NULL);
345
346 // Create a display link capable of being used with all active displays
347 CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
348
349 // Set the renderer output callback function
350 CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
351
352 // Set the display link for the current renderer
353 CGLContextObj cglContext = [[openGLView_ openGLContext] CGLContextObj];
354 CGLPixelFormatObj cglPixelFormat = [[openGLView_ pixelFormat] CGLPixelFormatObj];
355 CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
356
357 // Activate the display link
358 CVDisplayLinkStart(displayLink);
359}
360
361- (void) stopAnimation
362{
363 if( displayLink ) {
364 CVDisplayLinkStop(displayLink);
365 CVDisplayLinkRelease(displayLink);
366 displayLink = NULL;
367
368#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
369 [runningThread_ cancel];
370 [runningThread_ release];
371 runningThread_ = nil;
372#endif
373 }
374}
375
376-(void) dealloc
377{
378 if( displayLink ) {
379 CVDisplayLinkStop(displayLink);
380 CVDisplayLinkRelease(displayLink);
381 }
382 [super dealloc];
383}
384
385//
386// Mac Director has its own thread
387//
388-(void) mainLoop
389{
390 while( ![[NSThread currentThread] isCancelled] ) {
391 // There is no autorelease pool when this method is called because it will be called from a background thread
392 // It's important to create one or you will leak objects
393 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
394
395 [[NSRunLoop currentRunLoop] run];
396
397 [pool release];
398 }
399}
400
401//
402// Draw the Scene
403//
404- (void) drawScene
405{
406 // We draw on a secondary thread through the display link
407 // When resizing the view, -reshape is called automatically on the main thread
408 // Add a mutex around to avoid the threads accessing the context simultaneously when resizing
409 CGLLockContext([[openGLView_ openGLContext] CGLContextObj]);
410 [[openGLView_ openGLContext] makeCurrentContext];
411
412 /* calculate "global" dt */
413 [self calculateDeltaTime];
414
415 /* tick before glClear: issue #533 */
416 if( ! isPaused_ ) {
417 [[CCScheduler sharedScheduler] tick: dt];
418 }
419
420 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
421
422 /* to avoid flickr, nextScene MUST be here: after tick and before draw.
423 XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
424 if( nextScene_ )
425 [self setNextScene];
426
427 glPushMatrix();
428
429
430 // By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
431 CC_ENABLE_DEFAULT_GL_STATES();
432
433 /* draw the scene */
434 [runningScene_ visit];
435
436 /* draw the notification node */
437 [notificationNode_ visit];
438
439 if( displayFPS_ )
440 [self showFPS];
441
442#if CC_ENABLE_PROFILERS
443 [self showProfilers];
444#endif
445
446 CC_DISABLE_DEFAULT_GL_STATES();
447
448 glPopMatrix();
449
450 [[openGLView_ openGLContext] flushBuffer];
451 CGLUnlockContext([[openGLView_ openGLContext] CGLContextObj]);
452}
453
454// set the event dispatcher
455-(void) setOpenGLView:(MacGLView *)view
456{
457 if( view != openGLView_ ) {
458
459 [super setOpenGLView:view];
460
461 CCEventDispatcher *eventDispatcher = [CCEventDispatcher sharedDispatcher];
462 [openGLView_ setEventDelegate: eventDispatcher];
463 [eventDispatcher setDispatchEvents: YES];
464
465 // Enable Touches. Default no.
466 [view setAcceptsTouchEvents:NO];
467// [view setAcceptsTouchEvents:YES];
468
469
470 // Synchronize buffer swaps with vertical refresh rate
471 [[view openGLContext] makeCurrentContext];
472 GLint swapInt = 1;
473 [[view openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
474 }
475}
476
477@end
478
479#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h new file mode 100755 index 0000000..06889e8 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h
@@ -0,0 +1,277 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26// Only compile this code on Mac. These files should not be included on your iOS project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
31
32#import <Cocoa/Cocoa.h>
33
34#import "MacGLView.h"
35#import "../../Support/uthash.h" // hack: uthash needs to be imported before utlist to prevent warning
36#import "../../Support/utlist.h"
37#import "../../ccConfig.h"
38
39#pragma mark -
40#pragma mark CCMouseEventDelegate
41
42/** CCMouseEventDelegate protocol.
43 Implement it in your node to receive any of mouse events
44 */
45@protocol CCMouseEventDelegate <NSObject>
46@optional
47
48//
49// left
50//
51/** called when the "mouseDown" event is received.
52 Return YES to avoid propagating the event to other delegates.
53 */
54-(BOOL) ccMouseDown:(NSEvent*)event;
55
56/** called when the "mouseDragged" event is received.
57 Return YES to avoid propagating the event to other delegates.
58 */
59-(BOOL) ccMouseDragged:(NSEvent*)event;
60
61/** called when the "mouseMoved" event is received.
62 Return YES to avoid propagating the event to other delegates.
63 By default, "mouseMoved" is disabled. To enable it, send the "setAcceptsMouseMovedEvents:YES" message to the main window.
64 */
65-(BOOL) ccMouseMoved:(NSEvent*)event;
66
67/** called when the "mouseUp" event is received.
68 Return YES to avoid propagating the event to other delegates.
69 */
70-(BOOL) ccMouseUp:(NSEvent*)event;
71
72
73//
74// right
75//
76
77/** called when the "rightMouseDown" event is received.
78 Return YES to avoid propagating the event to other delegates.
79 */
80-(BOOL) ccRightMouseDown:(NSEvent*)event;
81
82/** called when the "rightMouseDragged" event is received.
83 Return YES to avoid propagating the event to other delegates.
84 */
85-(BOOL) ccRightMouseDragged:(NSEvent*)event;
86
87/** called when the "rightMouseUp" event is received.
88 Return YES to avoid propagating the event to other delegates.
89 */
90-(BOOL) ccRightMouseUp:(NSEvent*)event;
91
92//
93// other
94//
95
96/** called when the "otherMouseDown" event is received.
97 Return YES to avoid propagating the event to other delegates.
98 */
99-(BOOL) ccOtherMouseDown:(NSEvent*)event;
100
101/** called when the "otherMouseDragged" event is received.
102 Return YES to avoid propagating the event to other delegates.
103 */
104-(BOOL) ccOtherMouseDragged:(NSEvent*)event;
105
106/** called when the "otherMouseUp" event is received.
107 Return YES to avoid propagating the event to other delegates.
108 */
109-(BOOL) ccOtherMouseUp:(NSEvent*)event;
110
111//
112// scroll wheel
113//
114
115/** called when the "scrollWheel" event is received.
116 Return YES to avoid propagating the event to other delegates.
117 */
118- (BOOL)ccScrollWheel:(NSEvent *)theEvent;
119
120
121//
122// enter / exit
123//
124
125/** called when the "mouseEntered" event is received.
126 Return YES to avoid propagating the event to other delegates.
127 */
128- (void)ccMouseEntered:(NSEvent *)theEvent;
129
130/** called when the "mouseExited" event is received.
131 Return YES to avoid propagating the event to other delegates.
132 */
133- (void)ccMouseExited:(NSEvent *)theEvent;
134
135@end
136
137#pragma mark -
138#pragma mark CCKeyboardEventDelegate
139
140/** CCKeyboardEventDelegate protocol.
141 Implement it in your node to receive any of keyboard events
142 */
143@protocol CCKeyboardEventDelegate <NSObject>
144@optional
145/** called when the "keyUp" event is received.
146 Return YES to avoid propagating the event to other delegates.
147 */
148-(BOOL) ccKeyUp:(NSEvent*)event;
149
150/** called when the "keyDown" event is received.
151 Return YES to avoid propagating the event to other delegates.
152 */
153-(BOOL) ccKeyDown:(NSEvent*)event;
154/** called when the "flagsChanged" event is received.
155 Return YES to avoid propagating the event to other delegates.
156 */
157-(BOOL) ccFlagsChanged:(NSEvent*)event;
158@end
159
160#pragma mark -
161#pragma mark CCTouchEventDelegate
162
163/** CCTouchEventDelegate protocol.
164 Implement it in your node to receive any of touch events
165 */
166@protocol CCTouchEventDelegate <NSObject>
167@optional
168/** called when the "touchesBegan" event is received.
169 Return YES to avoid propagating the event to other delegates.
170 */
171- (BOOL)ccTouchesBeganWithEvent:(NSEvent *)event;
172
173/** called when the "touchesMoved" event is received.
174 Return YES to avoid propagating the event to other delegates.
175 */
176- (BOOL)ccTouchesMovedWithEvent:(NSEvent *)event;
177
178/** called when the "touchesEnded" event is received.
179 Return YES to avoid propagating the event to other delegates.
180 */
181- (BOOL)ccTouchesEndedWithEvent:(NSEvent *)event;
182
183/** called when the "touchesCancelled" event is received.
184 Return YES to avoid propagating the event to other delegates.
185 */
186- (BOOL)ccTouchesCancelledWithEvent:(NSEvent *)event;
187
188@end
189
190
191#pragma mark -
192#pragma mark CCEventDispatcher
193
194struct _listEntry;
195
196/** CCEventDispatcher
197
198 This is object is responsible for dispatching the events:
199 - Mouse events
200 - Keyboard events
201 - Touch events
202
203 Only available on Mac
204 */
205@interface CCEventDispatcher : NSObject <MacEventDelegate> {
206
207 BOOL dispatchEvents_;
208
209 struct _listEntry *keyboardDelegates_;
210 struct _listEntry *mouseDelegates_;
211 struct _listEntry *touchDelegates_;
212}
213
214@property (nonatomic, readwrite) BOOL dispatchEvents;
215
216
217/** CCEventDispatcher singleton */
218+(CCEventDispatcher*) sharedDispatcher;
219
220#pragma mark CCEventDispatcher - Mouse
221
222/** Adds a mouse delegate to the dispatcher's list.
223 Delegates with a lower priority value will be called before higher priority values.
224 All the events will be propgated to all the delegates, unless the one delegate returns YES.
225
226 IMPORTANT: The delegate will be retained.
227 */
228-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority;
229
230/** removes a mouse delegate */
231-(void) removeMouseDelegate:(id) delegate;
232
233/** Removes all mouse delegates, releasing all the delegates */
234-(void) removeAllMouseDelegates;
235
236#pragma mark CCEventDispatcher - Keyboard
237
238/** Adds a Keyboard delegate to the dispatcher's list.
239 Delegates with a lower priority value will be called before higher priority values.
240 All the events will be propgated to all the delegates, unless the one delegate returns YES.
241
242 IMPORTANT: The delegate will be retained.
243 */
244-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority;
245
246/** removes a mouse delegate */
247-(void) removeKeyboardDelegate:(id) delegate;
248
249/** Removes all mouse delegates, releasing all the delegates */
250-(void) removeAllKeyboardDelegates;
251
252#pragma mark CCEventDispatcher - Touches
253
254/** Adds a Touch delegate to the dispatcher's list.
255 Delegates with a lower priority value will be called before higher priority values.
256 All the events will be propgated to all the delegates, unless the one delegate returns YES.
257
258 IMPORTANT: The delegate will be retained.
259 */
260- (void)addTouchDelegate:(id<CCTouchEventDelegate>)delegate priority:(NSInteger)priority;
261
262/** Removes a touch delegate */
263- (void)removeTouchDelegate:(id) delegate;
264
265/** Removes all touch delegates, releasing all the delegates */
266- (void)removeAllTouchDelegates;
267
268#pragma mark CCEventDispatcher - Dispatch Events
269
270#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
271-(void) dispatchQueuedEvents;
272#endif
273
274@end
275
276
277#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m new file mode 100755 index 0000000..1d1740e --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m
@@ -0,0 +1,645 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26// Only compile this code on Mac. These files should not be included on your iOS project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
31
32#import "CCEventDispatcher.h"
33#import "../../ccConfig.h"
34
35static CCEventDispatcher *sharedDispatcher = nil;
36
37enum {
38 // mouse
39 kCCImplementsMouseDown = 1 << 0,
40 kCCImplementsMouseMoved = 1 << 1,
41 kCCImplementsMouseDragged = 1 << 2,
42 kCCImplementsMouseUp = 1 << 3,
43 kCCImplementsRightMouseDown = 1 << 4,
44 kCCImplementsRightMouseDragged = 1 << 5,
45 kCCImplementsRightMouseUp = 1 << 6,
46 kCCImplementsOtherMouseDown = 1 << 7,
47 kCCImplementsOtherMouseDragged = 1 << 8,
48 kCCImplementsOtherMouseUp = 1 << 9,
49 kCCImplementsScrollWheel = 1 << 10,
50 kCCImplementsMouseEntered = 1 << 11,
51 kCCImplementsMouseExited = 1 << 12,
52
53 kCCImplementsTouchesBegan = 1 << 13,
54 kCCImplementsTouchesMoved = 1 << 14,
55 kCCImplementsTouchesEnded = 1 << 15,
56 kCCImplementsTouchesCancelled = 1 << 16,
57
58 // keyboard
59 kCCImplementsKeyUp = 1 << 0,
60 kCCImplementsKeyDown = 1 << 1,
61 kCCImplementsFlagsChanged = 1 << 2,
62};
63
64
65typedef struct _listEntry
66{
67 struct _listEntry *prev, *next;
68 id delegate;
69 NSInteger priority;
70 NSUInteger flags;
71} tListEntry;
72
73
74#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
75
76#define QUEUE_EVENT_MAX 128
77struct _eventQueue {
78 SEL selector;
79 NSEvent *event;
80};
81
82static struct _eventQueue eventQueue[QUEUE_EVENT_MAX];
83static int eventQueueCount;
84
85#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
86
87
88@implementation CCEventDispatcher
89
90@synthesize dispatchEvents=dispatchEvents_;
91
92
93+(CCEventDispatcher*) sharedDispatcher
94{
95 @synchronized(self) {
96 if (sharedDispatcher == nil)
97 sharedDispatcher = [[self alloc] init]; // assignment not done here
98 }
99 return sharedDispatcher;
100}
101
102+(id) allocWithZone:(NSZone *)zone
103{
104 @synchronized(self) {
105 NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
106 return [super allocWithZone:zone];
107 }
108 return nil; // on subsequent allocation attempts return nil
109}
110
111-(id) init
112{
113 if( (self = [super init]) )
114 {
115 // events enabled by default
116 dispatchEvents_ = YES;
117
118 // delegates
119 keyboardDelegates_ = NULL;
120 mouseDelegates_ = NULL;
121 touchDelegates_ = NULL;
122
123#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
124 eventQueueCount = 0;
125#endif
126 }
127
128 return self;
129}
130
131- (void) dealloc
132{
133 [super dealloc];
134}
135
136#pragma mark CCEventDispatcher - add / remove delegates
137
138-(void) addDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list
139{
140 tListEntry *listElement = malloc( sizeof(*listElement) );
141
142 listElement->delegate = [delegate retain];
143 listElement->priority = priority;
144 listElement->flags = flags;
145 listElement->next = listElement->prev = NULL;
146
147 // empty list ?
148 if( ! *list ) {
149 DL_APPEND( *list, listElement );
150
151 } else {
152 BOOL added = NO;
153
154 for( tListEntry *elem = *list; elem ; elem = elem->next ) {
155 if( priority < elem->priority ) {
156
157 if( elem == *list )
158 DL_PREPEND(*list, listElement);
159 else {
160 listElement->next = elem;
161 listElement->prev = elem->prev;
162
163 elem->prev->next = listElement;
164 elem->prev = listElement;
165 }
166
167 added = YES;
168 break;
169 }
170 }
171
172 // Not added? priority has the higher value. Append it.
173 if( !added )
174 DL_APPEND(*list, listElement);
175 }
176}
177
178-(void) removeDelegate:(id)delegate fromList:(tListEntry**)list
179{
180 tListEntry *entry, *tmp;
181
182 // updates with priority < 0
183 DL_FOREACH_SAFE( *list, entry, tmp ) {
184 if( entry->delegate == delegate ) {
185 DL_DELETE( *list, entry );
186 [delegate release];
187 free(entry);
188 break;
189 }
190 }
191}
192
193-(void) removeAllDelegatesFromList:(tListEntry**)list
194{
195 tListEntry *entry, *tmp;
196
197 DL_FOREACH_SAFE( *list, entry, tmp ) {
198 DL_DELETE( *list, entry );
199 free(entry);
200 }
201}
202
203
204-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority
205{
206 NSUInteger flags = 0;
207
208 flags |= ( [delegate respondsToSelector:@selector(ccMouseDown:)] ? kCCImplementsMouseDown : 0 );
209 flags |= ( [delegate respondsToSelector:@selector(ccMouseDragged:)] ? kCCImplementsMouseDragged : 0 );
210 flags |= ( [delegate respondsToSelector:@selector(ccMouseMoved:)] ? kCCImplementsMouseMoved : 0 );
211 flags |= ( [delegate respondsToSelector:@selector(ccMouseUp:)] ? kCCImplementsMouseUp : 0 );
212
213 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDown:)] ? kCCImplementsRightMouseDown : 0 );
214 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDragged:)] ? kCCImplementsRightMouseDragged : 0 );
215 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseUp:)] ? kCCImplementsRightMouseUp : 0 );
216
217 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDown:)] ? kCCImplementsOtherMouseDown : 0 );
218 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDragged:)] ? kCCImplementsOtherMouseDragged : 0 );
219 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseUp:)] ? kCCImplementsOtherMouseUp : 0 );
220
221 flags |= ( [delegate respondsToSelector:@selector(ccMouseEntered:)] ? kCCImplementsMouseEntered : 0 );
222 flags |= ( [delegate respondsToSelector:@selector(ccMouseExited:)] ? kCCImplementsMouseExited : 0 );
223
224 flags |= ( [delegate respondsToSelector:@selector(ccScrollWheel:)] ? kCCImplementsScrollWheel : 0 );
225
226 [self addDelegate:delegate priority:priority flags:flags list:&mouseDelegates_];
227}
228
229-(void) removeMouseDelegate:(id) delegate
230{
231 [self removeDelegate:delegate fromList:&mouseDelegates_];
232}
233
234-(void) removeAllMouseDelegates
235{
236 [self removeAllDelegatesFromList:&mouseDelegates_];
237}
238
239-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority
240{
241 NSUInteger flags = 0;
242
243 flags |= ( [delegate respondsToSelector:@selector(ccKeyUp:)] ? kCCImplementsKeyUp : 0 );
244 flags |= ( [delegate respondsToSelector:@selector(ccKeyDown:)] ? kCCImplementsKeyDown : 0 );
245 flags |= ( [delegate respondsToSelector:@selector(ccFlagsChanged:)] ? kCCImplementsFlagsChanged : 0 );
246
247 [self addDelegate:delegate priority:priority flags:flags list:&keyboardDelegates_];
248}
249
250-(void) removeKeyboardDelegate:(id) delegate
251{
252 [self removeDelegate:delegate fromList:&keyboardDelegates_];
253}
254
255-(void) removeAllKeyboardDelegates
256{
257 [self removeAllDelegatesFromList:&keyboardDelegates_];
258}
259
260-(void) addTouchDelegate:(id<CCTouchEventDelegate>) delegate priority:(NSInteger)priority
261{
262 NSUInteger flags = 0;
263
264 flags |= ( [delegate respondsToSelector:@selector(ccTouchesBeganWithEvent:)] ? kCCImplementsTouchesBegan : 0 );
265 flags |= ( [delegate respondsToSelector:@selector(ccTouchesMovedWithEvent:)] ? kCCImplementsTouchesMoved : 0 );
266 flags |= ( [delegate respondsToSelector:@selector(ccTouchesEndedWithEvent:)] ? kCCImplementsTouchesEnded : 0 );
267 flags |= ( [delegate respondsToSelector:@selector(ccTouchesCancelledWithEvent:)] ? kCCImplementsTouchesCancelled : 0 );
268
269 [self addDelegate:delegate priority:priority flags:flags list:&touchDelegates_];
270}
271
272-(void) removeTouchDelegate:(id) delegate
273{
274 [self removeDelegate:delegate fromList:&touchDelegates_];
275}
276
277-(void) removeAllTouchDelegates
278{
279 [self removeAllDelegatesFromList:&touchDelegates_];
280}
281
282
283#pragma mark CCEventDispatcher - Mouse events
284//
285// Mouse events
286//
287
288//
289// Left
290//
291- (void)mouseDown:(NSEvent *)event
292{
293 if( dispatchEvents_ ) {
294 tListEntry *entry, *tmp;
295
296 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
297 if ( entry->flags & kCCImplementsMouseDown ) {
298 void *swallows = [entry->delegate performSelector:@selector(ccMouseDown:) withObject:event];
299 if( swallows )
300 break;
301 }
302 }
303 }
304}
305
306- (void)mouseMoved:(NSEvent *)event
307{
308 if( dispatchEvents_ ) {
309 tListEntry *entry, *tmp;
310
311 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
312 if ( entry->flags & kCCImplementsMouseMoved ) {
313 void *swallows = [entry->delegate performSelector:@selector(ccMouseMoved:) withObject:event];
314 if( swallows )
315 break;
316 }
317 }
318 }
319}
320
321- (void)mouseDragged:(NSEvent *)event
322{
323 if( dispatchEvents_ ) {
324 tListEntry *entry, *tmp;
325
326 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
327 if ( entry->flags & kCCImplementsMouseDragged ) {
328 void *swallows = [entry->delegate performSelector:@selector(ccMouseDragged:) withObject:event];
329 if( swallows )
330 break;
331 }
332 }
333 }
334}
335
336- (void)mouseUp:(NSEvent *)event
337{
338 if( dispatchEvents_ ) {
339 tListEntry *entry, *tmp;
340
341 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
342 if ( entry->flags & kCCImplementsMouseUp ) {
343 void *swallows = [entry->delegate performSelector:@selector(ccMouseUp:) withObject:event];
344 if( swallows )
345 break;
346 }
347 }
348 }
349}
350
351//
352// Mouse Right
353//
354- (void)rightMouseDown:(NSEvent *)event
355{
356 if( dispatchEvents_ ) {
357 tListEntry *entry, *tmp;
358
359 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
360 if ( entry->flags & kCCImplementsRightMouseDown ) {
361 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDown:) withObject:event];
362 if( swallows )
363 break;
364 }
365 }
366 }
367}
368
369- (void)rightMouseDragged:(NSEvent *)event
370{
371 if( dispatchEvents_ ) {
372 tListEntry *entry, *tmp;
373
374 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
375 if ( entry->flags & kCCImplementsRightMouseDragged ) {
376 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDragged:) withObject:event];
377 if( swallows )
378 break;
379 }
380 }
381 }
382}
383
384- (void)rightMouseUp:(NSEvent *)event
385{
386 if( dispatchEvents_ ) {
387 tListEntry *entry, *tmp;
388
389 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
390 if ( entry->flags & kCCImplementsRightMouseUp ) {
391 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseUp:) withObject:event];
392 if( swallows )
393 break;
394 }
395 }
396 }
397}
398
399//
400// Mouse Other
401//
402- (void)otherMouseDown:(NSEvent *)event
403{
404 if( dispatchEvents_ ) {
405 tListEntry *entry, *tmp;
406
407 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
408 if ( entry->flags & kCCImplementsOtherMouseDown ) {
409 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDown:) withObject:event];
410 if( swallows )
411 break;
412 }
413 }
414 }
415}
416
417- (void)otherMouseDragged:(NSEvent *)event
418{
419 if( dispatchEvents_ ) {
420 tListEntry *entry, *tmp;
421
422 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
423 if ( entry->flags & kCCImplementsOtherMouseDragged ) {
424 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDragged:) withObject:event];
425 if( swallows )
426 break;
427 }
428 }
429 }
430}
431
432- (void)otherMouseUp:(NSEvent *)event
433{
434 if( dispatchEvents_ ) {
435 tListEntry *entry, *tmp;
436
437 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
438 if ( entry->flags & kCCImplementsOtherMouseUp ) {
439 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseUp:) withObject:event];
440 if( swallows )
441 break;
442 }
443 }
444 }
445}
446
447//
448// Scroll Wheel
449//
450- (void)scrollWheel:(NSEvent *)event
451{
452 if( dispatchEvents_ ) {
453 tListEntry *entry, *tmp;
454
455 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
456 if ( entry->flags & kCCImplementsScrollWheel ) {
457 void *swallows = [entry->delegate performSelector:@selector(ccScrollWheel:) withObject:event];
458 if( swallows )
459 break;
460 }
461 }
462 }
463}
464
465//
466// Mouse enter / exit
467- (void)mouseExited:(NSEvent *)event
468{
469 if( dispatchEvents_ ) {
470 tListEntry *entry, *tmp;
471
472 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
473 if ( entry->flags & kCCImplementsMouseEntered ) {
474 void *swallows = [entry->delegate performSelector:@selector(ccMouseEntered:) withObject:event];
475 if( swallows )
476 break;
477 }
478 }
479 }
480}
481
482- (void)mouseEntered:(NSEvent *)event
483{
484 if( dispatchEvents_ ) {
485 tListEntry *entry, *tmp;
486
487 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
488 if ( entry->flags & kCCImplementsMouseExited) {
489 void *swallows = [entry->delegate performSelector:@selector(ccMouseExited:) withObject:event];
490 if( swallows )
491 break;
492 }
493 }
494 }
495}
496
497
498#pragma mark CCEventDispatcher - Keyboard events
499
500// Keyboard events
501- (void)keyDown:(NSEvent *)event
502{
503 if( dispatchEvents_ ) {
504 tListEntry *entry, *tmp;
505
506 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
507 if ( entry->flags & kCCImplementsKeyDown ) {
508 void *swallows = [entry->delegate performSelector:@selector(ccKeyDown:) withObject:event];
509 if( swallows )
510 break;
511 }
512 }
513 }
514}
515
516- (void)keyUp:(NSEvent *)event
517{
518 if( dispatchEvents_ ) {
519 tListEntry *entry, *tmp;
520
521 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
522 if ( entry->flags & kCCImplementsKeyUp ) {
523 void *swallows = [entry->delegate performSelector:@selector(ccKeyUp:) withObject:event];
524 if( swallows )
525 break;
526 }
527 }
528 }
529}
530
531- (void)flagsChanged:(NSEvent *)event
532{
533 if( dispatchEvents_ ) {
534 tListEntry *entry, *tmp;
535
536 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
537 if ( entry->flags & kCCImplementsFlagsChanged ) {
538 void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event];
539 if( swallows )
540 break;
541 }
542 }
543 }
544}
545
546
547#pragma mark CCEventDispatcher - Touch events
548
549- (void)touchesBeganWithEvent:(NSEvent *)event
550{
551 if( dispatchEvents_ ) {
552 tListEntry *entry, *tmp;
553
554 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) {
555 if ( entry->flags & kCCImplementsTouchesBegan) {
556 void *swallows = [entry->delegate performSelector:@selector(ccTouchesBeganWithEvent:) withObject:event];
557 if( swallows )
558 break;
559 }
560 }
561 }
562}
563
564- (void)touchesMovedWithEvent:(NSEvent *)event
565{
566 if( dispatchEvents_ ) {
567 tListEntry *entry, *tmp;
568
569 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) {
570 if ( entry->flags & kCCImplementsTouchesMoved) {
571 void *swallows = [entry->delegate performSelector:@selector(ccTouchesMovedWithEvent:) withObject:event];
572 if( swallows )
573 break;
574 }
575 }
576 }
577}
578
579- (void)touchesEndedWithEvent:(NSEvent *)event
580{
581 if( dispatchEvents_ ) {
582 tListEntry *entry, *tmp;
583
584 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) {
585 if ( entry->flags & kCCImplementsTouchesEnded) {
586 void *swallows = [entry->delegate performSelector:@selector(ccTouchesEndedWithEvent:) withObject:event];
587 if( swallows )
588 break;
589 }
590 }
591 }
592}
593
594- (void)touchesCancelledWithEvent:(NSEvent *)event
595{
596 if( dispatchEvents_ ) {
597 tListEntry *entry, *tmp;
598
599 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) {
600 if ( entry->flags & kCCImplementsTouchesCancelled) {
601 void *swallows = [entry->delegate performSelector:@selector(ccTouchesCancelledWithEvent:) withObject:event];
602 if( swallows )
603 break;
604 }
605 }
606 }
607}
608
609
610#pragma mark CCEventDispatcher - queue events
611
612#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
613-(void) queueEvent:(NSEvent*)event selector:(SEL)selector
614{
615 NSAssert( eventQueueCount < QUEUE_EVENT_MAX, @"CCEventDispatcher: recompile. Increment QUEUE_EVENT_MAX value");
616
617 @synchronized (self) {
618 eventQueue[eventQueueCount].selector = selector;
619 eventQueue[eventQueueCount].event = [event copy];
620
621 eventQueueCount++;
622 }
623}
624
625-(void) dispatchQueuedEvents
626{
627 @synchronized (self) {
628 for( int i=0; i < eventQueueCount; i++ ) {
629 SEL sel = eventQueue[i].selector;
630 NSEvent *event = eventQueue[i].event;
631
632 [self performSelector:sel withObject:event];
633
634 [event release];
635 }
636
637 eventQueueCount = 0;
638 }
639}
640#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
641
642
643@end
644
645#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/Mac/MacGLView.h b/libs/cocos2d/Platforms/Mac/MacGLView.h new file mode 100755 index 0000000..8099273 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/MacGLView.h
@@ -0,0 +1,89 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26// Only compile this code on Mac. These files should not be included on your iOS project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
31
32#import <Cocoa/Cocoa.h>
33
34#import "../../ccConfig.h"
35
36//PROTOCOLS:
37
38@protocol MacEventDelegate <NSObject>
39// Mouse
40- (void)mouseDown:(NSEvent *)theEvent;
41- (void)mouseUp:(NSEvent *)theEvent;
42- (void)mouseMoved:(NSEvent *)theEvent;
43- (void)mouseDragged:(NSEvent *)theEvent;
44- (void)rightMouseDown:(NSEvent*)event;
45- (void)rightMouseDragged:(NSEvent*)event;
46- (void)rightMouseUp:(NSEvent*)event;
47- (void)otherMouseDown:(NSEvent*)event;
48- (void)otherMouseDragged:(NSEvent*)event;
49- (void)otherMouseUp:(NSEvent*)event;
50- (void)scrollWheel:(NSEvent *)theEvent;
51- (void)mouseEntered:(NSEvent *)theEvent;
52- (void)mouseExited:(NSEvent *)theEvent;
53
54
55// Keyboard
56- (void)keyDown:(NSEvent *)theEvent;
57- (void)keyUp:(NSEvent *)theEvent;
58- (void)flagsChanged:(NSEvent *)theEvent;
59
60// Touches
61- (void)touchesBeganWithEvent:(NSEvent *)event;
62- (void)touchesMovedWithEvent:(NSEvent *)event;
63- (void)touchesEndedWithEvent:(NSEvent *)event;
64- (void)touchesCancelledWithEvent:(NSEvent *)event;
65
66#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
67- (void)queueEvent:(NSEvent*)event selector:(SEL)selector;
68#endif
69
70@end
71
72/** MacGLView
73
74 Only available for Mac OS X
75 */
76@interface MacGLView : NSOpenGLView {
77 id<MacEventDelegate> eventDelegate_;
78}
79
80@property (nonatomic, readwrite, assign) id<MacEventDelegate> eventDelegate;
81
82// initializes the MacGLView with a frame rect and an OpenGL context
83- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context;
84
85// private
86+(void) load_;
87@end
88
89#endif // __MAC_OS_X_VERSION_MAX_ALLOWED \ No newline at end of file
diff --git a/libs/cocos2d/Platforms/Mac/MacGLView.m b/libs/cocos2d/Platforms/Mac/MacGLView.m new file mode 100755 index 0000000..a041dc8 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/MacGLView.m
@@ -0,0 +1,242 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26/*
27 * Idea of subclassing NSOpenGLView was taken from "TextureUpload" Apple's sample
28 */
29
30// Only compile this code on Mac. These files should not be included on your iOS project.
31// But in case they are included, it won't be compiled.
32#import <Availability.h>
33#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
34#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
35
36#import "MacGLView.h"
37#import <OpenGL/gl.h>
38
39#import "CCDirectorMac.h"
40#import "../../ccConfig.h"
41
42
43@implementation MacGLView
44
45@synthesize eventDelegate = eventDelegate_;
46
47+(void) load_
48{
49 NSLog(@"%@ loaded", self);
50}
51
52- (id) initWithFrame:(NSRect)frameRect
53{
54 self = [self initWithFrame:frameRect shareContext:nil];
55 return self;
56}
57
58- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context
59{
60 NSOpenGLPixelFormatAttribute attribs[] =
61 {
62 NSOpenGLPFAAccelerated,
63 NSOpenGLPFANoRecovery,
64 NSOpenGLPFADoubleBuffer,
65 NSOpenGLPFADepthSize, 24,
66
67 0
68 };
69
70 NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
71
72 if (!pixelFormat)
73 NSLog(@"No OpenGL pixel format");
74
75 if( (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) ) {
76
77 if( context )
78 [self setOpenGLContext:context];
79
80 // Synchronize buffer swaps with vertical refresh rate
81 GLint swapInt = 1;
82 [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
83
84// GLint order = -1;
85// [[self openGLContext] setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
86
87 // event delegate
88 eventDelegate_ = nil;
89 }
90
91 return self;
92}
93
94- (void) reshape
95{
96 // We draw on a secondary thread through the display link
97 // When resizing the view, -reshape is called automatically on the main thread
98 // Add a mutex around to avoid the threads accessing the context simultaneously when resizing
99 CGLLockContext([[self openGLContext] CGLContextObj]);
100
101 NSRect rect = [self bounds];
102
103 CCDirector *director = [CCDirector sharedDirector];
104 [director reshapeProjection: NSSizeToCGSize(rect.size) ];
105
106 // avoid flicker
107 [director drawScene];
108// [self setNeedsDisplay:YES];
109
110 CGLUnlockContext([[self openGLContext] CGLContextObj]);
111}
112
113- (void) dealloc
114{
115
116 [super dealloc];
117}
118
119#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
120#define DISPATCH_EVENT(__event__, __selector__) [eventDelegate_ queueEvent:__event__ selector:__selector__];
121#else
122#define DISPATCH_EVENT(__event__, __selector__) \
123 id obj = eventDelegate_; \
124 [obj performSelector:__selector__ \
125 onThread:[(CCDirectorMac*)[CCDirector sharedDirector] runningThread] \
126 withObject:__event__ \
127 waitUntilDone:NO];
128#endif
129
130#pragma mark MacGLView - Mouse events
131- (void)mouseDown:(NSEvent *)theEvent
132{
133 DISPATCH_EVENT(theEvent, _cmd);
134}
135
136- (void)mouseMoved:(NSEvent *)theEvent
137{
138 DISPATCH_EVENT(theEvent, _cmd);
139}
140
141- (void)mouseDragged:(NSEvent *)theEvent
142{
143 DISPATCH_EVENT(theEvent, _cmd);
144}
145
146- (void)mouseUp:(NSEvent *)theEvent
147{
148 DISPATCH_EVENT(theEvent, _cmd);
149}
150
151- (void)rightMouseDown:(NSEvent *)theEvent {
152 DISPATCH_EVENT(theEvent, _cmd);
153}
154
155- (void)rightMouseDragged:(NSEvent *)theEvent {
156 DISPATCH_EVENT(theEvent, _cmd);
157}
158
159- (void)rightMouseUp:(NSEvent *)theEvent {
160 DISPATCH_EVENT(theEvent, _cmd);
161}
162
163- (void)otherMouseDown:(NSEvent *)theEvent {
164 DISPATCH_EVENT(theEvent, _cmd);
165}
166
167- (void)otherMouseDragged:(NSEvent *)theEvent {
168 DISPATCH_EVENT(theEvent, _cmd);
169}
170
171- (void)otherMouseUp:(NSEvent *)theEvent {
172 DISPATCH_EVENT(theEvent, _cmd);
173}
174
175- (void)mouseEntered:(NSEvent *)theEvent {
176 DISPATCH_EVENT(theEvent, _cmd);
177}
178
179- (void)mouseExited:(NSEvent *)theEvent {
180 DISPATCH_EVENT(theEvent, _cmd);
181}
182
183-(void) scrollWheel:(NSEvent *)theEvent {
184 DISPATCH_EVENT(theEvent, _cmd);
185}
186
187#pragma mark MacGLView - Key events
188
189-(BOOL) becomeFirstResponder
190{
191 return YES;
192}
193
194-(BOOL) acceptsFirstResponder
195{
196 return YES;
197}
198
199-(BOOL) resignFirstResponder
200{
201 return YES;
202}
203
204- (void)keyDown:(NSEvent *)theEvent
205{
206 DISPATCH_EVENT(theEvent, _cmd);
207}
208
209- (void)keyUp:(NSEvent *)theEvent
210{
211 DISPATCH_EVENT(theEvent, _cmd);
212}
213
214- (void)flagsChanged:(NSEvent *)theEvent
215{
216 DISPATCH_EVENT(theEvent, _cmd);
217}
218
219#pragma mark MacGLView - Touch events
220- (void)touchesBeganWithEvent:(NSEvent *)theEvent
221{
222 DISPATCH_EVENT(theEvent, _cmd);
223}
224
225- (void)touchesMovedWithEvent:(NSEvent *)theEvent
226{
227 DISPATCH_EVENT(theEvent, _cmd);
228}
229
230- (void)touchesEndedWithEvent:(NSEvent *)theEvent
231{
232 DISPATCH_EVENT(theEvent, _cmd);
233}
234
235- (void)touchesCancelledWithEvent:(NSEvent *)theEvent
236{
237 DISPATCH_EVENT(theEvent, _cmd);
238}
239
240@end
241
242#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/Mac/MacWindow.h b/libs/cocos2d/Platforms/Mac/MacWindow.h new file mode 100755 index 0000000..716fe9b --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/MacWindow.h
@@ -0,0 +1,42 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25// Only compile this code on Mac. These files should not be included on your iOS project.
26// But in case they are included, it won't be compiled.
27#import <Availability.h>
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
30
31#import <Cocoa/Cocoa.h>
32
33
34@interface MacWindow : NSWindow
35{
36}
37- (id) initWithFrame:(NSRect)frame fullscreen:(BOOL)fullscreen;
38
39@end
40
41
42#endif // __MAC_OS_X_VERSION_MAX_ALLOWED \ No newline at end of file
diff --git a/libs/cocos2d/Platforms/Mac/MacWindow.m b/libs/cocos2d/Platforms/Mac/MacWindow.m new file mode 100755 index 0000000..28736a3 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/MacWindow.m
@@ -0,0 +1,70 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25// Only compile this code on Mac. These files should not be included on your iOS project.
26// But in case they are included, it won't be compiled.
27#import <Availability.h>
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
30
31#import "MacWindow.h"
32
33
34@implementation MacWindow
35
36- (id) initWithFrame:(NSRect)frame fullscreen:(BOOL)fullscreen
37{
38 int styleMask = fullscreen ? NSBackingStoreBuffered : ( NSTitledWindowMask | NSClosableWindowMask );
39 self = [self initWithContentRect:frame
40 styleMask:styleMask
41 backing:NSBackingStoreBuffered
42 defer:YES];
43
44 if (self != nil)
45 {
46 if(fullscreen)
47 {
48 [self setLevel:NSMainMenuWindowLevel+1];
49 [self setHidesOnDeactivate:YES];
50 [self setHasShadow:NO];
51 }
52
53 [self setAcceptsMouseMovedEvents:NO];
54 [self setOpaque:YES];
55 }
56 return self;
57}
58
59- (BOOL) canBecomeKeyWindow
60{
61 return YES;
62}
63
64- (BOOL) canBecomeMainWindow
65{
66 return YES;
67}
68@end
69
70#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h new file mode 100755 index 0000000..1c264e4 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h
@@ -0,0 +1,255 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27// Only compile this code on iOS. These files should NOT be included on your Mac project.
28// But in case they are included, it won't be compiled.
29#import <Availability.h>
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31
32#import "../../CCDirector.h"
33
34/** @typedef ccDeviceOrientation
35 Possible device orientations
36 */
37typedef enum {
38 /// Device oriented vertically, home button on the bottom
39 kCCDeviceOrientationPortrait = UIDeviceOrientationPortrait,
40 /// Device oriented vertically, home button on the top
41 kCCDeviceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
42 /// Device oriented horizontally, home button on the right
43 kCCDeviceOrientationLandscapeLeft = UIDeviceOrientationLandscapeLeft,
44 /// Device oriented horizontally, home button on the left
45 kCCDeviceOrientationLandscapeRight = UIDeviceOrientationLandscapeRight,
46
47 // Backward compatibility stuff
48 CCDeviceOrientationPortrait = kCCDeviceOrientationPortrait,
49 CCDeviceOrientationPortraitUpsideDown = kCCDeviceOrientationPortraitUpsideDown,
50 CCDeviceOrientationLandscapeLeft = kCCDeviceOrientationLandscapeLeft,
51 CCDeviceOrientationLandscapeRight = kCCDeviceOrientationLandscapeRight,
52} ccDeviceOrientation;
53
54/** @typedef ccDirectorType
55 Possible Director Types.
56 @since v0.8.2
57 */
58typedef enum {
59 /** Will use a Director that triggers the main loop from an NSTimer object
60 *
61 * Features and Limitations:
62 * - Integrates OK with UIKit objects
63 * - It the slowest director
64 * - The invertal update is customizable from 1 to 60
65 */
66 kCCDirectorTypeNSTimer,
67
68 /** will use a Director that triggers the main loop from a custom main loop.
69 *
70 * Features and Limitations:
71 * - Faster than NSTimer Director
72 * - It doesn't integrate well with UIKit objecgts
73 * - The interval update can't be customizable
74 */
75 kCCDirectorTypeMainLoop,
76
77 /** Will use a Director that triggers the main loop from a thread, but the main loop will be executed on the main thread.
78 *
79 * Features and Limitations:
80 * - Faster than NSTimer Director
81 * - It doesn't integrate well with UIKit objecgts
82 * - The interval update can't be customizable
83 */
84 kCCDirectorTypeThreadMainLoop,
85
86 /** Will use a Director that synchronizes timers with the refresh rate of the display.
87 *
88 * Features and Limitations:
89 * - Faster than NSTimer Director
90 * - Only available on 3.1+
91 * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
92 * - Integrates OK with UIKit objects
93 * - The interval update can be 1/60, 1/30, 1/15
94 */
95 kCCDirectorTypeDisplayLink,
96
97 /** Default director is the NSTimer directory */
98 kCCDirectorTypeDefault = kCCDirectorTypeNSTimer,
99
100 // backward compatibility stuff
101 CCDirectorTypeNSTimer = kCCDirectorTypeNSTimer,
102 CCDirectorTypeMainLoop = kCCDirectorTypeMainLoop,
103 CCDirectorTypeThreadMainLoop = kCCDirectorTypeThreadMainLoop,
104 CCDirectorTypeDisplayLink = kCCDirectorTypeDisplayLink,
105 CCDirectorTypeDefault = kCCDirectorTypeDefault,
106
107
108} ccDirectorType;
109
110/** CCDirector extensions for iPhone
111 */
112@interface CCDirector (iOSExtension)
113
114// rotates the screen if an orientation differnent than Portrait is used
115-(void) applyOrientation;
116
117/** Sets the device orientation.
118 If the orientation is going to be controlled by an UIViewController, then the orientation should be Portrait
119 */
120-(void) setDeviceOrientation:(ccDeviceOrientation)orientation;
121
122/** returns the device orientation */
123-(ccDeviceOrientation) deviceOrientation;
124
125/** The size in pixels of the surface. It could be different than the screen size.
126 High-res devices might have a higher surface size than the screen size.
127 In non High-res device the contentScale will be emulated.
128
129 The recommend way to enable Retina Display is by using the "enableRetinaDisplay:(BOOL)enabled" method.
130
131 @since v0.99.4
132 */
133-(void) setContentScaleFactor:(CGFloat)scaleFactor;
134
135/** Will enable Retina Display on devices that supports it.
136 It will enable Retina Display on iPhone4 and iPod Touch 4.
137 It will return YES, if it could enabled it, otherwise it will return NO.
138
139 This is the recommened way to enable Retina Display.
140 @since v0.99.5
141 */
142-(BOOL) enableRetinaDisplay:(BOOL)yes;
143
144
145/** returns the content scale factor */
146-(CGFloat) contentScaleFactor;
147@end
148
149@interface CCDirector (iOSExtensionClassMethods)
150
151/** There are 4 types of Director.
152 - kCCDirectorTypeNSTimer (default)
153 - kCCDirectorTypeMainLoop
154 - kCCDirectorTypeThreadMainLoop
155 - kCCDirectorTypeDisplayLink
156
157 Each Director has it's own benefits, limitations.
158 If you are using SDK 3.1 or newer it is recommed to use the DisplayLink director
159
160 This method should be called before any other call to the director.
161
162 It will return NO if the director type is kCCDirectorTypeDisplayLink and the running SDK is < 3.1. Otherwise it will return YES.
163
164 @since v0.8.2
165 */
166+(BOOL) setDirectorType:(ccDirectorType) directorType;
167@end
168
169#pragma mark -
170#pragma mark CCDirectorIOS
171
172/** CCDirectorIOS: Base class of iOS directors
173 @since v0.99.5
174 */
175@interface CCDirectorIOS : CCDirector
176{
177 /* orientation */
178 ccDeviceOrientation deviceOrientation_;
179
180 /* contentScaleFactor could be simulated */
181 BOOL isContentScaleSupported_;
182
183}
184@end
185
186/** FastDirector is a Director that triggers the main loop as fast as possible.
187 *
188 * Features and Limitations:
189 * - Faster than "normal" director
190 * - Consumes more battery than the "normal" director
191 * - It has some issues while using UIKit objects
192 */
193@interface CCDirectorFast : CCDirectorIOS
194{
195 BOOL isRunning;
196
197 NSAutoreleasePool *autoreleasePool;
198}
199-(void) mainLoop;
200@end
201
202/** ThreadedFastDirector is a Director that triggers the main loop from a thread.
203 *
204 * Features and Limitations:
205 * - Faster than "normal" director
206 * - Consumes more battery than the "normal" director
207 * - It can be used with UIKit objects
208 *
209 * @since v0.8.2
210 */
211@interface CCDirectorFastThreaded : CCDirectorIOS
212{
213 BOOL isRunning;
214}
215-(void) mainLoop;
216@end
217
218/** DisplayLinkDirector is a Director that synchronizes timers with the refresh rate of the display.
219 *
220 * Features and Limitations:
221 * - Only available on 3.1+
222 * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
223 * - Only supports animation intervals of 1/60 1/30 & 1/15
224 *
225 * It is the recommended Director if the SDK is 3.1 or newer
226 *
227 * @since v0.8.2
228 */
229@interface CCDirectorDisplayLink : CCDirectorIOS
230{
231 id displayLink;
232}
233-(void) mainLoop:(id)sender;
234@end
235
236/** TimerDirector is a Director that calls the main loop from an NSTimer object
237 *
238 * Features and Limitations:
239 * - Integrates OK with UIKit objects
240 * - It the slowest director
241 * - The invertal update is customizable from 1 to 60
242 *
243 * It is the default Director.
244 */
245@interface CCDirectorTimer : CCDirectorIOS
246{
247 NSTimer *animationTimer;
248}
249-(void) mainLoop;
250@end
251
252// optimization. Should only be used to read it. Never to write it.
253extern CGFloat __ccContentScaleFactor;
254
255#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m new file mode 100755 index 0000000..c483665 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m
@@ -0,0 +1,735 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27// Only compile this code on iOS. These files should NOT be included on your Mac project.
28// But in case they are included, it won't be compiled.
29#import <Availability.h>
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31
32#import <unistd.h>
33
34// cocos2d imports
35#import "CCDirectorIOS.h"
36#import "CCTouchDelegateProtocol.h"
37#import "CCTouchDispatcher.h"
38#import "../../CCScheduler.h"
39#import "../../CCActionManager.h"
40#import "../../CCTextureCache.h"
41#import "../../ccMacros.h"
42#import "../../CCScene.h"
43
44// support imports
45#import "glu.h"
46#import "../../Support/OpenGL_Internal.h"
47#import "../../Support/CGPointExtension.h"
48
49#import "CCLayer.h"
50
51#if CC_ENABLE_PROFILERS
52#import "../../Support/CCProfiling.h"
53#endif
54
55
56#pragma mark -
57#pragma mark Director - global variables (optimization)
58
59CGFloat __ccContentScaleFactor = 1;
60
61#pragma mark -
62#pragma mark Director iOS
63
64@interface CCDirector ()
65-(void) setNextScene;
66-(void) showFPS;
67-(void) calculateDeltaTime;
68@end
69
70@implementation CCDirector (iOSExtensionClassMethods)
71
72+(Class) defaultDirector
73{
74 return [CCDirectorTimer class];
75}
76
77+ (BOOL) setDirectorType:(ccDirectorType)type
78{
79 if( type == CCDirectorTypeDisplayLink ) {
80 NSString *reqSysVer = @"3.1";
81 NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
82
83 if([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
84 return NO;
85 }
86 switch (type) {
87 case CCDirectorTypeNSTimer:
88 [CCDirectorTimer sharedDirector];
89 break;
90 case CCDirectorTypeDisplayLink:
91 [CCDirectorDisplayLink sharedDirector];
92 break;
93 case CCDirectorTypeMainLoop:
94 [CCDirectorFast sharedDirector];
95 break;
96 case CCDirectorTypeThreadMainLoop:
97 [CCDirectorFastThreaded sharedDirector];
98 break;
99 default:
100 NSAssert(NO,@"Unknown director type");
101 }
102
103 return YES;
104}
105
106@end
107
108
109
110#pragma mark -
111#pragma mark CCDirectorIOS
112
113@interface CCDirectorIOS ()
114-(void) updateContentScaleFactor;
115
116@end
117
118@implementation CCDirectorIOS
119
120- (id) init
121{
122 if( (self=[super init]) ) {
123
124 // portrait mode default
125 deviceOrientation_ = CCDeviceOrientationPortrait;
126
127 __ccContentScaleFactor = 1;
128 isContentScaleSupported_ = NO;
129
130 // running thread is main thread on iOS
131 runningThread_ = [NSThread currentThread];
132 }
133
134 return self;
135}
136
137- (void) dealloc
138{
139 [super dealloc];
140}
141
142//
143// Draw the Scene
144//
145- (void) drawScene
146{
147 /* calculate "global" dt */
148 [self calculateDeltaTime];
149
150 /* tick before glClear: issue #533 */
151 if( ! isPaused_ ) {
152 [[CCScheduler sharedScheduler] tick: dt];
153 }
154
155 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
156
157 /* to avoid flickr, nextScene MUST be here: after tick and before draw.
158 XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
159 if( nextScene_ )
160 [self setNextScene];
161
162 glPushMatrix();
163
164 [self applyOrientation];
165
166 // By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
167 CC_ENABLE_DEFAULT_GL_STATES();
168
169 /* draw the scene */
170 [runningScene_ visit];
171
172 /* draw the notification node */
173 [notificationNode_ visit];
174
175 if( displayFPS_ )
176 [self showFPS];
177
178#if CC_ENABLE_PROFILERS
179 [self showProfilers];
180#endif
181
182 CC_DISABLE_DEFAULT_GL_STATES();
183
184 glPopMatrix();
185
186 [openGLView_ swapBuffers];
187}
188
189-(void) setProjection:(ccDirectorProjection)projection
190{
191 CGSize size = winSizeInPixels_;
192
193 switch (projection) {
194 case kCCDirectorProjection2D:
195 glViewport(0, 0, size.width, size.height);
196 glMatrixMode(GL_PROJECTION);
197 glLoadIdentity();
198 ccglOrtho(0, size.width, 0, size.height, -1024 * CC_CONTENT_SCALE_FACTOR(), 1024 * CC_CONTENT_SCALE_FACTOR());
199 glMatrixMode(GL_MODELVIEW);
200 glLoadIdentity();
201 break;
202
203 case kCCDirectorProjection3D:
204 {
205 float zeye = [self getZEye];
206
207 glViewport(0, 0, size.width, size.height);
208 glMatrixMode(GL_PROJECTION);
209 glLoadIdentity();
210// gluPerspective(60, (GLfloat)size.width/size.height, zeye-size.height/2, zeye+size.height/2 );
211 gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500);
212
213 glMatrixMode(GL_MODELVIEW);
214 glLoadIdentity();
215 gluLookAt( size.width/2, size.height/2, zeye,
216 size.width/2, size.height/2, 0,
217 0.0f, 1.0f, 0.0f);
218 break;
219 }
220
221 case kCCDirectorProjectionCustom:
222 if( projectionDelegate_ )
223 [projectionDelegate_ updateProjection];
224 break;
225
226 default:
227 CCLOG(@"cocos2d: Director: unrecognized projecgtion");
228 break;
229 }
230
231 projection_ = projection;
232}
233
234#pragma mark Director Integration with a UIKit view
235
236-(void) setOpenGLView:(EAGLView *)view
237{
238 if( view != openGLView_ ) {
239
240 [super setOpenGLView:view];
241
242 // set size
243 winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor);
244
245 if( __ccContentScaleFactor != 1 )
246 [self updateContentScaleFactor];
247
248 CCTouchDispatcher *touchDispatcher = [CCTouchDispatcher sharedDispatcher];
249 [openGLView_ setTouchDelegate: touchDispatcher];
250 [touchDispatcher setDispatchEvents: YES];
251 }
252}
253
254#pragma mark Director - Retina Display
255
256-(CGFloat) contentScaleFactor
257{
258 return __ccContentScaleFactor;
259}
260
261-(void) setContentScaleFactor:(CGFloat)scaleFactor
262{
263 if( scaleFactor != __ccContentScaleFactor ) {
264
265 __ccContentScaleFactor = scaleFactor;
266 winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * scaleFactor, winSizeInPoints_.height * scaleFactor );
267
268 if( openGLView_ )
269 [self updateContentScaleFactor];
270
271 // update projection
272 [self setProjection:projection_];
273 }
274}
275
276-(void) updateContentScaleFactor
277{
278 // Based on code snippet from: http://developer.apple.com/iphone/prerelease/library/snippets/sp2010/sp28.html
279 if ([openGLView_ respondsToSelector:@selector(setContentScaleFactor:)])
280 {
281 [openGLView_ setContentScaleFactor: __ccContentScaleFactor];
282
283 isContentScaleSupported_ = YES;
284 }
285 else
286 CCLOG(@"cocos2d: 'setContentScaleFactor:' is not supported on this device");
287}
288
289-(BOOL) enableRetinaDisplay:(BOOL)enabled
290{
291 // Already enabled ?
292 if( enabled && __ccContentScaleFactor == 2 )
293 return YES;
294
295 // Already disabled
296 if( ! enabled && __ccContentScaleFactor == 1 )
297 return YES;
298
299 // setContentScaleFactor is not supported
300 if (! [openGLView_ respondsToSelector:@selector(setContentScaleFactor:)])
301 return NO;
302
303 // SD device
304 if ([[UIScreen mainScreen] scale] == 1.0)
305 return NO;
306
307 float newScale = enabled ? 2 : 1;
308 [self setContentScaleFactor:newScale];
309
310 return YES;
311}
312
313// overriden, don't call super
314-(void) reshapeProjection:(CGSize)size
315{
316 winSizeInPoints_ = [openGLView_ bounds].size;
317 winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor);
318
319 [self setProjection:projection_];
320}
321
322#pragma mark Director Scene Landscape
323
324-(CGPoint)convertToGL:(CGPoint)uiPoint
325{
326 CGSize s = winSizeInPoints_;
327 float newY = s.height - uiPoint.y;
328 float newX = s.width - uiPoint.x;
329
330 CGPoint ret = CGPointZero;
331 switch ( deviceOrientation_) {
332 case CCDeviceOrientationPortrait:
333 ret = ccp( uiPoint.x, newY );
334 break;
335 case CCDeviceOrientationPortraitUpsideDown:
336 ret = ccp(newX, uiPoint.y);
337 break;
338 case CCDeviceOrientationLandscapeLeft:
339 ret.x = uiPoint.y;
340 ret.y = uiPoint.x;
341 break;
342 case CCDeviceOrientationLandscapeRight:
343 ret.x = newY;
344 ret.y = newX;
345 break;
346 }
347 return ret;
348}
349
350-(CGPoint)convertToUI:(CGPoint)glPoint
351{
352 CGSize winSize = winSizeInPoints_;
353 int oppositeX = winSize.width - glPoint.x;
354 int oppositeY = winSize.height - glPoint.y;
355 CGPoint uiPoint = CGPointZero;
356 switch ( deviceOrientation_) {
357 case CCDeviceOrientationPortrait:
358 uiPoint = ccp(glPoint.x, oppositeY);
359 break;
360 case CCDeviceOrientationPortraitUpsideDown:
361 uiPoint = ccp(oppositeX, glPoint.y);
362 break;
363 case CCDeviceOrientationLandscapeLeft:
364 uiPoint = ccp(glPoint.y, glPoint.x);
365 break;
366 case CCDeviceOrientationLandscapeRight:
367 // Can't use oppositeX/Y because x/y are flipped
368 uiPoint = ccp(winSize.width-glPoint.y, winSize.height-glPoint.x);
369 break;
370 }
371 return uiPoint;
372}
373
374// get the current size of the glview
375-(CGSize) winSize
376{
377 CGSize s = winSizeInPoints_;
378
379 if( deviceOrientation_ == CCDeviceOrientationLandscapeLeft || deviceOrientation_ == CCDeviceOrientationLandscapeRight ) {
380 // swap x,y in landscape mode
381 CGSize tmp = s;
382 s.width = tmp.height;
383 s.height = tmp.width;
384 }
385 return s;
386}
387
388-(CGSize) winSizeInPixels
389{
390 CGSize s = [self winSize];
391
392 s.width *= CC_CONTENT_SCALE_FACTOR();
393 s.height *= CC_CONTENT_SCALE_FACTOR();
394
395 return s;
396}
397
398-(ccDeviceOrientation) deviceOrientation
399{
400 return deviceOrientation_;
401}
402
403- (void) setDeviceOrientation:(ccDeviceOrientation) orientation
404{
405 if( deviceOrientation_ != orientation ) {
406 deviceOrientation_ = orientation;
407 switch( deviceOrientation_) {
408 case CCDeviceOrientationPortrait:
409 [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:NO];
410 break;
411 case CCDeviceOrientationPortraitUpsideDown:
412 [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown animated:NO];
413 break;
414 case CCDeviceOrientationLandscapeLeft:
415 [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];
416 break;
417 case CCDeviceOrientationLandscapeRight:
418 [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft animated:NO];
419 break;
420 default:
421 NSLog(@"Director: Unknown device orientation");
422 break;
423 }
424 }
425}
426
427-(void) applyOrientation
428{
429 CGSize s = winSizeInPixels_;
430 float w = s.width / 2;
431 float h = s.height / 2;
432
433 // XXX it's using hardcoded values.
434 // What if the the screen size changes in the future?
435 switch ( deviceOrientation_ ) {
436 case CCDeviceOrientationPortrait:
437 // nothing
438 break;
439 case CCDeviceOrientationPortraitUpsideDown:
440 // upside down
441 glTranslatef(w,h,0);
442 glRotatef(180,0,0,1);
443 glTranslatef(-w,-h,0);
444 break;
445 case CCDeviceOrientationLandscapeRight:
446 glTranslatef(w,h,0);
447 glRotatef(90,0,0,1);
448 glTranslatef(-h,-w,0);
449 break;
450 case CCDeviceOrientationLandscapeLeft:
451 glTranslatef(w,h,0);
452 glRotatef(-90,0,0,1);
453 glTranslatef(-h,-w,0);
454 break;
455 }
456}
457
458-(void) end
459{
460 // don't release the event handlers
461 // They are needed in case the director is run again
462 [[CCTouchDispatcher sharedDispatcher] removeAllDelegates];
463
464 [super end];
465}
466
467@end
468
469
470#pragma mark -
471#pragma mark Director TimerDirector
472
473@implementation CCDirectorTimer
474- (void)startAnimation
475{
476 NSAssert( animationTimer == nil, @"animationTimer must be nil. Calling startAnimation twice?");
477
478 if( gettimeofday( &lastUpdate_, NULL) != 0 ) {
479 CCLOG(@"cocos2d: Director: Error in gettimeofday");
480 }
481
482 animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval_ target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
483
484 //
485 // If you want to attach the opengl view into UIScrollView
486 // uncomment this line to prevent 'freezing'.
487 // It doesn't work on with the Fast Director
488 //
489 // [[NSRunLoop currentRunLoop] addTimer:animationTimer
490 // forMode:NSRunLoopCommonModes];
491}
492
493-(void) mainLoop
494{
495 [self drawScene];
496}
497
498- (void)stopAnimation
499{
500 [animationTimer invalidate];
501 animationTimer = nil;
502}
503
504- (void)setAnimationInterval:(NSTimeInterval)interval
505{
506 animationInterval_ = interval;
507
508 if(animationTimer) {
509 [self stopAnimation];
510 [self startAnimation];
511 }
512}
513
514-(void) dealloc
515{
516 [animationTimer release];
517 [super dealloc];
518}
519@end
520
521
522#pragma mark -
523#pragma mark Director DirectorFast
524
525@implementation CCDirectorFast
526
527- (id) init
528{
529 if(( self = [super init] )) {
530
531#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
532 CCLOG(@"cocos2d: Fast Events enabled");
533#else
534 CCLOG(@"cocos2d: Fast Events disabled");
535#endif
536 isRunning = NO;
537
538 // XXX:
539 // XXX: Don't create any autorelease object before calling "fast director"
540 // XXX: else it will be leaked
541 // XXX:
542 autoreleasePool = [NSAutoreleasePool new];
543 }
544
545 return self;
546}
547
548- (void) startAnimation
549{
550 NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?");
551
552 // XXX:
553 // XXX: release autorelease objects created
554 // XXX: between "use fast director" and "runWithScene"
555 // XXX:
556 [autoreleasePool release];
557 autoreleasePool = nil;
558
559 if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
560 CCLOG(@"cocos2d: Director: Error in gettimeofday");
561 }
562
563
564 isRunning = YES;
565
566 SEL selector = @selector(mainLoop);
567 NSMethodSignature* sig = [[[CCDirector sharedDirector] class]
568 instanceMethodSignatureForSelector:selector];
569 NSInvocation* invocation = [NSInvocation
570 invocationWithMethodSignature:sig];
571 [invocation setTarget:[CCDirector sharedDirector]];
572 [invocation setSelector:selector];
573 [invocation performSelectorOnMainThread:@selector(invokeWithTarget:)
574 withObject:[CCDirector sharedDirector] waitUntilDone:NO];
575
576// NSInvocationOperation *loopOperation = [[[NSInvocationOperation alloc]
577// initWithTarget:self selector:@selector(mainLoop) object:nil]
578// autorelease];
579//
580// [loopOperation performSelectorOnMainThread:@selector(start) withObject:nil
581// waitUntilDone:NO];
582}
583
584-(void) mainLoop
585{
586 while (isRunning) {
587
588 NSAutoreleasePool *loopPool = [NSAutoreleasePool new];
589
590#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
591 while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource);
592#else
593 while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource);
594#endif
595
596 if (isPaused_) {
597 usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps.
598 }
599
600 [self drawScene];
601
602#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
603 while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource);
604#else
605 while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource);
606#endif
607
608 [loopPool release];
609 }
610}
611- (void) stopAnimation
612{
613 isRunning = NO;
614}
615
616- (void)setAnimationInterval:(NSTimeInterval)interval
617{
618 NSLog(@"FastDirectory doesn't support setAnimationInterval, yet");
619}
620@end
621
622#pragma mark -
623#pragma mark Director DirectorThreadedFast
624
625@implementation CCDirectorFastThreaded
626
627- (id) init
628{
629 if(( self = [super init] )) {
630 isRunning = NO;
631 }
632
633 return self;
634}
635
636- (void) startAnimation
637{
638 NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?");
639
640 if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
641 CCLOG(@"cocos2d: ThreadedFastDirector: Error on gettimeofday");
642 }
643
644 isRunning = YES;
645
646 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil];
647 [thread start];
648 [thread release];
649}
650
651-(void) mainLoop
652{
653 while( ![[NSThread currentThread] isCancelled] ) {
654 if( isRunning )
655 [self performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES];
656
657 if (isPaused_) {
658 usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps.
659 } else {
660// usleep(2000);
661 }
662 }
663}
664- (void) stopAnimation
665{
666 isRunning = NO;
667}
668
669- (void)setAnimationInterval:(NSTimeInterval)interval
670{
671 NSLog(@"FastDirector doesn't support setAnimationInterval, yet");
672}
673@end
674
675#pragma mark -
676#pragma mark DirectorDisplayLink
677
678// Allows building DisplayLinkDirector for pre-3.1 SDKS
679// without getting compiler warnings.
680@interface NSObject(CADisplayLink)
681+ (id) displayLinkWithTarget:(id)arg1 selector:(SEL)arg2;
682- (void) addToRunLoop:(id)arg1 forMode:(id)arg2;
683- (void) setFrameInterval:(int)interval;
684- (void) invalidate;
685@end
686
687@implementation CCDirectorDisplayLink
688
689- (void)setAnimationInterval:(NSTimeInterval)interval
690{
691 animationInterval_ = interval;
692 if(displayLink){
693 [self stopAnimation];
694 [self startAnimation];
695 }
696}
697
698- (void) startAnimation
699{
700 NSAssert( displayLink == nil, @"displayLink must be nil. Calling startAnimation twice?");
701
702 if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
703 CCLOG(@"cocos2d: DisplayLinkDirector: Error on gettimeofday");
704 }
705
706 // approximate frame rate
707 // assumes device refreshes at 60 fps
708 int frameInterval = (int) floor(animationInterval_ * 60.0f);
709
710 CCLOG(@"cocos2d: Frame interval: %d", frameInterval);
711
712 displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(mainLoop:)];
713 [displayLink setFrameInterval:frameInterval];
714 [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
715}
716
717-(void) mainLoop:(id)sender
718{
719 [self drawScene];
720}
721
722- (void) stopAnimation
723{
724 [displayLink invalidate];
725 displayLink = nil;
726}
727
728-(void) dealloc
729{
730 [displayLink release];
731 [super dealloc];
732}
733@end
734
735#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCTouchDelegateProtocol.h b/libs/cocos2d/Platforms/iOS/CCTouchDelegateProtocol.h new file mode 100755 index 0000000..20ba036 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCTouchDelegateProtocol.h
@@ -0,0 +1,75 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26// Only compile this code on iOS. These files should NOT be included on your Mac project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30
31#import <UIKit/UIKit.h>
32
33/**
34 CCTargetedTouchDelegate.
35
36 Using this type of delegate results in two benefits:
37 1. You don't need to deal with NSSets, the dispatcher does the job of splitting
38 them. You get exactly one UITouch per call.
39 2. You can *claim* a UITouch by returning YES in ccTouchBegan. Updates of claimed
40 touches are sent only to the delegate(s) that claimed them. So if you get a move/
41 ended/cancelled update you're sure it's your touch. This frees you from doing a
42 lot of checks when doing multi-touch.
43
44 (The name TargetedTouchDelegate relates to updates "targeting" their specific
45 handler, without bothering the other handlers.)
46 @since v0.8
47 */
48@protocol CCTargetedTouchDelegate <NSObject>
49
50/** Return YES to claim the touch.
51 @since v0.8
52 */
53- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event;
54@optional
55// touch updates:
56- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event;
57- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event;
58- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event;
59@end
60
61/**
62 CCStandardTouchDelegate.
63
64 This type of delegate is the same one used by CocoaTouch. You will receive all the events (Began,Moved,Ended,Cancelled).
65 @since v0.8
66*/
67@protocol CCStandardTouchDelegate <NSObject>
68@optional
69- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
70- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
71- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
72- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
73@end
74
75#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h new file mode 100755 index 0000000..9931189 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h
@@ -0,0 +1,123 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26// Only compile this code on iOS. These files should NOT be included on your Mac project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30
31#import "CCTouchDelegateProtocol.h"
32#import "EAGLView.h"
33
34
35typedef enum
36{
37 kCCTouchSelectorBeganBit = 1 << 0,
38 kCCTouchSelectorMovedBit = 1 << 1,
39 kCCTouchSelectorEndedBit = 1 << 2,
40 kCCTouchSelectorCancelledBit = 1 << 3,
41 kCCTouchSelectorAllBits = ( kCCTouchSelectorBeganBit | kCCTouchSelectorMovedBit | kCCTouchSelectorEndedBit | kCCTouchSelectorCancelledBit),
42} ccTouchSelectorFlag;
43
44
45enum {
46 kCCTouchBegan,
47 kCCTouchMoved,
48 kCCTouchEnded,
49 kCCTouchCancelled,
50
51 kCCTouchMax,
52};
53
54struct ccTouchHandlerHelperData {
55 SEL touchesSel;
56 SEL touchSel;
57 ccTouchSelectorFlag type;
58};
59
60/** CCTouchDispatcher.
61 Singleton that handles all the touch events.
62 The dispatcher dispatches events to the registered TouchHandlers.
63 There are 2 different type of touch handlers:
64 - Standard Touch Handlers
65 - Targeted Touch Handlers
66
67 The Standard Touch Handlers work like the CocoaTouch touch handler: a set of touches is passed to the delegate.
68 On the other hand, the Targeted Touch Handlers only receive 1 touch at the time, and they can "swallow" touches (avoid the propagation of the event).
69
70 Firstly, the dispatcher sends the received touches to the targeted touches.
71 These touches can be swallowed by the Targeted Touch Handlers. If there are still remaining touches, then the remaining touches will be sent
72 to the Standard Touch Handlers.
73
74 @since v0.8.0
75 */
76@interface CCTouchDispatcher : NSObject <EAGLTouchDelegate>
77{
78 NSMutableArray *targetedHandlers;
79 NSMutableArray *standardHandlers;
80
81 BOOL locked;
82 BOOL toAdd;
83 BOOL toRemove;
84 NSMutableArray *handlersToAdd;
85 NSMutableArray *handlersToRemove;
86 BOOL toQuit;
87
88 BOOL dispatchEvents;
89
90 // 4, 1 for each type of event
91 struct ccTouchHandlerHelperData handlerHelperData[kCCTouchMax];
92}
93
94/** singleton of the CCTouchDispatcher */
95+ (CCTouchDispatcher*)sharedDispatcher;
96
97/** Whether or not the events are going to be dispatched. Default: YES */
98@property (nonatomic,readwrite, assign) BOOL dispatchEvents;
99
100/** Adds a standard touch delegate to the dispatcher's list.
101 See StandardTouchDelegate description.
102 IMPORTANT: The delegate will be retained.
103 */
104-(void) addStandardDelegate:(id<CCStandardTouchDelegate>) delegate priority:(int)priority;
105/** Adds a targeted touch delegate to the dispatcher's list.
106 See TargetedTouchDelegate description.
107 IMPORTANT: The delegate will be retained.
108 */
109-(void) addTargetedDelegate:(id<CCTargetedTouchDelegate>) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
110/** Removes a touch delegate.
111 The delegate will be released
112 */
113-(void) removeDelegate:(id) delegate;
114/** Removes all touch delegates, releasing all the delegates */
115-(void) removeAllDelegates;
116/** Changes the priority of a previously added delegate. The lower the number,
117 the higher the priority */
118-(void) setPriority:(int) priority forDelegate:(id) delegate;
119
120NSComparisonResult sortByPriority(id first, id second, void *context);
121@end
122
123#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m new file mode 100755 index 0000000..1553b48 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m
@@ -0,0 +1,347 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26// Only compile this code on iOS. These files should NOT be included on your Mac project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30
31
32#import "CCTouchDispatcher.h"
33#import "CCTouchHandler.h"
34
35@implementation CCTouchDispatcher
36
37@synthesize dispatchEvents;
38
39static CCTouchDispatcher *sharedDispatcher = nil;
40
41+(CCTouchDispatcher*) sharedDispatcher
42{
43 @synchronized(self) {
44 if (sharedDispatcher == nil)
45 sharedDispatcher = [[self alloc] init]; // assignment not done here
46 }
47 return sharedDispatcher;
48}
49
50+(id) allocWithZone:(NSZone *)zone
51{
52 @synchronized(self) {
53 NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
54 return [super allocWithZone:zone];
55 }
56 return nil; // on subsequent allocation attempts return nil
57}
58
59-(id) init
60{
61 if((self = [super init])) {
62
63 dispatchEvents = YES;
64 targetedHandlers = [[NSMutableArray alloc] initWithCapacity:8];
65 standardHandlers = [[NSMutableArray alloc] initWithCapacity:4];
66
67 handlersToAdd = [[NSMutableArray alloc] initWithCapacity:8];
68 handlersToRemove = [[NSMutableArray alloc] initWithCapacity:8];
69
70 toRemove = NO;
71 toAdd = NO;
72 toQuit = NO;
73 locked = NO;
74
75 handlerHelperData[kCCTouchBegan] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesBegan:withEvent:),@selector(ccTouchBegan:withEvent:),kCCTouchSelectorBeganBit};
76 handlerHelperData[kCCTouchMoved] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesMoved:withEvent:),@selector(ccTouchMoved:withEvent:),kCCTouchSelectorMovedBit};
77 handlerHelperData[kCCTouchEnded] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesEnded:withEvent:),@selector(ccTouchEnded:withEvent:),kCCTouchSelectorEndedBit};
78 handlerHelperData[kCCTouchCancelled] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesCancelled:withEvent:),@selector(ccTouchCancelled:withEvent:),kCCTouchSelectorCancelledBit};
79
80 }
81
82 return self;
83}
84
85-(void) dealloc
86{
87 [targetedHandlers release];
88 [standardHandlers release];
89 [handlersToAdd release];
90 [handlersToRemove release];
91 [super dealloc];
92}
93
94//
95// handlers management
96//
97
98#pragma mark TouchDispatcher - Add Hanlder
99
100-(void) forceAddHandler:(CCTouchHandler*)handler array:(NSMutableArray*)array
101{
102 NSUInteger i = 0;
103
104 for( CCTouchHandler *h in array ) {
105 if( h.priority < handler.priority )
106 i++;
107
108 NSAssert( h.delegate != handler.delegate, @"Delegate already added to touch dispatcher.");
109 }
110 [array insertObject:handler atIndex:i];
111}
112
113-(void) addStandardDelegate:(id<CCStandardTouchDelegate>) delegate priority:(int)priority
114{
115 CCTouchHandler *handler = [CCStandardTouchHandler handlerWithDelegate:delegate priority:priority];
116 if( ! locked ) {
117 [self forceAddHandler:handler array:standardHandlers];
118 } else {
119 [handlersToAdd addObject:handler];
120 toAdd = YES;
121 }
122}
123
124-(void) addTargetedDelegate:(id<CCTargetedTouchDelegate>) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches
125{
126 CCTouchHandler *handler = [CCTargetedTouchHandler handlerWithDelegate:delegate priority:priority swallowsTouches:swallowsTouches];
127 if( ! locked ) {
128 [self forceAddHandler:handler array:targetedHandlers];
129 } else {
130 [handlersToAdd addObject:handler];
131 toAdd = YES;
132 }
133}
134
135#pragma mark TouchDispatcher - removeDelegate
136
137-(void) forceRemoveDelegate:(id)delegate
138{
139 // XXX: remove it from both handlers ???
140
141 for( CCTouchHandler *handler in targetedHandlers ) {
142 if( handler.delegate == delegate ) {
143 [targetedHandlers removeObject:handler];
144 break;
145 }
146 }
147
148 for( CCTouchHandler *handler in standardHandlers ) {
149 if( handler.delegate == delegate ) {
150 [standardHandlers removeObject:handler];
151 break;
152 }
153 }
154}
155
156-(void) removeDelegate:(id) delegate
157{
158 if( delegate == nil )
159 return;
160
161 if( ! locked ) {
162 [self forceRemoveDelegate:delegate];
163 } else {
164 [handlersToRemove addObject:delegate];
165 toRemove = YES;
166 }
167}
168
169#pragma mark TouchDispatcher - removeAllDelegates
170
171-(void) forceRemoveAllDelegates
172{
173 [standardHandlers removeAllObjects];
174 [targetedHandlers removeAllObjects];
175}
176-(void) removeAllDelegates
177{
178 if( ! locked )
179 [self forceRemoveAllDelegates];
180 else
181 toQuit = YES;
182}
183
184#pragma mark Changing priority of added handlers
185
186-(CCTouchHandler*) findHandler:(id)delegate
187{
188 for( CCTouchHandler *handler in targetedHandlers ) {
189 if( handler.delegate == delegate ) {
190 return handler;
191 }
192 }
193
194 for( CCTouchHandler *handler in standardHandlers ) {
195 if( handler.delegate == delegate ) {
196 return handler;
197 }
198 }
199 return nil;
200}
201
202NSComparisonResult sortByPriority(id first, id second, void *context)
203{
204 if (((CCTouchHandler*)first).priority < ((CCTouchHandler*)second).priority)
205 return NSOrderedAscending;
206 else if (((CCTouchHandler*)first).priority > ((CCTouchHandler*)second).priority)
207 return NSOrderedDescending;
208 else
209 return NSOrderedSame;
210}
211
212-(void) rearrangeHandlers:(NSMutableArray*)array
213{
214 [array sortUsingFunction:sortByPriority context:nil];
215}
216
217-(void) setPriority:(int) priority forDelegate:(id) delegate
218{
219 NSAssert(delegate != nil, @"Got nil touch delegate!");
220
221 CCTouchHandler *handler = nil;
222 handler = [self findHandler:delegate];
223
224 NSAssert(handler != nil, @"Delegate not found!");
225
226 handler.priority = priority;
227
228 [self rearrangeHandlers:targetedHandlers];
229 [self rearrangeHandlers:standardHandlers];
230}
231
232//
233// dispatch events
234//
235-(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx
236{
237 NSAssert(idx < 4, @"Invalid idx value");
238
239 id mutableTouches;
240 locked = YES;
241
242 // optimization to prevent a mutable copy when it is not necessary
243 unsigned int targetedHandlersCount = [targetedHandlers count];
244 unsigned int standardHandlersCount = [standardHandlers count];
245 BOOL needsMutableSet = (targetedHandlersCount && standardHandlersCount);
246
247 mutableTouches = (needsMutableSet ? [touches mutableCopy] : touches);
248
249 struct ccTouchHandlerHelperData helper = handlerHelperData[idx];
250 //
251 // process the target handlers 1st
252 //
253 if( targetedHandlersCount > 0 ) {
254 for( UITouch *touch in touches ) {
255 for(CCTargetedTouchHandler *handler in targetedHandlers) {
256
257 BOOL claimed = NO;
258 if( idx == kCCTouchBegan ) {
259 claimed = [handler.delegate ccTouchBegan:touch withEvent:event];
260 if( claimed )
261 [handler.claimedTouches addObject:touch];
262 }
263
264 // else (moved, ended, cancelled)
265 else if( [handler.claimedTouches containsObject:touch] ) {
266 claimed = YES;
267 if( handler.enabledSelectors & helper.type )
268 [handler.delegate performSelector:helper.touchSel withObject:touch withObject:event];
269
270 if( helper.type & (kCCTouchSelectorCancelledBit | kCCTouchSelectorEndedBit) )
271 [handler.claimedTouches removeObject:touch];
272 }
273
274 if( claimed && handler.swallowsTouches ) {
275 if( needsMutableSet )
276 [mutableTouches removeObject:touch];
277 break;
278 }
279 }
280 }
281 }
282
283 //
284 // process standard handlers 2nd
285 //
286 if( standardHandlersCount > 0 && [mutableTouches count]>0 ) {
287 for( CCTouchHandler *handler in standardHandlers ) {
288 if( handler.enabledSelectors & helper.type )
289 [handler.delegate performSelector:helper.touchesSel withObject:mutableTouches withObject:event];
290 }
291 }
292 if( needsMutableSet )
293 [mutableTouches release];
294
295 //
296 // Optimization. To prevent a [handlers copy] which is expensive
297 // the add/removes/quit is done after the iterations
298 //
299 locked = NO;
300 if( toRemove ) {
301 toRemove = NO;
302 for( id delegate in handlersToRemove )
303 [self forceRemoveDelegate:delegate];
304 [handlersToRemove removeAllObjects];
305 }
306 if( toAdd ) {
307 toAdd = NO;
308 for( CCTouchHandler *handler in handlersToAdd ) {
309 Class targetedClass = [CCTargetedTouchHandler class];
310 if( [handler isKindOfClass:targetedClass] )
311 [self forceAddHandler:handler array:targetedHandlers];
312 else
313 [self forceAddHandler:handler array:standardHandlers];
314 }
315 [handlersToAdd removeAllObjects];
316 }
317 if( toQuit ) {
318 toQuit = NO;
319 [self forceRemoveAllDelegates];
320 }
321}
322
323- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
324{
325 if( dispatchEvents )
326 [self touches:touches withEvent:event withTouchType:kCCTouchBegan];
327}
328- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
329{
330 if( dispatchEvents )
331 [self touches:touches withEvent:event withTouchType:kCCTouchMoved];
332}
333
334- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
335{
336 if( dispatchEvents )
337 [self touches:touches withEvent:event withTouchType:kCCTouchEnded];
338}
339
340- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
341{
342 if( dispatchEvents )
343 [self touches:touches withEvent:event withTouchType:kCCTouchCancelled];
344}
345@end
346
347#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCTouchHandler.h b/libs/cocos2d/Platforms/iOS/CCTouchHandler.h new file mode 100755 index 0000000..31a3e36 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCTouchHandler.h
@@ -0,0 +1,93 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26// Only compile this code on iOS. These files should NOT be included on your Mac project.
27// But in case they are included, it won't be compiled.
28#import <Availability.h>
29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
30
31/*
32 * This file contains the delegates of the touches
33 * There are 2 possible delegates:
34 * - CCStandardTouchHandler: propagates all the events at once
35 * - CCTargetedTouchHandler: propagates 1 event at the time
36 */
37
38#import "CCTouchDelegateProtocol.h"
39#import "CCTouchDispatcher.h"
40
41/**
42 CCTouchHandler
43 Object than contains the delegate and priority of the event handler.
44*/
45@interface CCTouchHandler : NSObject {
46 id delegate;
47 int priority;
48 ccTouchSelectorFlag enabledSelectors_;
49}
50
51/** delegate */
52@property(nonatomic, readwrite, retain) id delegate;
53/** priority */
54@property(nonatomic, readwrite) int priority; // default 0
55/** enabled selectors */
56@property(nonatomic,readwrite) ccTouchSelectorFlag enabledSelectors;
57
58/** allocates a TouchHandler with a delegate and a priority */
59+ (id)handlerWithDelegate:(id)aDelegate priority:(int)priority;
60/** initializes a TouchHandler with a delegate and a priority */
61- (id)initWithDelegate:(id)aDelegate priority:(int)priority;
62@end
63
64/** CCStandardTouchHandler
65 It forwardes each event to the delegate.
66 */
67@interface CCStandardTouchHandler : CCTouchHandler
68{
69}
70@end
71
72/**
73 CCTargetedTouchHandler
74 Object than contains the claimed touches and if it swallos touches.
75 Used internally by TouchDispatcher
76 */
77@interface CCTargetedTouchHandler : CCTouchHandler {
78 BOOL swallowsTouches;
79 NSMutableSet *claimedTouches;
80}
81/** whether or not the touches are swallowed */
82@property(nonatomic, readwrite) BOOL swallowsTouches; // default NO
83/** MutableSet that contains the claimed touches */
84@property(nonatomic, readonly) NSMutableSet *claimedTouches;
85
86/** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */
87+ (id)handlerWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
88/** initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */
89- (id)initWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
90
91@end
92
93#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/CCTouchHandler.m b/libs/cocos2d/Platforms/iOS/CCTouchHandler.m new file mode 100755 index 0000000..a52103b --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCTouchHandler.m
@@ -0,0 +1,135 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27// Only compile this code on iOS. These files should NOT be included on your Mac project.
28// But in case they are included, it won't be compiled.
29#import <Availability.h>
30#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
31
32/*
33 * This file contains the delegates of the touches
34 * There are 2 possible delegates:
35 * - CCStandardTouchHandler: propagates all the events at once
36 * - CCTargetedTouchHandler: propagates 1 event at the time
37 */
38
39#import "CCTouchHandler.h"
40#import "../../ccMacros.h"
41
42#pragma mark -
43#pragma mark TouchHandler
44@implementation CCTouchHandler
45
46@synthesize delegate, priority;
47@synthesize enabledSelectors=enabledSelectors_;
48
49+ (id)handlerWithDelegate:(id) aDelegate priority:(int)aPriority
50{
51 return [[[self alloc] initWithDelegate:aDelegate priority:aPriority] autorelease];
52}
53
54- (id)initWithDelegate:(id) aDelegate priority:(int)aPriority
55{
56 NSAssert(aDelegate != nil, @"Touch delegate may not be nil");
57
58 if ((self = [super init])) {
59 self.delegate = aDelegate;
60 priority = aPriority;
61 enabledSelectors_ = 0;
62 }
63
64 return self;
65}
66
67- (void)dealloc {
68 CCLOGINFO(@"cocos2d: deallocing %@", self);
69 [delegate release];
70 [super dealloc];
71}
72@end
73
74#pragma mark -
75#pragma mark StandardTouchHandler
76@implementation CCStandardTouchHandler
77-(id) initWithDelegate:(id)del priority:(int)pri
78{
79 if( (self=[super initWithDelegate:del priority:pri]) ) {
80 if( [del respondsToSelector:@selector(ccTouchesBegan:withEvent:)] )
81 enabledSelectors_ |= kCCTouchSelectorBeganBit;
82 if( [del respondsToSelector:@selector(ccTouchesMoved:withEvent:)] )
83 enabledSelectors_ |= kCCTouchSelectorMovedBit;
84 if( [del respondsToSelector:@selector(ccTouchesEnded:withEvent:)] )
85 enabledSelectors_ |= kCCTouchSelectorEndedBit;
86 if( [del respondsToSelector:@selector(ccTouchesCancelled:withEvent:)] )
87 enabledSelectors_ |= kCCTouchSelectorCancelledBit;
88 }
89 return self;
90}
91@end
92
93#pragma mark -
94#pragma mark TargetedTouchHandler
95
96@interface CCTargetedTouchHandler (private)
97-(void) updateKnownTouches:(NSMutableSet *)touches withEvent:(UIEvent *)event selector:(SEL)selector unclaim:(BOOL)doUnclaim;
98@end
99
100@implementation CCTargetedTouchHandler
101
102@synthesize swallowsTouches, claimedTouches;
103
104+ (id)handlerWithDelegate:(id)aDelegate priority:(int)priority swallowsTouches:(BOOL)swallow
105{
106 return [[[self alloc] initWithDelegate:aDelegate priority:priority swallowsTouches:swallow] autorelease];
107}
108
109- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow
110{
111 if ((self = [super initWithDelegate:aDelegate priority:aPriority])) {
112 claimedTouches = [[NSMutableSet alloc] initWithCapacity:2];
113 swallowsTouches = swallow;
114
115 if( [aDelegate respondsToSelector:@selector(ccTouchBegan:withEvent:)] )
116 enabledSelectors_ |= kCCTouchSelectorBeganBit;
117 if( [aDelegate respondsToSelector:@selector(ccTouchMoved:withEvent:)] )
118 enabledSelectors_ |= kCCTouchSelectorMovedBit;
119 if( [aDelegate respondsToSelector:@selector(ccTouchEnded:withEvent:)] )
120 enabledSelectors_ |= kCCTouchSelectorEndedBit;
121 if( [aDelegate respondsToSelector:@selector(ccTouchCancelled:withEvent:)] )
122 enabledSelectors_ |= kCCTouchSelectorCancelledBit;
123 }
124
125 return self;
126}
127
128- (void)dealloc {
129 [claimedTouches release];
130 [super dealloc];
131}
132@end
133
134
135#endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file
diff --git a/libs/cocos2d/Platforms/iOS/EAGLView.h b/libs/cocos2d/Platforms/iOS/EAGLView.h new file mode 100755 index 0000000..3b6c2f3 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/EAGLView.h
@@ -0,0 +1,155 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentation
14seeds.
15
16=====================
17
18File: EAGLView.h
19Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
20UIView subclass.
21
22Version: 1.3
23
24Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
25("Apple") in consideration of your agreement to the following terms, and your
26use, installation, modification or redistribution of this Apple software
27constitutes acceptance of these terms. If you do not agree with these terms,
28please do not use, install, modify or redistribute this Apple software.
29
30In consideration of your agreement to abide by the following terms, and subject
31to these terms, Apple grants you a personal, non-exclusive license, under
32Apple's copyrights in this original Apple software (the "Apple Software"), to
33use, reproduce, modify and redistribute the Apple Software, with or without
34modifications, in source and/or binary forms; provided that if you redistribute
35the Apple Software in its entirety and without modifications, you must retain
36this notice and the following text and disclaimers in all such redistributions
37of the Apple Software.
38Neither the name, trademarks, service marks or logos of Apple Inc. may be used
39to endorse or promote products derived from the Apple Software without specific
40prior written permission from Apple. Except as expressly stated in this notice,
41no other rights or licenses, express or implied, are granted by Apple herein,
42including but not limited to any patent rights that may be infringed by your
43derivative works or by other works in which the Apple Software may be
44incorporated.
45
46The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
47WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
48WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
50COMBINATION WITH YOUR PRODUCTS.
51
52IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
53CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
54GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
56DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
57CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
58APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
60Copyright (C) 2008 Apple Inc. All Rights Reserved.
61
62*/
63
64// Only compile this code on iOS. These files should NOT be included on your Mac project.
65// But in case they are included, it won't be compiled.
66#import <Availability.h>
67#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
68
69#import <UIKit/UIKit.h>
70#import <OpenGLES/EAGL.h>
71#import <OpenGLES/EAGLDrawable.h>
72#import <OpenGLES/ES1/gl.h>
73#import <OpenGLES/ES1/glext.h>
74
75#import "ESRenderer.h"
76
77//CLASSES:
78
79@class EAGLView;
80@class EAGLSharegroup;
81
82//PROTOCOLS:
83
84@protocol EAGLTouchDelegate <NSObject>
85- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
86- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
87- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
88- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
89@end
90
91//CLASS INTERFACE:
92
93/** EAGLView Class.
94 * This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
95 * The view content is basically an EAGL surface you render your OpenGL scene into.
96 * Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
97 */
98@interface EAGLView : UIView
99{
100 id<ESRenderer> renderer_;
101 EAGLContext *context_; // weak ref
102
103 NSString *pixelformat_;
104 GLuint depthFormat_;
105 BOOL preserveBackbuffer_;
106
107 CGSize size_;
108 BOOL discardFramebufferSupported_;
109 id<EAGLTouchDelegate> touchDelegate_;
110
111 //fsaa addition
112 BOOL multisampling_;
113 unsigned int requestedSamples_;
114}
115
116/** creates an initializes an EAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer. */
117+ (id) viewWithFrame:(CGRect)frame;
118/** creates an initializes an EAGLView with a frame, a color buffer format, and 0-bit depth buffer. */
119+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format;
120/** creates an initializes an EAGLView with a frame, a color buffer format, and a depth buffer. */
121+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth;
122/** creates an initializes an EAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup, and multisamping */
123+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples;
124
125/** Initializes an EAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer */
126- (id) initWithFrame:(CGRect)frame; //These also set the current context
127/** Initializes an EAGLView with a frame, a color buffer format, and 0-bit depth buffer */
128- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format;
129/** Initializes an EAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup and multisampling support */
130- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples;
131
132/** pixel format: it could be RGBA8 (32-bit) or RGB565 (16-bit) */
133@property(nonatomic,readonly) NSString* pixelFormat;
134/** depth format of the render buffer: 0, 16 or 24 bits*/
135@property(nonatomic,readonly) GLuint depthFormat;
136
137/** returns surface size in pixels */
138@property(nonatomic,readonly) CGSize surfaceSize;
139
140/** OpenGL context */
141@property(nonatomic,readonly) EAGLContext *context;
142
143@property(nonatomic,readwrite) BOOL multiSampling;
144
145/** touch delegate */
146@property(nonatomic,readwrite,assign) id<EAGLTouchDelegate> touchDelegate;
147
148/** EAGLView uses double-buffer. This method swaps the buffers */
149-(void) swapBuffers;
150
151- (CGPoint) convertPointFromViewToSurface:(CGPoint)point;
152- (CGRect) convertRectFromViewToSurface:(CGRect)rect;
153@end
154
155#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/EAGLView.m b/libs/cocos2d/Platforms/iOS/EAGLView.m new file mode 100755 index 0000000..d5ead65 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/EAGLView.m
@@ -0,0 +1,343 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentation
14seeds.
15
16=====================
17
18File: EAGLView.m
19Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
20UIView subclass.
21
22Version: 1.3
23
24Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
25("Apple") in consideration of your agreement to the following terms, and your
26use, installation, modification or redistribution of this Apple software
27constitutes acceptance of these terms. If you do not agree with these terms,
28please do not use, install, modify or redistribute this Apple software.
29
30In consideration of your agreement to abide by the following terms, and subject
31to these terms, Apple grants you a personal, non-exclusive license, under
32Apple's copyrights in this original Apple software (the "Apple Software"), to
33use, reproduce, modify and redistribute the Apple Software, with or without
34modifications, in source and/or binary forms; provided that if you redistribute
35the Apple Software in its entirety and without modifications, you must retain
36this notice and the following text and disclaimers in all such redistributions
37of the Apple Software.
38Neither the name, trademarks, service marks or logos of Apple Inc. may be used
39to endorse or promote products derived from the Apple Software without specific
40prior written permission from Apple. Except as expressly stated in this notice,
41no other rights or licenses, express or implied, are granted by Apple herein,
42including but not limited to any patent rights that may be infringed by your
43derivative works or by other works in which the Apple Software may be
44incorporated.
45
46The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
47WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
48WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
50COMBINATION WITH YOUR PRODUCTS.
51
52IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
53CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
54GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
56DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
57CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
58APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
60Copyright (C) 2008 Apple Inc. All Rights Reserved.
61
62*/
63
64// Only compile this code on iOS. These files should NOT be included on your Mac project.
65// But in case they are included, it won't be compiled.
66#import <Availability.h>
67#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
68
69#import <QuartzCore/QuartzCore.h>
70
71#import "EAGLView.h"
72#import "ES1Renderer.h"
73#import "../../CCDirector.h"
74#import "../../ccMacros.h"
75#import "../../CCConfiguration.h"
76#import "../../Support/OpenGL_Internal.h"
77
78
79//CLASS IMPLEMENTATIONS:
80
81@interface EAGLView (Private)
82- (BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup;
83- (unsigned int) convertPixelFormat:(NSString*) pixelFormat;
84@end
85
86@implementation EAGLView
87
88@synthesize surfaceSize=size_;
89@synthesize pixelFormat=pixelformat_, depthFormat=depthFormat_;
90@synthesize touchDelegate=touchDelegate_;
91@synthesize context=context_;
92@synthesize multiSampling=multiSampling_;
93
94+ (Class) layerClass
95{
96 return [CAEAGLLayer class];
97}
98
99+ (id) viewWithFrame:(CGRect)frame
100{
101 return [[[self alloc] initWithFrame:frame] autorelease];
102}
103
104+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format
105{
106 return [[[self alloc] initWithFrame:frame pixelFormat:format] autorelease];
107}
108
109+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth
110{
111 return [[[self alloc] initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0] autorelease];
112}
113
114+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples
115{
116 return [[[self alloc] initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:retained sharegroup:sharegroup multiSampling:multisampling numberOfSamples:samples] autorelease];
117}
118
119- (id) initWithFrame:(CGRect)frame
120{
121 return [self initWithFrame:frame pixelFormat:kEAGLColorFormatRGB565 depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
122}
123
124- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format
125{
126 return [self initWithFrame:frame pixelFormat:format depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
127}
128
129- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples
130{
131 if((self = [super initWithFrame:frame]))
132 {
133 pixelformat_ = format;
134 depthFormat_ = depth;
135 multiSampling_ = sampling;
136 requestedSamples_ = nSamples;
137 preserveBackbuffer_ = retained;
138
139 if( ! [self setupSurfaceWithSharegroup:sharegroup] ) {
140 [self release];
141 return nil;
142 }
143 }
144
145 return self;
146}
147
148-(id) initWithCoder:(NSCoder *)aDecoder
149{
150 if( (self = [super initWithCoder:aDecoder]) ) {
151
152 CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[self layer];
153
154 pixelformat_ = kEAGLColorFormatRGB565;
155 depthFormat_ = 0; // GL_DEPTH_COMPONENT24_OES;
156 multiSampling_= NO;
157 requestedSamples_ = 0;
158 size_ = [eaglLayer bounds].size;
159
160 if( ! [self setupSurfaceWithSharegroup:nil] ) {
161 [self release];
162 return nil;
163 }
164 }
165
166 return self;
167}
168
169-(BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup
170{
171 CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
172
173 eaglLayer.opaque = YES;
174 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
175 [NSNumber numberWithBool:preserveBackbuffer_], kEAGLDrawablePropertyRetainedBacking,
176 pixelformat_, kEAGLDrawablePropertyColorFormat, nil];
177
178
179 renderer_ = [[ES1Renderer alloc] initWithDepthFormat:depthFormat_
180 withPixelFormat:[self convertPixelFormat:pixelformat_]
181 withSharegroup:sharegroup
182 withMultiSampling:multiSampling_
183 withNumberOfSamples:requestedSamples_];
184 if (!renderer_)
185 return NO;
186
187 context_ = [renderer_ context];
188 [context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer];
189
190 discardFramebufferSupported_ = [[CCConfiguration sharedConfiguration] supportsDiscardFramebuffer];
191
192 return YES;
193}
194
195- (void) dealloc
196{
197 CCLOGINFO(@"cocos2d: deallocing %@", self);
198
199
200 [renderer_ release];
201 [super dealloc];
202}
203
204- (void) layoutSubviews
205{
206 size_ = [renderer_ backingSize];
207
208 [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer];
209
210 // Issue #914 #924
211 CCDirector *director = [CCDirector sharedDirector];
212 [director reshapeProjection:size_];
213
214 // Avoid flicker. Issue #350
215 [director performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES];
216}
217
218- (void) swapBuffers
219{
220 // IMPORTANT:
221 // - preconditions
222 // -> context_ MUST be the OpenGL context
223 // -> renderbuffer_ must be the the RENDER BUFFER
224
225#ifdef __IPHONE_4_0
226
227 if (multiSampling_)
228 {
229 /* Resolve from msaaFramebuffer to resolveFramebuffer */
230 //glDisable(GL_SCISSOR_TEST);
231 glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, [renderer_ msaaFrameBuffer]);
232 glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, [renderer_ defaultFrameBuffer]);
233 glResolveMultisampleFramebufferAPPLE();
234 }
235
236 if( discardFramebufferSupported_)
237 {
238 if (multiSampling_)
239 {
240 if (depthFormat_)
241 {
242 GLenum attachments[] = {GL_COLOR_ATTACHMENT0_OES, GL_DEPTH_ATTACHMENT_OES};
243 glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments);
244 }
245 else
246 {
247 GLenum attachments[] = {GL_COLOR_ATTACHMENT0_OES};
248 glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, attachments);
249 }
250
251 glBindRenderbufferOES(GL_RENDERBUFFER_OES, [renderer_ colorRenderBuffer]);
252
253 }
254
255 // not MSAA
256 else if (depthFormat_ ) {
257 GLenum attachments[] = { GL_DEPTH_ATTACHMENT_OES};
258 glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, 1, attachments);
259 }
260 }
261
262#endif // __IPHONE_4_0
263
264 if(![context_ presentRenderbuffer:GL_RENDERBUFFER_OES])
265 CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__);
266
267#if COCOS2D_DEBUG
268 CHECK_GL_ERROR();
269#endif
270
271 // We can safely re-bind the framebuffer here, since this will be the
272 // 1st instruction of the new main loop
273 if( multiSampling_ )
274 glBindFramebufferOES(GL_FRAMEBUFFER_OES, [renderer_ msaaFrameBuffer]);
275}
276
277- (unsigned int) convertPixelFormat:(NSString*) pixelFormat
278{
279 // define the pixel format
280 GLenum pFormat;
281
282
283 if([pixelFormat isEqualToString:@"EAGLColorFormat565"])
284 pFormat = GL_RGB565_OES;
285 else
286 pFormat = GL_RGBA8_OES;
287
288 return pFormat;
289}
290
291#pragma mark EAGLView - Point conversion
292
293- (CGPoint) convertPointFromViewToSurface:(CGPoint)point
294{
295 CGRect bounds = [self bounds];
296
297 return CGPointMake((point.x - bounds.origin.x) / bounds.size.width * size_.width, (point.y - bounds.origin.y) / bounds.size.height * size_.height);
298}
299
300- (CGRect) convertRectFromViewToSurface:(CGRect)rect
301{
302 CGRect bounds = [self bounds];
303
304 return CGRectMake((rect.origin.x - bounds.origin.x) / bounds.size.width * size_.width, (rect.origin.y - bounds.origin.y) / bounds.size.height * size_.height, rect.size.width / bounds.size.width * size_.width, rect.size.height / bounds.size.height * size_.height);
305}
306
307// Pass the touches to the superview
308#pragma mark EAGLView - Touch Delegate
309
310- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
311{
312 if(touchDelegate_)
313 {
314 [touchDelegate_ touchesBegan:touches withEvent:event];
315 }
316}
317
318- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
319{
320 if(touchDelegate_)
321 {
322 [touchDelegate_ touchesMoved:touches withEvent:event];
323 }
324}
325
326- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
327{
328 if(touchDelegate_)
329 {
330 [touchDelegate_ touchesEnded:touches withEvent:event];
331 }
332}
333- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
334{
335 if(touchDelegate_)
336 {
337 [touchDelegate_ touchesCancelled:touches withEvent:event];
338 }
339}
340
341@end
342
343#endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file
diff --git a/libs/cocos2d/Platforms/iOS/ES1Renderer.h b/libs/cocos2d/Platforms/iOS/ES1Renderer.h new file mode 100755 index 0000000..fd946a7 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/ES1Renderer.h
@@ -0,0 +1,72 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * File autogenerated with Xcode. Adapted for cocos2d needs.
27 */
28
29// Only compile this code on iOS. These files should NOT be included on your Mac project.
30// But in case they are included, it won't be compiled.
31#import <Availability.h>
32#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
33
34
35#import "ESRenderer.h"
36
37#import <OpenGLES/ES1/gl.h>
38#import <OpenGLES/ES1/glext.h>
39
40@interface ES1Renderer : NSObject <ESRenderer>
41{
42 // The pixel dimensions of the CAEAGLLayer
43 GLint backingWidth_;
44 GLint backingHeight_;
45
46 unsigned int samplesToUse_;
47 BOOL multiSampling_;
48
49 unsigned int depthFormat_;
50 unsigned int pixelFormat_;
51
52 // The OpenGL ES names for the framebuffer and renderbuffer used to render to this view
53 GLuint defaultFramebuffer_;
54 GLuint colorRenderbuffer_;
55 GLuint depthBuffer_;
56
57
58 //buffers for MSAA
59 GLuint msaaFramebuffer_;
60 GLuint msaaColorbuffer_;
61
62 EAGLContext *context_;
63}
64
65/** EAGLContext */
66@property (nonatomic,readonly) EAGLContext* context;
67
68- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer;
69
70@end
71
72#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/ES1Renderer.m b/libs/cocos2d/Platforms/iOS/ES1Renderer.m new file mode 100755 index 0000000..398d946 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/ES1Renderer.m
@@ -0,0 +1,259 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * File autogenerated with Xcode. Adapted for cocos2d needs.
27 */
28
29// Only compile this code on iOS. These files should NOT be included on your Mac project.
30// But in case they are included, it won't be compiled.
31#import <Availability.h>
32#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
33
34#import "ES1Renderer.h"
35#import "../../Support/OpenGL_Internal.h"
36#import "../../ccMacros.h"
37
38
39@interface ES1Renderer (private)
40
41- (GLenum) convertPixelFormat:(int) pixelFormat;
42
43@end
44
45
46@implementation ES1Renderer
47
48@synthesize context=context_;
49
50- (id) initWithDepthFormat:(unsigned int)depthFormat withPixelFormat:(unsigned int)pixelFormat withSharegroup:(EAGLSharegroup*)sharegroup withMultiSampling:(BOOL) multiSampling withNumberOfSamples:(unsigned int) requestedSamples
51{
52 if ((self = [super init]))
53 {
54 if ( sharegroup == nil )
55 {
56 context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
57 }
58 else
59 {
60 context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:sharegroup];
61 }
62
63 if (!context_ || ![EAGLContext setCurrentContext:context_])
64 {
65 [self release];
66 return nil;
67 }
68
69 // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
70 glGenFramebuffersOES(1, &defaultFramebuffer_);
71 NSAssert( defaultFramebuffer_, @"Can't create default frame buffer");
72 glGenRenderbuffersOES(1, &colorRenderbuffer_);
73 NSAssert( colorRenderbuffer_, @"Can't create default render buffer");
74
75 glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_);
76 glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
77 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer_);
78
79 depthFormat_ = depthFormat;
80
81 if( depthFormat_ ) {
82// glGenRenderbuffersOES(1, &depthBuffer_);
83// glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_);
84// glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, 100, 100);
85// glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_);
86
87 // default buffer
88// glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
89 }
90
91 pixelFormat_ = pixelFormat;
92 multiSampling_ = multiSampling;
93 if (multiSampling_)
94 {
95 GLint maxSamplesAllowed;
96 glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamplesAllowed);
97 samplesToUse_ = MIN(maxSamplesAllowed,requestedSamples);
98
99 /* Create the MSAA framebuffer (offscreen) */
100 glGenFramebuffersOES(1, &msaaFramebuffer_);
101 glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_);
102
103 }
104
105 CHECK_GL_ERROR();
106 }
107
108 return self;
109}
110
111- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
112{
113 // Allocate color buffer backing based on the current layer size
114
115 glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
116
117 if (![context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer])
118 {
119 CCLOG(@"failed to call context");
120 }
121
122 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth_);
123 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight_);
124
125 CCLOG(@"cocos2d: surface size: %dx%d", (int)backingWidth_, (int)backingHeight_);
126
127 if (multiSampling_)
128 {
129
130 if ( msaaColorbuffer_) {
131 glDeleteRenderbuffersOES(1, &msaaColorbuffer_);
132 msaaColorbuffer_ = 0;
133 }
134
135 /* Create the offscreen MSAA color buffer.
136 After rendering, the contents of this will be blitted into ColorRenderbuffer */
137
138 //msaaFrameBuffer needs to be binded
139 glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_);
140 glGenRenderbuffersOES(1, &msaaColorbuffer_);
141 glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaColorbuffer_);
142 glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_,pixelFormat_ , backingWidth_, backingHeight_);
143 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, msaaColorbuffer_);
144
145 if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
146 {
147 CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
148 return NO;
149 }
150 }
151
152 if (depthFormat_)
153 {
154 if( ! depthBuffer_ )
155 glGenRenderbuffersOES(1, &depthBuffer_);
156
157 glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_);
158 if( multiSampling_ )
159 glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_, depthFormat_,backingWidth_, backingHeight_);
160 else
161 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, backingWidth_, backingHeight_);
162 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_);
163
164 // bind color buffer
165 glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
166 }
167
168 glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_);
169
170 if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
171 {
172 CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
173 return NO;
174 }
175
176 CHECK_GL_ERROR();
177
178 return YES;
179}
180
181-(CGSize) backingSize
182{
183 return CGSizeMake( backingWidth_, backingHeight_);
184}
185
186- (NSString*) description
187{
188 return [NSString stringWithFormat:@"<%@ = %08X | size = %ix%i>", [self class], self, backingWidth_, backingHeight_];
189}
190
191
192- (void)dealloc
193{
194 CCLOGINFO(@"cocos2d: deallocing %@", self);
195
196 // Tear down GL
197 if(defaultFramebuffer_)
198 {
199 glDeleteFramebuffersOES(1, &defaultFramebuffer_);
200 defaultFramebuffer_ = 0;
201 }
202
203 if(colorRenderbuffer_)
204 {
205 glDeleteRenderbuffersOES(1, &colorRenderbuffer_);
206 colorRenderbuffer_ = 0;
207 }
208
209 if( depthBuffer_ )
210 {
211 glDeleteRenderbuffersOES(1, &depthBuffer_);
212 depthBuffer_ = 0;
213 }
214
215 if ( msaaColorbuffer_)
216 {
217 glDeleteRenderbuffersOES(1, &msaaColorbuffer_);
218 msaaColorbuffer_ = 0;
219 }
220
221 if ( msaaFramebuffer_)
222 {
223 glDeleteRenderbuffersOES(1, &msaaFramebuffer_);
224 msaaFramebuffer_ = 0;
225 }
226
227 // Tear down context
228 if ([EAGLContext currentContext] == context_)
229 [EAGLContext setCurrentContext:nil];
230
231 [context_ release];
232 context_ = nil;
233
234 [super dealloc];
235}
236
237- (unsigned int) colorRenderBuffer
238{
239 return colorRenderbuffer_;
240}
241
242- (unsigned int) defaultFrameBuffer
243{
244 return defaultFramebuffer_;
245}
246
247- (unsigned int) msaaFrameBuffer
248{
249 return msaaFramebuffer_;
250}
251
252- (unsigned int) msaaColorBuffer
253{
254 return msaaColorbuffer_;
255}
256
257@end
258
259#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/ESRenderer.h b/libs/cocos2d/Platforms/iOS/ESRenderer.h new file mode 100755 index 0000000..e612eee --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/ESRenderer.h
@@ -0,0 +1,54 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 *
26 * File autogenerated with Xcode. Adapted for cocos2d needs.
27 */
28
29// Only compile this code on iOS. These files should NOT be included on your Mac project.
30// But in case they are included, it won't be compiled.
31#import <Availability.h>
32#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
33
34#import <QuartzCore/QuartzCore.h>
35
36#import <OpenGLES/EAGL.h>
37#import <OpenGLES/EAGLDrawable.h>
38
39@protocol ESRenderer <NSObject>
40
41- (id) initWithDepthFormat:(unsigned int)depthFormat withPixelFormat:(unsigned int)pixelFormat withSharegroup:(EAGLSharegroup*)sharegroup withMultiSampling:(BOOL) multiSampling withNumberOfSamples:(unsigned int) requestedSamples;
42
43- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer;
44
45- (EAGLContext*) context;
46- (CGSize) backingSize;
47
48- (unsigned int) colorRenderBuffer;
49- (unsigned int) defaultFrameBuffer;
50- (unsigned int) msaaFrameBuffer;
51- (unsigned int) msaaColorBuffer;
52@end
53
54#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/glu.c b/libs/cocos2d/Platforms/iOS/glu.c new file mode 100755 index 0000000..2e00d5f --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/glu.c
@@ -0,0 +1,113 @@
1//
2// cocos2d (incomplete) GLU implementation
3//
4// gluLookAt and gluPerspective from:
5// http://jet.ro/creations (San Angeles Observation)
6//
7//
8
9// Only compile this code on iOS. These files should NOT be included on your Mac project.
10// But in case they are included, it won't be compiled.
11#import <Availability.h>
12#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
13
14#import <OpenGLES/ES1/gl.h>
15#import <math.h>
16#import "../../Support/OpenGL_Internal.h"
17#include "glu.h"
18
19void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
20{
21 GLfloat xmin, xmax, ymin, ymax;
22
23 ymax = zNear * (GLfloat)tanf(fovy * (float)M_PI / 360);
24 ymin = -ymax;
25 xmin = ymin * aspect;
26 xmax = ymax * aspect;
27
28 glFrustumf(xmin, xmax,
29 ymin, ymax,
30 zNear, zFar);
31}
32
33void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
34 GLfloat centerx, GLfloat centery, GLfloat centerz,
35 GLfloat upx, GLfloat upy, GLfloat upz)
36{
37 GLfloat m[16];
38 GLfloat x[3], y[3], z[3];
39 GLfloat mag;
40
41 /* Make rotation matrix */
42
43 /* Z vector */
44 z[0] = eyex - centerx;
45 z[1] = eyey - centery;
46 z[2] = eyez - centerz;
47 mag = (float)sqrtf(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
48 if (mag) {
49 z[0] /= mag;
50 z[1] /= mag;
51 z[2] /= mag;
52 }
53
54 /* Y vector */
55 y[0] = upx;
56 y[1] = upy;
57 y[2] = upz;
58
59 /* X vector = Y cross Z */
60 x[0] = y[1] * z[2] - y[2] * z[1];
61 x[1] = -y[0] * z[2] + y[2] * z[0];
62 x[2] = y[0] * z[1] - y[1] * z[0];
63
64 /* Recompute Y = Z cross X */
65 y[0] = z[1] * x[2] - z[2] * x[1];
66 y[1] = -z[0] * x[2] + z[2] * x[0];
67 y[2] = z[0] * x[1] - z[1] * x[0];
68
69 /* cross product gives area of parallelogram, which is < 1.0 for
70 * non-perpendicular unit-length vectors; so normalize x, y here
71 */
72
73 mag = (float)sqrtf(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
74 if (mag) {
75 x[0] /= mag;
76 x[1] /= mag;
77 x[2] /= mag;
78 }
79
80 mag = (float)sqrtf(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
81 if (mag) {
82 y[0] /= mag;
83 y[1] /= mag;
84 y[2] /= mag;
85 }
86
87#define M(row,col) m[col*4+row]
88 M(0, 0) = x[0];
89 M(0, 1) = x[1];
90 M(0, 2) = x[2];
91 M(0, 3) = 0.0f;
92 M(1, 0) = y[0];
93 M(1, 1) = y[1];
94 M(1, 2) = y[2];
95 M(1, 3) = 0.0f;
96 M(2, 0) = z[0];
97 M(2, 1) = z[1];
98 M(2, 2) = z[2];
99 M(2, 3) = 0.0f;
100 M(3, 0) = 0.0f;
101 M(3, 1) = 0.0f;
102 M(3, 2) = 0.0f;
103 M(3, 3) = 1.0f;
104#undef M
105
106 glMultMatrixf(m);
107
108
109 /* Translate Eye to Origin */
110 glTranslatef(-eyex, -eyey, -eyez);
111}
112
113#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
diff --git a/libs/cocos2d/Platforms/iOS/glu.h b/libs/cocos2d/Platforms/iOS/glu.h new file mode 100755 index 0000000..86dcac7 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/glu.h
@@ -0,0 +1,29 @@
1//
2// cocos2d GLU implementation
3//
4// implementation of GLU functions
5//
6#ifndef __COCOS2D_GLU_H
7#define __COCOS2D_GLU_H
8
9// Only compile this code on iOS. These files should NOT be included on your Mac project.
10// But in case they are included, it won't be compiled.
11#import <Availability.h>
12#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
13
14#import <OpenGLES/ES1/gl.h>
15
16/**
17 @file
18 cocos2d OpenGL GLU implementation
19 */
20
21/** OpenGL gluLookAt implementation */
22void gluLookAt(float eyeX, float eyeY, float eyeZ, float lookAtX, float lookAtY, float lookAtZ, float upX, float upY, float upZ);
23/** OpenGL gluPerspective implementation */
24void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
25
26#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
27
28#endif /* __COCOS2D_GLU_H */
29
diff --git a/libs/cocos2d/Support/CCArray.h b/libs/cocos2d/Support/CCArray.h new file mode 100755 index 0000000..0c7b2b8 --- /dev/null +++ b/libs/cocos2d/Support/CCArray.h
@@ -0,0 +1,106 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25
26#import "ccCArray.h"
27
28
29/** A faster alternative of NSArray.
30 CCArray uses internally a c-array.
31 @since v0.99.4
32 */
33
34
35/** @def CCARRAY_FOREACH
36 A convience macro to iterate over a CCArray using. It is faster than the "fast enumeration" interface.
37 @since v0.99.4
38 */
39
40#define CCARRAY_FOREACH(__array__, __object__) \
41if (__array__ && __array__->data->num > 0) \
42for(id *__arr__ = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \
43 __arr__ <= end && ((__object__ = *__arr__) != nil || true); \
44 __arr__++)
45
46@interface CCArray : NSObject <NSFastEnumeration, NSCoding, NSCopying>
47{
48 @public ccArray *data;
49}
50
51+ (id) array;
52+ (id) arrayWithCapacity:(NSUInteger)capacity;
53+ (id) arrayWithArray:(CCArray*)otherArray;
54+ (id) arrayWithNSArray:(NSArray*)otherArray;
55
56
57- (id) initWithCapacity:(NSUInteger)capacity;
58- (id) initWithArray:(CCArray*)otherArray;
59- (id) initWithNSArray:(NSArray*)otherArray;
60
61
62// Querying an Array
63
64- (NSUInteger) count;
65- (NSUInteger) capacity;
66- (NSUInteger) indexOfObject:(id)object;
67- (id) objectAtIndex:(NSUInteger)index;
68- (BOOL) containsObject:(id)object;
69- (id) randomObject;
70- (id) lastObject;
71- (NSArray*) getNSArray;
72
73
74// Adding Objects
75
76- (void) addObject:(id)object;
77- (void) addObjectsFromArray:(CCArray*)otherArray;
78- (void) addObjectsFromNSArray:(NSArray*)otherArray;
79- (void) insertObject:(id)object atIndex:(NSUInteger)index;
80
81
82// Removing Objects
83
84- (void) removeLastObject;
85- (void) removeObject:(id)object;
86- (void) removeObjectAtIndex:(NSUInteger)index;
87- (void) removeObjectsInArray:(CCArray*)otherArray;
88- (void) removeAllObjects;
89- (void) fastRemoveObject:(id)object;
90- (void) fastRemoveObjectAtIndex:(NSUInteger)index;
91
92
93// Rearranging Content
94
95- (void) exchangeObject:(id)object1 withObject:(id)object2;
96- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2;
97- (void) reverseObjects;
98- (void) reduceMemoryFootprint;
99
100// Sending Messages to Elements
101
102- (void) makeObjectsPerformSelector:(SEL)aSelector;
103- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object;
104
105
106@end
diff --git a/libs/cocos2d/Support/CCArray.m b/libs/cocos2d/Support/CCArray.m new file mode 100755 index 0000000..a48a5f3 --- /dev/null +++ b/libs/cocos2d/Support/CCArray.m
@@ -0,0 +1,290 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#import "CCArray.h"
26#import "../ccMacros.h"
27
28
29@implementation CCArray
30
31+ (id) array
32{
33 return [[[self alloc] init] autorelease];
34}
35
36+ (id) arrayWithCapacity:(NSUInteger)capacity
37{
38 return [[[self alloc] initWithCapacity:capacity] autorelease];
39}
40
41+ (id) arrayWithArray:(CCArray*)otherArray
42{
43 return [[(CCArray*)[self alloc] initWithArray:otherArray] autorelease];
44}
45
46+ (id) arrayWithNSArray:(NSArray*)otherArray
47{
48 return [[(CCArray*)[self alloc] initWithNSArray:otherArray] autorelease];
49}
50
51- (id) init
52{
53 self = [self initWithCapacity:2];
54 return self;
55}
56
57- (id) initWithCapacity:(NSUInteger)capacity
58{
59 self = [super init];
60 if (self != nil) {
61 data = ccArrayNew(capacity);
62 }
63 return self;
64}
65
66- (id) initWithArray:(CCArray*)otherArray
67{
68 self = [self initWithCapacity:otherArray->data->num];
69 if (self != nil) {
70 [self addObjectsFromArray:otherArray];
71 }
72 return self;
73}
74
75- (id) initWithNSArray:(NSArray*)otherArray
76{
77 self = [self initWithCapacity:otherArray.count];
78 if (self != nil) {
79 [self addObjectsFromNSArray:otherArray];
80 }
81 return self;
82}
83
84- (id) initWithCoder:(NSCoder*)coder
85{
86 self = [self initWithNSArray:[coder decodeObjectForKey:@"nsarray"]];
87 return self;
88}
89
90
91#pragma mark Querying an Array
92
93- (NSUInteger) count
94{
95 return data->num;
96}
97
98- (NSUInteger) capacity
99{
100 return data->max;
101}
102
103- (NSUInteger) indexOfObject:(id)object
104{
105 return ccArrayGetIndexOfObject(data, object);
106}
107
108- (id) objectAtIndex:(NSUInteger)index
109{
110 NSAssert2( index < data->num, @"index out of range in objectAtIndex(%d), index %i", data->num, index );
111
112 return data->arr[index];
113}
114
115- (BOOL) containsObject:(id)object
116{
117 return ccArrayContainsObject(data, object);
118}
119
120- (id) lastObject
121{
122 if( data->num > 0 )
123 return data->arr[data->num-1];
124 return nil;
125}
126
127- (id) randomObject
128{
129 if(data->num==0) return nil;
130 return data->arr[(int)(data->num*CCRANDOM_0_1())];
131}
132
133- (NSArray*) getNSArray
134{
135 return [NSArray arrayWithObjects:data->arr count:data->num];
136}
137
138
139#pragma mark Adding Objects
140
141- (void) addObject:(id)object
142{
143 ccArrayAppendObjectWithResize(data, object);
144}
145
146- (void) addObjectsFromArray:(CCArray*)otherArray
147{
148 ccArrayAppendArrayWithResize(data, otherArray->data);
149}
150
151- (void) addObjectsFromNSArray:(NSArray*)otherArray
152{
153 ccArrayEnsureExtraCapacity(data, otherArray.count);
154 for(id object in otherArray)
155 ccArrayAppendObject(data, object);
156}
157
158- (void) insertObject:(id)object atIndex:(NSUInteger)index
159{
160 ccArrayInsertObjectAtIndex(data, object, index);
161}
162
163
164#pragma mark Removing Objects
165
166- (void) removeObject:(id)object
167{
168 ccArrayRemoveObject(data, object);
169}
170
171- (void) removeObjectAtIndex:(NSUInteger)index
172{
173 ccArrayRemoveObjectAtIndex(data, index);
174}
175
176- (void) fastRemoveObject:(id)object
177{
178 ccArrayFastRemoveObject(data, object);
179}
180
181- (void) fastRemoveObjectAtIndex:(NSUInteger)index
182{
183 ccArrayFastRemoveObjectAtIndex(data, index);
184}
185
186- (void) removeObjectsInArray:(CCArray*)otherArray
187{
188 ccArrayRemoveArray(data, otherArray->data);
189}
190
191- (void) removeLastObject
192{
193 NSAssert( data->num > 0, @"no objects added" );
194
195 ccArrayRemoveObjectAtIndex(data, data->num-1);
196}
197
198- (void) removeAllObjects
199{
200 ccArrayRemoveAllObjects(data);
201}
202
203
204#pragma mark Rearranging Content
205
206- (void) exchangeObject:(id)object1 withObject:(id)object2
207{
208 NSUInteger index1 = ccArrayGetIndexOfObject(data, object1);
209 if(index1 == NSNotFound) return;
210 NSUInteger index2 = ccArrayGetIndexOfObject(data, object2);
211 if(index2 == NSNotFound) return;
212
213 ccArraySwapObjectsAtIndexes(data, index1, index2);
214}
215
216- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2
217{
218 ccArraySwapObjectsAtIndexes(data, index1, index2);
219}
220
221- (void) reverseObjects
222{
223 if (data->num > 1)
224 {
225 //floor it since in case of a oneven number the number of swaps stays the same
226 int count = (int) floorf(data->num/2.f);
227 NSUInteger maxIndex = data->num - 1;
228
229 for (int i = 0; i < count ; i++)
230 {
231 ccArraySwapObjectsAtIndexes(data, i, maxIndex);
232 maxIndex--;
233 }
234 }
235}
236
237- (void) reduceMemoryFootprint
238{
239 ccArrayShrink(data);
240}
241
242#pragma mark Sending Messages to Elements
243
244- (void) makeObjectsPerformSelector:(SEL)aSelector
245{
246 ccArrayMakeObjectsPerformSelector(data, aSelector);
247}
248
249- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object
250{
251 ccArrayMakeObjectsPerformSelectorWithObject(data, aSelector, object);
252}
253
254
255#pragma mark CCArray - NSFastEnumeration protocol
256
257- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
258{
259 if(state->state == 1) return 0;
260
261 state->mutationsPtr = (unsigned long *)self;
262 state->itemsPtr = &data->arr[0];
263 state->state = 1;
264 return data->num;
265}
266
267
268#pragma mark CCArray - NSCopying protocol
269
270- (id)copyWithZone:(NSZone *)zone
271{
272 NSArray *nsArray = [self getNSArray];
273 CCArray *newArray = [[[self class] allocWithZone:zone] initWithNSArray:nsArray];
274 return newArray;
275}
276
277- (void) encodeWithCoder:(NSCoder *)coder
278{
279 [coder encodeObject:[self getNSArray] forKey:@"nsarray"];
280}
281
282#pragma mark
283
284- (void) dealloc
285{
286 ccArrayFree(data);
287 [super dealloc];
288}
289
290@end
diff --git a/libs/cocos2d/Support/CCFileUtils.h b/libs/cocos2d/Support/CCFileUtils.h new file mode 100755 index 0000000..0455202 --- /dev/null +++ b/libs/cocos2d/Support/CCFileUtils.h
@@ -0,0 +1,62 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Foundation/Foundation.h>
29
30
31/** Helper class to handle file operations */
32@interface CCFileUtils : NSObject
33{
34}
35
36/** Returns the fullpath of an filename.
37
38 If this method is when Retina Display is enabled, then the
39 Retina Display suffix will be appended to the file (See ccConfig.h).
40
41 If the Retina Display image doesn't exist, then it will return the "non-Retina Display" image
42
43 */
44+(NSString*) fullPathFromRelativePath:(NSString*) relPath;
45@end
46
47/** loads a file into memory.
48 the caller should release the allocated buffer.
49
50 @returns the size of the allocated buffer
51 @since v0.99.5
52 */
53NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out);
54
55
56/** removes the HD suffix from a path
57
58 @returns NSString * without the HD suffix
59 @since v0.99.5
60 */
61NSString *ccRemoveHDSuffixFromFile( NSString *path );
62
diff --git a/libs/cocos2d/Support/CCFileUtils.m b/libs/cocos2d/Support/CCFileUtils.m new file mode 100755 index 0000000..6d33799 --- /dev/null +++ b/libs/cocos2d/Support/CCFileUtils.m
@@ -0,0 +1,169 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Availability.h>
29#import "CCFileUtils.h"
30#import "../CCConfiguration.h"
31#import "../ccMacros.h"
32#import "../ccConfig.h"
33
34static NSFileManager *__localFileManager=nil;
35
36//
37NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out)
38{
39 NSCAssert( out, @"ccLoadFileIntoMemory: invalid 'out' parameter");
40 NSCAssert( &*out, @"ccLoadFileIntoMemory: invalid 'out' parameter");
41
42 size_t size = 0;
43 FILE *f = fopen(filename, "rb");
44 if( !f ) {
45 *out = NULL;
46 return -1;
47 }
48
49 fseek(f, 0, SEEK_END);
50 size = ftell(f);
51 fseek(f, 0, SEEK_SET);
52
53 *out = malloc(size);
54 size_t read = fread(*out, 1, size, f);
55 if( read != size ) {
56 free(*out);
57 *out = NULL;
58 return -1;
59 }
60
61 fclose(f);
62
63 return size;
64}
65
66NSString *ccRemoveHDSuffixFromFile( NSString *path )
67{
68#if CC_IS_RETINA_DISPLAY_SUPPORTED
69
70 if( CC_CONTENT_SCALE_FACTOR() == 2 ) {
71
72 NSString *name = [path lastPathComponent];
73
74 // check if path already has the suffix.
75 if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
76
77 CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
78
79 NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX withString:@""];
80
81 NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent];
82 return [pathWithoutLastname stringByAppendingPathComponent:newLastname];
83 }
84 }
85
86#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
87
88 return path;
89
90}
91
92
93@implementation CCFileUtils
94
95+(void) initialize
96{
97 if( self == [CCFileUtils class] )
98 __localFileManager = [[NSFileManager alloc] init];
99}
100
101+(NSString*) getDoubleResolutionImage:(NSString*)path
102{
103#if CC_IS_RETINA_DISPLAY_SUPPORTED
104
105 if( CC_CONTENT_SCALE_FACTOR() == 2 )
106 {
107
108 NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
109 NSString *name = [pathWithoutExtension lastPathComponent];
110
111 // check if path already has the suffix.
112 if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
113
114 CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
115 return path;
116 }
117
118
119 NSString *extension = [path pathExtension];
120
121 if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] )
122 {
123 // All ccz / gz files should be in the format filename.xxx.ccz
124 // so we need to pull off the .xxx part of the extension as well
125 extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension];
126 pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
127 }
128
129
130 NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX];
131 retinaName = [retinaName stringByAppendingPathExtension:extension];
132
133 if( [__localFileManager fileExistsAtPath:retinaName] )
134 return retinaName;
135
136 CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] );
137 }
138
139#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
140
141 return path;
142}
143
144+(NSString*) fullPathFromRelativePath:(NSString*) relPath
145{
146 NSAssert(relPath != nil, @"CCFileUtils: Invalid path");
147
148 NSString *fullpath = nil;
149
150 // only if it is not an absolute path
151 if( ! [relPath isAbsolutePath] )
152 {
153 NSString *file = [relPath lastPathComponent];
154 NSString *imageDirectory = [relPath stringByDeletingLastPathComponent];
155
156 fullpath = [[NSBundle mainBundle] pathForResource:file
157 ofType:nil
158 inDirectory:imageDirectory];
159 }
160
161 if (fullpath == nil)
162 fullpath = relPath;
163
164 fullpath = [self getDoubleResolutionImage:fullpath];
165
166 return fullpath;
167}
168
169@end
diff --git a/libs/cocos2d/Support/CCProfiling.h b/libs/cocos2d/Support/CCProfiling.h new file mode 100755 index 0000000..b241fb9 --- /dev/null +++ b/libs/cocos2d/Support/CCProfiling.h
@@ -0,0 +1,53 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28#import <sys/time.h>
29
30@class CCProfilingTimer;
31
32@interface CCProfiler : NSObject {
33 NSMutableArray* activeTimers;
34}
35
36+ (CCProfiler*)sharedProfiler;
37+ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance;
38+ (void)releaseTimer:(CCProfilingTimer*)timer;
39- (void)displayTimers;
40
41@end
42
43
44@interface CCProfilingTimer : NSObject {
45 NSString* name;
46 struct timeval startTime;
47 double averageTime;
48}
49
50@end
51
52extern void CCProfilingBeginTimingBlock(CCProfilingTimer* timer);
53extern void CCProfilingEndTimingBlock(CCProfilingTimer* timer);
diff --git a/libs/cocos2d/Support/CCProfiling.m b/libs/cocos2d/Support/CCProfiling.m new file mode 100755 index 0000000..13c8c81 --- /dev/null +++ b/libs/cocos2d/Support/CCProfiling.m
@@ -0,0 +1,117 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "../ccConfig.h"
27
28#if CC_ENABLE_PROFILERS
29
30#import "CCProfiling.h"
31
32@interface CCProfilingTimer()
33- (id)initWithName:(NSString*)timerName andInstance:(id)instance;
34@end
35
36@implementation CCProfiler
37
38static CCProfiler* g_sharedProfiler;
39
40+ (CCProfiler*)sharedProfiler {
41 if (!g_sharedProfiler)
42 g_sharedProfiler = [[CCProfiler alloc] init];
43
44 return g_sharedProfiler;
45}
46
47+ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance {
48 CCProfiler* p = [CCProfiler sharedProfiler];
49 CCProfilingTimer* t = [[CCProfilingTimer alloc] initWithName:timerName andInstance:instance];
50 [p->activeTimers addObject:t];
51 [t release];
52 return t;
53}
54
55+ (void)releaseTimer:(CCProfilingTimer*)timer {
56 CCProfiler* p = [CCProfiler sharedProfiler];
57 [p->activeTimers removeObject:timer];
58}
59
60- (id)init {
61 if (!(self = [super init])) return nil;
62
63 activeTimers = [[NSMutableArray alloc] init];
64
65 return self;
66}
67
68- (void)dealloc {
69 [activeTimers release];
70 [super dealloc];
71}
72
73- (void)displayTimers {
74 for (id timer in activeTimers) {
75 printf("%s\n", [[timer description] cStringUsingEncoding:[NSString defaultCStringEncoding]]);
76 }
77}
78
79@end
80
81@implementation CCProfilingTimer
82
83- (id)initWithName:(NSString*)timerName andInstance:(id)instance {
84 if (!(self = [super init])) return nil;
85
86 name = [[NSString stringWithFormat:@"%@ (0x%.8x)", timerName, instance] retain];
87
88 return self;
89}
90
91- (void)dealloc {
92 [name release];
93 [super dealloc];
94}
95
96- (NSString*)description {
97 return [NSString stringWithFormat:@"%@ : avg time, %fms", name, averageTime];
98}
99
100void CCProfilingBeginTimingBlock(CCProfilingTimer* timer) {
101 gettimeofday(&timer->startTime, NULL);
102}
103
104typedef unsigned int uint32;
105void CCProfilingEndTimingBlock(CCProfilingTimer* timer) {
106 struct timeval currentTime;
107 gettimeofday(&currentTime, NULL);
108 timersub(&currentTime, &timer->startTime, &currentTime);
109 double duration = currentTime.tv_sec * 1000.0 + currentTime.tv_usec / 1000.0;
110
111 // return in milliseconds
112 timer->averageTime = (timer->averageTime + duration) / 2.0f;
113}
114
115@end
116
117#endif
diff --git a/libs/cocos2d/Support/CGPointExtension.h b/libs/cocos2d/Support/CGPointExtension.h new file mode 100755 index 0000000..96edeb7 --- /dev/null +++ b/libs/cocos2d/Support/CGPointExtension.h
@@ -0,0 +1,334 @@
1/* cocos2d for iPhone
2 * http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2007 Scott Lembcke
5 *
6 * Copyright (c) 2010 Lam Pham
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27/*
28 * Some of the functions were based on Chipmunk's cpVect.h.
29 */
30
31/**
32 @file
33 CGPoint extensions based on Chipmunk's cpVect file.
34 These extensions work both with CGPoint and cpVect.
35
36 The "ccp" prefix means: "CoCos2d Point"
37
38 Examples:
39 - ccpAdd( ccp(1,1), ccp(2,2) ); // preferred cocos2d way
40 - ccpAdd( CGPointMake(1,1), CGPointMake(2,2) ); // also ok but more verbose
41
42 - cpvadd( cpv(1,1), cpv(2,2) ); // way of the chipmunk
43 - ccpAdd( cpv(1,1), cpv(2,2) ); // mixing chipmunk and cocos2d (avoid)
44 - cpvadd( CGPointMake(1,1), CGPointMake(2,2) ); // mixing chipmunk and CG (avoid)
45 */
46
47#import <Availability.h>
48
49#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
50#import <CoreGraphics/CGGeometry.h>
51#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
52#import <Foundation/Foundation.h>
53#endif
54
55#import <math.h>
56#import <objc/objc.h>
57
58#ifdef __cplusplus
59extern "C" {
60#endif
61
62/** Helper macro that creates a CGPoint
63 @return CGPoint
64 @since v0.7.2
65 */
66#define ccp(__X__,__Y__) CGPointMake(__X__,__Y__)
67
68
69/** Returns opposite of point.
70 @return CGPoint
71 @since v0.7.2
72 */
73static inline CGPoint
74ccpNeg(const CGPoint v)
75{
76 return ccp(-v.x, -v.y);
77}
78
79/** Calculates sum of two points.
80 @return CGPoint
81 @since v0.7.2
82 */
83static inline CGPoint
84ccpAdd(const CGPoint v1, const CGPoint v2)
85{
86 return ccp(v1.x + v2.x, v1.y + v2.y);
87}
88
89/** Calculates difference of two points.
90 @return CGPoint
91 @since v0.7.2
92 */
93static inline CGPoint
94ccpSub(const CGPoint v1, const CGPoint v2)
95{
96 return ccp(v1.x - v2.x, v1.y - v2.y);
97}
98
99/** Returns point multiplied by given factor.
100 @return CGPoint
101 @since v0.7.2
102 */
103static inline CGPoint
104ccpMult(const CGPoint v, const CGFloat s)
105{
106 return ccp(v.x*s, v.y*s);
107}
108
109/** Calculates midpoint between two points.
110 @return CGPoint
111 @since v0.7.2
112 */
113static inline CGPoint
114ccpMidpoint(const CGPoint v1, const CGPoint v2)
115{
116 return ccpMult(ccpAdd(v1, v2), 0.5f);
117}
118
119/** Calculates dot product of two points.
120 @return CGFloat
121 @since v0.7.2
122 */
123static inline CGFloat
124ccpDot(const CGPoint v1, const CGPoint v2)
125{
126 return v1.x*v2.x + v1.y*v2.y;
127}
128
129/** Calculates cross product of two points.
130 @return CGFloat
131 @since v0.7.2
132 */
133static inline CGFloat
134ccpCross(const CGPoint v1, const CGPoint v2)
135{
136 return v1.x*v2.y - v1.y*v2.x;
137}
138
139/** Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0
140 @return CGPoint
141 @since v0.7.2
142 */
143static inline CGPoint
144ccpPerp(const CGPoint v)
145{
146 return ccp(-v.y, v.x);
147}
148
149/** Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0
150 @return CGPoint
151 @since v0.7.2
152 */
153static inline CGPoint
154ccpRPerp(const CGPoint v)
155{
156 return ccp(v.y, -v.x);
157}
158
159/** Calculates the projection of v1 over v2.
160 @return CGPoint
161 @since v0.7.2
162 */
163static inline CGPoint
164ccpProject(const CGPoint v1, const CGPoint v2)
165{
166 return ccpMult(v2, ccpDot(v1, v2)/ccpDot(v2, v2));
167}
168
169/** Rotates two points.
170 @return CGPoint
171 @since v0.7.2
172 */
173static inline CGPoint
174ccpRotate(const CGPoint v1, const CGPoint v2)
175{
176 return ccp(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
177}
178
179/** Unrotates two points.
180 @return CGPoint
181 @since v0.7.2
182 */
183static inline CGPoint
184ccpUnrotate(const CGPoint v1, const CGPoint v2)
185{
186 return ccp(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
187}
188
189/** Calculates the square length of a CGPoint (not calling sqrt() )
190 @return CGFloat
191 @since v0.7.2
192 */
193static inline CGFloat
194ccpLengthSQ(const CGPoint v)
195{
196 return ccpDot(v, v);
197}
198
199/** Calculates distance between point an origin
200 @return CGFloat
201 @since v0.7.2
202 */
203CGFloat ccpLength(const CGPoint v);
204
205/** Calculates the distance between two points
206 @return CGFloat
207 @since v0.7.2
208 */
209CGFloat ccpDistance(const CGPoint v1, const CGPoint v2);
210
211/** Returns point multiplied to a length of 1.
212 @return CGPoint
213 @since v0.7.2
214 */
215CGPoint ccpNormalize(const CGPoint v);
216
217/** Converts radians to a normalized vector.
218 @return CGPoint
219 @since v0.7.2
220 */
221CGPoint ccpForAngle(const CGFloat a);
222
223/** Converts a vector to radians.
224 @return CGFloat
225 @since v0.7.2
226 */
227CGFloat ccpToAngle(const CGPoint v);
228
229
230/** Clamp a value between from and to.
231 @since v0.99.1
232 */
233float clampf(float value, float min_inclusive, float max_inclusive);
234
235/** Clamp a point between from and to.
236 @since v0.99.1
237 */
238CGPoint ccpClamp(CGPoint p, CGPoint from, CGPoint to);
239
240/** Quickly convert CGSize to a CGPoint
241 @since v0.99.1
242 */
243CGPoint ccpFromSize(CGSize s);
244
245/** Run a math operation function on each point component
246 * absf, fllorf, ceilf, roundf
247 * any function that has the signature: float func(float);
248 * For example: let's try to take the floor of x,y
249 * ccpCompOp(p,floorf);
250 @since v0.99.1
251 */
252CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float));
253
254/** Linear Interpolation between two points a and b
255 @returns
256 alpha == 0 ? a
257 alpha == 1 ? b
258 otherwise a value between a..b
259 @since v0.99.1
260 */
261CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha);
262
263
264/** @returns if points have fuzzy equality which means equal with some degree of variance.
265 @since v0.99.1
266 */
267BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float variance);
268
269
270/** Multiplies a nd b components, a.x*b.x, a.y*b.y
271 @returns a component-wise multiplication
272 @since v0.99.1
273 */
274CGPoint ccpCompMult(CGPoint a, CGPoint b);
275
276/** @returns the signed angle in radians between two vector directions
277 @since v0.99.1
278 */
279float ccpAngleSigned(CGPoint a, CGPoint b);
280
281/** @returns the angle in radians between two vector directions
282 @since v0.99.1
283*/
284float ccpAngle(CGPoint a, CGPoint b);
285
286/** Rotates a point counter clockwise by the angle around a pivot
287 @param v is the point to rotate
288 @param pivot is the pivot, naturally
289 @param angle is the angle of rotation cw in radians
290 @returns the rotated point
291 @since v0.99.1
292 */
293CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle);
294
295/** A general line-line intersection test
296 @param p1
297 is the startpoint for the first line P1 = (p1 - p2)
298 @param p2
299 is the endpoint for the first line P1 = (p1 - p2)
300 @param p3
301 is the startpoint for the second line P2 = (p3 - p4)
302 @param p4
303 is the endpoint for the second line P2 = (p3 - p4)
304 @param s
305 is the range for a hitpoint in P1 (pa = p1 + s*(p2 - p1))
306 @param t
307 is the range for a hitpoint in P3 (pa = p2 + t*(p4 - p3))
308 @return bool
309 indicating successful intersection of a line
310 note that to truly test intersection for segments we have to make
311 sure that s & t lie within [0..1] and for rays, make sure s & t > 0
312 the hit point is p3 + t * (p4 - p3);
313 the hit point also is p1 + s * (p2 - p1);
314 @since v0.99.1
315 */
316BOOL ccpLineIntersect(CGPoint p1, CGPoint p2,
317 CGPoint p3, CGPoint p4,
318 float *s, float *t);
319
320/*
321 ccpSegmentIntersect returns YES if Segment A-B intersects with segment C-D
322 @since v1.0.0
323 */
324BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D);
325
326/*
327 ccpIntersectPoint returns the intersection point of line A-B, C-D
328 @since v1.0.0
329 */
330CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D);
331
332#ifdef __cplusplus
333}
334#endif
diff --git a/libs/cocos2d/Support/CGPointExtension.m b/libs/cocos2d/Support/CGPointExtension.m new file mode 100755 index 0000000..b06859d --- /dev/null +++ b/libs/cocos2d/Support/CGPointExtension.m
@@ -0,0 +1,196 @@
1/* cocos2d for iPhone
2 * http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2007 Scott Lembcke
5 *
6 * Copyright (c) 2010 Lam Pham
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include "stdio.h"
28#include "math.h"
29
30#import "../ccMacros.h" // CC_SWAP
31#include "CGPointExtension.h"
32
33#define kCGPointEpsilon FLT_EPSILON
34
35CGFloat
36ccpLength(const CGPoint v)
37{
38 return sqrtf(ccpLengthSQ(v));
39}
40
41CGFloat
42ccpDistance(const CGPoint v1, const CGPoint v2)
43{
44 return ccpLength(ccpSub(v1, v2));
45}
46
47CGPoint
48ccpNormalize(const CGPoint v)
49{
50 return ccpMult(v, 1.0f/ccpLength(v));
51}
52
53CGPoint
54ccpForAngle(const CGFloat a)
55{
56 return ccp(cosf(a), sinf(a));
57}
58
59CGFloat
60ccpToAngle(const CGPoint v)
61{
62 return atan2f(v.y, v.x);
63}
64
65CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha)
66{
67 return ccpAdd(ccpMult(a, 1.f - alpha), ccpMult(b, alpha));
68}
69
70float clampf(float value, float min_inclusive, float max_inclusive)
71{
72 if (min_inclusive > max_inclusive) {
73 CC_SWAP(min_inclusive,max_inclusive);
74 }
75 return value < min_inclusive ? min_inclusive : value < max_inclusive? value : max_inclusive;
76}
77
78CGPoint ccpClamp(CGPoint p, CGPoint min_inclusive, CGPoint max_inclusive)
79{
80 return ccp(clampf(p.x,min_inclusive.x,max_inclusive.x), clampf(p.y, min_inclusive.y, max_inclusive.y));
81}
82
83CGPoint ccpFromSize(CGSize s)
84{
85 return ccp(s.width, s.height);
86}
87
88CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float))
89{
90 return ccp(opFunc(p.x), opFunc(p.y));
91}
92
93BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float var)
94{
95 if(a.x - var <= b.x && b.x <= a.x + var)
96 if(a.y - var <= b.y && b.y <= a.y + var)
97 return true;
98 return false;
99}
100
101CGPoint ccpCompMult(CGPoint a, CGPoint b)
102{
103 return ccp(a.x * b.x, a.y * b.y);
104}
105
106float ccpAngleSigned(CGPoint a, CGPoint b)
107{
108 CGPoint a2 = ccpNormalize(a);
109 CGPoint b2 = ccpNormalize(b);
110 float angle = atan2f(a2.x * b2.y - a2.y * b2.x, ccpDot(a2, b2));
111 if( fabs(angle) < kCGPointEpsilon ) return 0.f;
112 return angle;
113}
114
115CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle)
116{
117 CGPoint r = ccpSub(v, pivot);
118 float cosa = cosf(angle), sina = sinf(angle);
119 float t = r.x;
120 r.x = t*cosa - r.y*sina + pivot.x;
121 r.y = t*sina + r.y*cosa + pivot.y;
122 return r;
123}
124
125
126BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D)
127{
128 float S, T;
129
130 if( ccpLineIntersect(A, B, C, D, &S, &T )
131 && (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f) )
132 return YES;
133
134 return NO;
135}
136
137CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D)
138{
139 float S, T;
140
141 if( ccpLineIntersect(A, B, C, D, &S, &T) ) {
142 // Point of intersection
143 CGPoint P;
144 P.x = A.x + S * (B.x - A.x);
145 P.y = A.y + S * (B.y - A.y);
146 return P;
147 }
148
149 return CGPointZero;
150}
151
152BOOL ccpLineIntersect(CGPoint A, CGPoint B,
153 CGPoint C, CGPoint D,
154 float *S, float *T)
155{
156 // FAIL: Line undefined
157 if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) return NO;
158
159 const float BAx = B.x - A.x;
160 const float BAy = B.y - A.y;
161 const float DCx = D.x - C.x;
162 const float DCy = D.y - C.y;
163 const float ACx = A.x - C.x;
164 const float ACy = A.y - C.y;
165
166 const float denom = DCy*BAx - DCx*BAy;
167
168 *S = DCx*ACy - DCy*ACx;
169 *T = BAx*ACy - BAy*ACx;
170
171 if (denom == 0) {
172 if (*S == 0 || *T == 0) {
173 // Lines incident
174 return YES;
175 }
176 // Lines parallel and not incident
177 return NO;
178 }
179
180 *S = *S / denom;
181 *T = *T / denom;
182
183 // Point of intersection
184 // CGPoint P;
185 // P.x = A.x + *S * (B.x - A.x);
186 // P.y = A.y + *S * (B.y - A.y);
187
188 return YES;
189}
190
191float ccpAngle(CGPoint a, CGPoint b)
192{
193 float angle = acosf(ccpDot(ccpNormalize(a), ccpNormalize(b)));
194 if( fabs(angle) < kCGPointEpsilon ) return 0.f;
195 return angle;
196}
diff --git a/libs/cocos2d/Support/OpenGL_Internal.h b/libs/cocos2d/Support/OpenGL_Internal.h new file mode 100755 index 0000000..4789683 --- /dev/null +++ b/libs/cocos2d/Support/OpenGL_Internal.h
@@ -0,0 +1,80 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentation
14seeds.
15
16=====================
17
18File: OpenGL_Internal.h
19Abstract: This file is included for support purposes and isn't necessary for
20understanding this sample.
21
22Version: 1.0
23
24Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
25("Apple") in consideration of your agreement to the following terms, and your
26use, installation, modification or redistribution of this Apple software
27constitutes acceptance of these terms. If you do not agree with these terms,
28please do not use, install, modify or redistribute this Apple software.
29
30In consideration of your agreement to abide by the following terms, and subject
31to these terms, Apple grants you a personal, non-exclusive license, under
32Apple's copyrights in this original Apple software (the "Apple Software"), to
33use, reproduce, modify and redistribute the Apple Software, with or without
34modifications, in source and/or binary forms; provided that if you redistribute
35the Apple Software in its entirety and without modifications, you must retain
36this notice and the following text and disclaimers in all such redistributions
37of the Apple Software.
38Neither the name, trademarks, service marks or logos of Apple Inc. may be used
39to endorse or promote products derived from the Apple Software without specific
40prior written permission from Apple. Except as expressly stated in this notice,
41no other rights or licenses, express or implied, are granted by Apple herein,
42including but not limited to any patent rights that may be infringed by your
43derivative works or by other works in which the Apple Software may be
44incorporated.
45
46The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
47WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
48WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
50COMBINATION WITH YOUR PRODUCTS.
51
52IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
53CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
54GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
56DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
57CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
58APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
60Copyright (C) 2008 Apple Inc. All Rights Reserved.
61
62*/
63
64/* Generic error reporting */
65#define REPORT_ERROR(__FORMAT__, ...) printf("%s: %s\n", __FUNCTION__, [[NSString stringWithFormat:__FORMAT__, __VA_ARGS__] UTF8String])
66
67/* EAGL and GL functions calling wrappers that log on error */
68#define CALL_EAGL_FUNCTION(__FUNC__, ...) ({ EAGLError __error = __FUNC__( __VA_ARGS__ ); if(__error != kEAGLErrorSuccess) printf("%s() called from %s returned error %i\n", #__FUNC__, __FUNCTION__, __error); (__error ? NO : YES); })
69//#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? NO : YES); })
70#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); })
71
72/* Optional delegate methods support */
73#ifndef __DELEGATE_IVAR__
74#define __DELEGATE_IVAR__ _delegate
75#endif
76#ifndef __DELEGATE_METHODS_IVAR__
77#define __DELEGATE_METHODS_IVAR__ _delegateMethods
78#endif
79#define TEST_DELEGATE_METHOD_BIT(__BIT__) (self->__DELEGATE_METHODS_IVAR__ & (1 << __BIT__))
80#define SET_DELEGATE_METHOD_BIT(__BIT__, __NAME__) { if([self->__DELEGATE_IVAR__ respondsToSelector:@selector(__NAME__)]) self->__DELEGATE_METHODS_IVAR__ |= (1 << __BIT__); else self->__DELEGATE_METHODS_IVAR__ &= ~(1 << __BIT__); }
diff --git a/libs/cocos2d/Support/TGAlib.h b/libs/cocos2d/Support/TGAlib.h new file mode 100755 index 0000000..247084e --- /dev/null +++ b/libs/cocos2d/Support/TGAlib.h
@@ -0,0 +1,55 @@
1//
2// TGA lib for cocos2d-iphone
3//
4// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
5//
6
7//#ifndef TGA_LIB
8//#define TGA_LIB
9
10/**
11 @file
12 TGA image support
13 */
14
15enum {
16 TGA_OK,
17 TGA_ERROR_FILE_OPEN,
18 TGA_ERROR_READING_FILE,
19 TGA_ERROR_INDEXED_COLOR,
20 TGA_ERROR_MEMORY,
21 TGA_ERROR_COMPRESSED_FILE,
22};
23
24/** TGA format */
25typedef struct sImageTGA {
26 int status;
27 unsigned char type, pixelDepth;
28
29 /** map width */
30 short int width;
31
32 /** map height */
33 short int height;
34
35 /** raw data */
36 unsigned char *imageData;
37 int flipped;
38} tImageTGA;
39
40/// load the image header fields. We only keep those that matter!
41void tgaLoadHeader(FILE *file, tImageTGA *info);
42
43/// loads the image pixels. You shouldn't call this function directly
44void tgaLoadImageData(FILE *file, tImageTGA *info);
45
46/// this is the function to call when we want to load an image
47tImageTGA * tgaLoad(const char *filename);
48
49// /converts RGB to greyscale
50void tgaRGBtogreyscale(tImageTGA *info);
51
52/// releases the memory used for the image
53void tgaDestroy(tImageTGA *info);
54
55//#endif // TGA_LIB
diff --git a/libs/cocos2d/Support/TGAlib.m b/libs/cocos2d/Support/TGAlib.m new file mode 100755 index 0000000..11303b4 --- /dev/null +++ b/libs/cocos2d/Support/TGAlib.m
@@ -0,0 +1,274 @@
1//
2// TGA lib for cocos2d-iphone
3//
4// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
5//
6// TGA RLE compression support by Ernesto Corvi
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#import "TGAlib.h"
13
14void tgaLoadRLEImageData(FILE *file, tImageTGA *info);
15void tgaFlipImage( tImageTGA *info );
16
17// load the image header fields. We only keep those that matter!
18void tgaLoadHeader(FILE *file, tImageTGA *info) {
19 unsigned char cGarbage;
20 short int iGarbage;
21
22 fread(&cGarbage, sizeof(unsigned char), 1, file);
23 fread(&cGarbage, sizeof(unsigned char), 1, file);
24
25 // type must be 2 or 3
26 fread(&info->type, sizeof(unsigned char), 1, file);
27
28 fread(&iGarbage, sizeof(short int), 1, file);
29 fread(&iGarbage, sizeof(short int), 1, file);
30 fread(&cGarbage, sizeof(unsigned char), 1, file);
31 fread(&iGarbage, sizeof(short int), 1, file);
32 fread(&iGarbage, sizeof(short int), 1, file);
33
34 fread(&info->width, sizeof(short int), 1, file);
35 fread(&info->height, sizeof(short int), 1, file);
36 fread(&info->pixelDepth, sizeof(unsigned char), 1, file);
37
38 fread(&cGarbage, sizeof(unsigned char), 1, file);
39
40 info->flipped = 0;
41 if ( cGarbage & 0x20 ) info->flipped = 1;
42}
43
44// loads the image pixels. You shouldn't call this function directly
45void tgaLoadImageData(FILE *file, tImageTGA *info) {
46
47 int mode,total,i;
48 unsigned char aux;
49
50 // mode equal the number of components for each pixel
51 mode = info->pixelDepth / 8;
52 // total is the number of unsigned chars we'll have to read
53 total = info->height * info->width * mode;
54
55 fread(info->imageData,sizeof(unsigned char),total,file);
56
57 // mode=3 or 4 implies that the image is RGB(A). However TGA
58 // stores it as BGR(A) so we'll have to swap R and B.
59 if (mode >= 3)
60 for (i=0; i < total; i+= mode) {
61 aux = info->imageData[i];
62 info->imageData[i] = info->imageData[i+2];
63 info->imageData[i+2] = aux;
64 }
65}
66
67// loads the RLE encoded image pixels. You shouldn't call this function directly
68void tgaLoadRLEImageData(FILE *file, tImageTGA *info)
69{
70 unsigned int mode,total,i, index = 0;
71 unsigned char aux[4], runlength = 0;
72 unsigned int skip = 0, flag = 0;
73
74 // mode equal the number of components for each pixel
75 mode = info->pixelDepth / 8;
76 // total is the number of unsigned chars we'll have to read
77 total = info->height * info->width;
78
79 for( i = 0; i < total; i++ )
80 {
81 // if we have a run length pending, run it
82 if ( runlength != 0 )
83 {
84 // we do, update the run length count
85 runlength--;
86 skip = (flag != 0);
87 }
88 else
89 {
90 // otherwise, read in the run length token
91 if ( fread(&runlength,sizeof(unsigned char),1,file) != 1 )
92 return;
93
94 // see if it's a RLE encoded sequence
95 flag = runlength & 0x80;
96 if ( flag ) runlength -= 128;
97 skip = 0;
98 }
99
100 // do we need to skip reading this pixel?
101 if ( !skip )
102 {
103 // no, read in the pixel data
104 if ( fread(aux,sizeof(unsigned char),mode,file) != mode )
105 return;
106
107 // mode=3 or 4 implies that the image is RGB(A). However TGA
108 // stores it as BGR(A) so we'll have to swap R and B.
109 if ( mode >= 3 )
110 {
111 unsigned char tmp;
112
113 tmp = aux[0];
114 aux[0] = aux[2];
115 aux[2] = tmp;
116 }
117 }
118
119 // add the pixel to our image
120 memcpy(&info->imageData[index], aux, mode);
121 index += mode;
122 }
123}
124
125void tgaFlipImage( tImageTGA *info )
126{
127 // mode equal the number of components for each pixel
128 int mode = info->pixelDepth / 8;
129 int rowbytes = info->width*mode;
130 unsigned char *row = (unsigned char *)malloc(rowbytes);
131 int y;
132
133 if (row == NULL) return;
134
135 for( y = 0; y < (info->height/2); y++ )
136 {
137 memcpy(row, &info->imageData[y*rowbytes],rowbytes);
138 memcpy(&info->imageData[y*rowbytes], &info->imageData[(info->height-(y+1))*rowbytes], rowbytes);
139 memcpy(&info->imageData[(info->height-(y+1))*rowbytes], row, rowbytes);
140 }
141
142 free(row);
143 info->flipped = 0;
144}
145
146// this is the function to call when we want to load an image
147tImageTGA * tgaLoad(const char *filename) {
148
149 FILE *file;
150 tImageTGA *info;
151 int mode,total;
152
153 // allocate memory for the info struct and check!
154 info = (tImageTGA *)malloc(sizeof(tImageTGA));
155 if (info == NULL)
156 return(NULL);
157
158
159 // open the file for reading (binary mode)
160 file = fopen(filename, "rb");
161 if (file == NULL) {
162 info->status = TGA_ERROR_FILE_OPEN;
163 return(info);
164 }
165
166 // load the header
167 tgaLoadHeader(file,info);
168
169 // check for errors when loading the header
170 if (ferror(file)) {
171 info->status = TGA_ERROR_READING_FILE;
172 fclose(file);
173 return(info);
174 }
175
176 // check if the image is color indexed
177 if (info->type == 1) {
178 info->status = TGA_ERROR_INDEXED_COLOR;
179 fclose(file);
180 return(info);
181 }
182 // check for other types (compressed images)
183 if ((info->type != 2) && (info->type !=3) && (info->type !=10) ) {
184 info->status = TGA_ERROR_COMPRESSED_FILE;
185 fclose(file);
186 return(info);
187 }
188
189 // mode equals the number of image components
190 mode = info->pixelDepth / 8;
191 // total is the number of unsigned chars to read
192 total = info->height * info->width * mode;
193 // allocate memory for image pixels
194 info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
195 total);
196
197 // check to make sure we have the memory required
198 if (info->imageData == NULL) {
199 info->status = TGA_ERROR_MEMORY;
200 fclose(file);
201 return(info);
202 }
203 // finally load the image pixels
204 if ( info->type == 10 )
205 tgaLoadRLEImageData(file, info);
206 else
207 tgaLoadImageData(file,info);
208
209 // check for errors when reading the pixels
210 if (ferror(file)) {
211 info->status = TGA_ERROR_READING_FILE;
212 fclose(file);
213 return(info);
214 }
215 fclose(file);
216 info->status = TGA_OK;
217
218 if ( info->flipped )
219 {
220 tgaFlipImage( info );
221 if ( info->flipped ) info->status = TGA_ERROR_MEMORY;
222 }
223
224 return(info);
225}
226
227// converts RGB to greyscale
228void tgaRGBtogreyscale(tImageTGA *info) {
229
230 int mode,i,j;
231
232 unsigned char *newImageData;
233
234 // if the image is already greyscale do nothing
235 if (info->pixelDepth == 8)
236 return;
237
238 // compute the number of actual components
239 mode = info->pixelDepth / 8;
240
241 // allocate an array for the new image data
242 newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
243 info->height * info->width);
244 if (newImageData == NULL) {
245 return;
246 }
247
248 // convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
249 for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
250 newImageData[j] =
251 (unsigned char)(0.30 * info->imageData[i] +
252 0.59 * info->imageData[i+1] +
253 0.11 * info->imageData[i+2]);
254
255
256 //free old image data
257 free(info->imageData);
258
259 // reassign pixelDepth and type according to the new image type
260 info->pixelDepth = 8;
261 info->type = 3;
262 // reassing imageData to the new array.
263 info->imageData = newImageData;
264}
265
266// releases the memory used for the image
267void tgaDestroy(tImageTGA *info) {
268
269 if (info != NULL) {
270 if (info->imageData != NULL)
271 free(info->imageData);
272 free(info);
273 }
274}
diff --git a/libs/cocos2d/Support/TransformUtils.h b/libs/cocos2d/Support/TransformUtils.h new file mode 100755 index 0000000..49fde35 --- /dev/null +++ b/libs/cocos2d/Support/TransformUtils.h
@@ -0,0 +1,37 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Availability.h>
27
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#import <UIKit/UIKit.h>
30#import <OpenGLES/ES1/gl.h>
31#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
32#import <OpenGL/gl.h>
33#import <Foundation/Foundation.h>
34#endif
35
36void CGAffineToGL(const CGAffineTransform *t, GLfloat *m);
37void GLToCGAffine(const GLfloat *m, CGAffineTransform *t);
diff --git a/libs/cocos2d/Support/TransformUtils.m b/libs/cocos2d/Support/TransformUtils.m new file mode 100755 index 0000000..9caecf0 --- /dev/null +++ b/libs/cocos2d/Support/TransformUtils.m
@@ -0,0 +1,46 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "TransformUtils.h"
28
29void CGAffineToGL(const CGAffineTransform *t, GLfloat *m)
30{
31 // | m[0] m[4] m[8] m[12] | | m11 m21 m31 m41 | | a c 0 tx |
32 // | m[1] m[5] m[9] m[13] | | m12 m22 m32 m42 | | b d 0 ty |
33 // | m[2] m[6] m[10] m[14] | <=> | m13 m23 m33 m43 | <=> | 0 0 1 0 |
34 // | m[3] m[7] m[11] m[15] | | m14 m24 m34 m44 | | 0 0 0 1 |
35
36 m[2] = m[3] = m[6] = m[7] = m[8] = m[9] = m[11] = m[14] = 0.0f;
37 m[10] = m[15] = 1.0f;
38 m[0] = t->a; m[4] = t->c; m[12] = t->tx;
39 m[1] = t->b; m[5] = t->d; m[13] = t->ty;
40}
41
42void GLToCGAffine(const GLfloat *m, CGAffineTransform *t)
43{
44 t->a = m[0]; t->c = m[4]; t->tx = m[12];
45 t->b = m[1]; t->d = m[5]; t->ty = m[13];
46}
diff --git a/libs/cocos2d/Support/ZipUtils.h b/libs/cocos2d/Support/ZipUtils.h new file mode 100755 index 0000000..363f911 --- /dev/null +++ b/libs/cocos2d/Support/ZipUtils.h
@@ -0,0 +1,91 @@
1/* cocos2d for iPhone
2 *
3 * http://www.cocos2d-iphone.org
4 *
5 *
6 * inflateMemory_ based on zlib example code
7 * http://www.zlib.net
8 *
9 * Some ideas were taken from:
10 * http://themanaworld.org/
11 * from the mapreader.cpp file
12 *
13 */
14
15#ifndef __CC_ZIP_UTILS_H
16#define __CC_ZIP_UTILS_H
17
18#import <stdint.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24 /* XXX: pragma pack ??? */
25 /** @struct CCZHeader
26 */
27 struct CCZHeader {
28 uint8_t sig[4]; // signature. Should be 'CCZ!' 4 bytes
29 uint16_t compression_type; // should 0
30 uint16_t version; // should be 2 (although version type==1 is also supported)
31 uint32_t reserved; // Reserverd for users.
32 uint32_t len; // size of the uncompressed file
33 };
34
35 enum {
36 CCZ_COMPRESSION_ZLIB, // zlib format.
37 CCZ_COMPRESSION_BZIP2, // bzip2 format (not supported yet)
38 CCZ_COMPRESSION_GZIP, // gzip format (not supported yet)
39 CCZ_COMPRESSION_NONE, // plain (not supported yet)
40 };
41
42/** @file
43 * Zip helper functions
44 */
45
46/**
47 * Inflates either zlib or gzip deflated memory. The inflated memory is
48 * expected to be freed by the caller.
49 *
50 * It will allocate 256k for the destination buffer. If it is not enought it will multiply the previous buffer size per 2, until there is enough memory.
51 * @returns the length of the deflated buffer
52 *
53 @since v0.8.1
54 */
55int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out);
56
57/**
58 * Inflates either zlib or gzip deflated memory. The inflated memory is
59 * expected to be freed by the caller.
60 *
61 * outLenghtHint is assumed to be the needed room to allocate the inflated buffer.
62 *
63 * @returns the length of the deflated buffer
64 *
65 @since v1.0.0
66 */
67int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLenghtHint );
68
69
70/** inflates a GZip file into memory
71 *
72 * @returns the length of the deflated buffer
73 *
74 * @since v0.99.5
75 */
76int ccInflateGZipFile(const char *filename, unsigned char **out);
77
78/** inflates a CCZ file into memory
79 *
80 * @returns the length of the deflated buffer
81 *
82 * @since v0.99.5
83 */
84int ccInflateCCZFile(const char *filename, unsigned char **out);
85
86
87#ifdef __cplusplus
88}
89#endif
90
91#endif // __CC_ZIP_UTILS_H
diff --git a/libs/cocos2d/Support/ZipUtils.m b/libs/cocos2d/Support/ZipUtils.m new file mode 100755 index 0000000..ccd8bbc --- /dev/null +++ b/libs/cocos2d/Support/ZipUtils.m
@@ -0,0 +1,251 @@
1/* cocos2d for iPhone
2 *
3 * http://www.cocos2d-iphone.org
4 *
5 *
6 * Inflates either zlib or gzip deflated memory. The inflated memory is
7 * expected to be freed by the caller.
8 *
9 * inflateMemory_ based on zlib example code
10 * http://www.zlib.net
11 *
12 * Some ideas were taken from:
13 * http://themanaworld.org/
14 * from the mapreader.cpp file
15 */
16
17#import <Availability.h>
18
19#import <zlib.h>
20#import <stdlib.h>
21#import <assert.h>
22#import <stdio.h>
23
24#import "ZipUtils.h"
25#import "CCFileUtils.h"
26#import "../ccMacros.h"
27
28// memory in iPhone is precious
29// Should buffer factor be 1.5 instead of 2 ?
30#define BUFFER_INC_FACTOR (2)
31
32static int inflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength, unsigned int outLenghtHint )
33{
34 /* ret value */
35 int err = Z_OK;
36
37 int bufferSize = outLenghtHint;
38 *out = (unsigned char*) malloc(bufferSize);
39
40 z_stream d_stream; /* decompression stream */
41 d_stream.zalloc = (alloc_func)0;
42 d_stream.zfree = (free_func)0;
43 d_stream.opaque = (voidpf)0;
44
45 d_stream.next_in = in;
46 d_stream.avail_in = inLength;
47 d_stream.next_out = *out;
48 d_stream.avail_out = bufferSize;
49
50 /* window size to hold 256k */
51 if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
52 return err;
53
54 for (;;) {
55 err = inflate(&d_stream, Z_NO_FLUSH);
56
57 if (err == Z_STREAM_END)
58 break;
59
60 switch (err) {
61 case Z_NEED_DICT:
62 err = Z_DATA_ERROR;
63 case Z_DATA_ERROR:
64 case Z_MEM_ERROR:
65 inflateEnd(&d_stream);
66 return err;
67 }
68
69 // not enough memory ?
70 if (err != Z_STREAM_END) {
71
72 unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR);
73
74 /* not enough memory, ouch */
75 if (! tmp ) {
76 CCLOG(@"cocos2d: ZipUtils: realloc failed");
77 inflateEnd(&d_stream);
78 return Z_MEM_ERROR;
79 }
80 /* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */
81 *out = tmp;
82
83 d_stream.next_out = *out + bufferSize;
84 d_stream.avail_out = bufferSize;
85 bufferSize *= BUFFER_INC_FACTOR;
86 }
87 }
88
89
90 *outLength = bufferSize - d_stream.avail_out;
91 err = inflateEnd(&d_stream);
92 return err;
93}
94
95int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLengthHint )
96{
97 unsigned int outLength = 0;
98 int err = inflateMemoryWithHint(in, inLength, out, &outLength, outLengthHint );
99
100 if (err != Z_OK || *out == NULL) {
101 if (err == Z_MEM_ERROR)
102 CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!");
103
104 else if (err == Z_VERSION_ERROR)
105 CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!");
106
107 else if (err == Z_DATA_ERROR)
108 CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!");
109
110 else
111 CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!");
112
113 free(*out);
114 *out = NULL;
115 outLength = 0;
116 }
117
118 return outLength;
119}
120
121int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
122{
123 // 256k for hint
124 return ccInflateMemoryWithHint(in, inLength, out, 256 * 1024 );
125}
126
127int ccInflateGZipFile(const char *path, unsigned char **out)
128{
129 int len;
130 unsigned int offset = 0;
131
132 NSCAssert( out, @"ccInflateGZipFile: invalid 'out' parameter");
133 NSCAssert( &*out, @"ccInflateGZipFile: invalid 'out' parameter");
134
135 gzFile inFile = gzopen(path, "rb");
136 if( inFile == NULL ) {
137 CCLOG(@"cocos2d: ZipUtils: error open gzip file: %s", path);
138 return -1;
139 }
140
141 /* 512k initial decompress buffer */
142 int bufferSize = 512 * 1024;
143 unsigned int totalBufferSize = bufferSize;
144
145 *out = malloc( bufferSize );
146 if( ! out ) {
147 CCLOG(@"cocos2d: ZipUtils: out of memory");
148 return -1;
149 }
150
151 for (;;) {
152 len = gzread(inFile, *out + offset, bufferSize);
153 if (len < 0) {
154 CCLOG(@"cocos2d: ZipUtils: error in gzread");
155 free( *out );
156 *out = NULL;
157 return -1;
158 }
159 if (len == 0)
160 break;
161
162 offset += len;
163
164 // finish reading the file
165 if( len < bufferSize )
166 break;
167
168 bufferSize *= BUFFER_INC_FACTOR;
169 totalBufferSize += bufferSize;
170 unsigned char *tmp = realloc(*out, totalBufferSize );
171
172 if( ! tmp ) {
173 CCLOG(@"cocos2d: ZipUtils: out of memory");
174 free( *out );
175 *out = NULL;
176 return -1;
177 }
178
179 *out = tmp;
180 }
181
182 if (gzclose(inFile) != Z_OK)
183 CCLOG(@"cocos2d: ZipUtils: gzclose failed");
184
185 return offset;
186}
187
188int ccInflateCCZFile(const char *path, unsigned char **out)
189{
190 NSCAssert( out, @"ccInflateCCZFile: invalid 'out' parameter");
191 NSCAssert( &*out, @"ccInflateCCZFile: invalid 'out' parameter");
192
193 // load file into memory
194 unsigned char *compressed = NULL;
195 NSInteger fileLen = ccLoadFileIntoMemory( path, &compressed );
196 if( fileLen < 0 ) {
197 CCLOG(@"cocos2d: Error loading CCZ compressed file");
198 }
199
200 struct CCZHeader *header = (struct CCZHeader*) compressed;
201
202 // verify header
203 if( header->sig[0] != 'C' || header->sig[1] != 'C' || header->sig[2] != 'Z' || header->sig[3] != '!' ) {
204 CCLOG(@"cocos2d: Invalid CCZ file");
205 free(compressed);
206 return -1;
207 }
208
209 // verify header version
210 uint16_t version = CFSwapInt16BigToHost( header->version );
211 if( version > 2 ) {
212 CCLOG(@"cocos2d: Unsupported CCZ header format");
213 free(compressed);
214 return -1;
215 }
216
217 // verify compression format
218 if( CFSwapInt16BigToHost(header->compression_type) != CCZ_COMPRESSION_ZLIB ) {
219 CCLOG(@"cocos2d: CCZ Unsupported compression method");
220 free(compressed);
221 return -1;
222 }
223
224 uint32_t len = CFSwapInt32BigToHost( header->len );
225
226 *out = malloc( len );
227 if(! *out )
228 {
229 CCLOG(@"cocos2d: CCZ: Failed to allocate memory for texture");
230 free(compressed);
231 return -1;
232 }
233
234
235 uLongf destlen = len;
236 uLongf source = (uLongf) compressed + sizeof(*header);
237 int ret = uncompress(*out, &destlen, (Bytef*)source, fileLen - sizeof(*header) );
238
239 free( compressed );
240
241 if( ret != Z_OK )
242 {
243 CCLOG(@"cocos2d: CCZ: Failed to uncompress data");
244 free( *out );
245 *out = NULL;
246 return -1;
247 }
248
249
250 return len;
251}
diff --git a/libs/cocos2d/Support/base64.c b/libs/cocos2d/Support/base64.c new file mode 100755 index 0000000..9aa52a6 --- /dev/null +++ b/libs/cocos2d/Support/base64.c
@@ -0,0 +1,93 @@
1/*
2 public domain BASE64 code
3
4 modified for cocos2d-iphone: http://www.cocos2d-iphone.org
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9
10#include "base64.h"
11
12unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13
14int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len );
15
16int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len )
17{
18 static char inalphabet[256], decoder[256];
19 int i, bits, c, char_count, errors = 0;
20 unsigned int input_idx = 0;
21 unsigned int output_idx = 0;
22
23 for (i = (sizeof alphabet) - 1; i >= 0 ; i--) {
24 inalphabet[alphabet[i]] = 1;
25 decoder[alphabet[i]] = i;
26 }
27
28 char_count = 0;
29 bits = 0;
30 for( input_idx=0; input_idx < input_len ; input_idx++ ) {
31 c = input[ input_idx ];
32 if (c == '=')
33 break;
34 if (c > 255 || ! inalphabet[c])
35 continue;
36 bits += decoder[c];
37 char_count++;
38 if (char_count == 4) {
39 output[ output_idx++ ] = (bits >> 16);
40 output[ output_idx++ ] = ((bits >> 8) & 0xff);
41 output[ output_idx++ ] = ( bits & 0xff);
42 bits = 0;
43 char_count = 0;
44 } else {
45 bits <<= 6;
46 }
47 }
48
49 if( c == '=' ) {
50 switch (char_count) {
51 case 1:
52 fprintf(stderr, "base64Decode: encoding incomplete: at least 2 bits missing");
53 errors++;
54 break;
55 case 2:
56 output[ output_idx++ ] = ( bits >> 10 );
57 break;
58 case 3:
59 output[ output_idx++ ] = ( bits >> 16 );
60 output[ output_idx++ ] = (( bits >> 8 ) & 0xff);
61 break;
62 }
63 } else if ( input_idx < input_len ) {
64 if (char_count) {
65 fprintf(stderr, "base64 encoding incomplete: at least %d bits truncated",
66 ((4 - char_count) * 6));
67 errors++;
68 }
69 }
70
71 *output_len = output_idx;
72 return errors;
73}
74
75int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out)
76{
77 unsigned int outLength = 0;
78
79 //should be enough to store 6-bit buffers in 8-bit buffers
80 *out = malloc( inLength * 3.0f / 4.0f + 1 );
81 if( *out ) {
82 int ret = _base64Decode(in, inLength, *out, &outLength);
83
84 if (ret > 0 )
85 {
86 printf("Base64Utils: error decoding");
87 free(*out);
88 *out = NULL;
89 outLength = 0;
90 }
91 }
92 return outLength;
93}
diff --git a/libs/cocos2d/Support/base64.h b/libs/cocos2d/Support/base64.h new file mode 100755 index 0000000..d30878e --- /dev/null +++ b/libs/cocos2d/Support/base64.h
@@ -0,0 +1,33 @@
1/*
2 public domain BASE64 code
3
4 modified for cocos2d-iphone: http://www.cocos2d-iphone.org
5 */
6
7#ifndef __CC_BASE64_DECODE_H
8#define __CC_BASE64_DECODE_H
9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14
15/** @file
16 base64 helper functions
17 */
18
19/**
20 * Decodes a 64base encoded memory. The decoded memory is
21 * expected to be freed by the caller.
22 *
23 * @returns the length of the out buffer
24 *
25 @since v0.8.1
26 */
27int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out);
28
29#ifdef __cplusplus
30}
31#endif
32
33#endif // __CC_BASE64_DECODE_H
diff --git a/libs/cocos2d/Support/ccCArray.h b/libs/cocos2d/Support/ccCArray.h new file mode 100755 index 0000000..20d9633 --- /dev/null +++ b/libs/cocos2d/Support/ccCArray.h
@@ -0,0 +1,447 @@
1/* Copyright (c) 2007 Scott Lembcke
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 * SOFTWARE.
20 */
21
22/**
23 @file
24 Based on Chipmunk cpArray.
25 ccArray is a faster alternative to NSMutableArray, it does pretty much the
26 same thing (stores NSObjects and retains/releases them appropriately). It's
27 faster because:
28 - it uses a plain C interface so it doesn't incur Objective-c messaging overhead
29 - it assumes you know what you're doing, so it doesn't spend time on safety checks
30 (index out of bounds, required capacity etc.)
31 - comparisons are done using pointer equality instead of isEqual
32
33 There are 2 kind of functions:
34 - ccArray functions that manipulates objective-c objects (retain and release are performanced)
35 - ccCArray functions that manipulates values like if they were standard C structures (no retain/release is performed)
36 */
37
38#ifndef CC_ARRAY_H
39#define CC_ARRAY_H
40
41#import <Foundation/Foundation.h>
42
43#import <stdlib.h>
44#import <string.h>
45
46
47#pragma mark -
48#pragma mark ccArray for Objects
49
50// Easy integration
51#define CCARRAYDATA_FOREACH(__array__, __object__) \
52__object__=__array__->arr[0]; for(NSUInteger i=0, num=__array__->num; i<num; i++, __object__=__array__->arr[i]) \
53
54
55typedef struct ccArray {
56 NSUInteger num, max;
57 id *arr;
58} ccArray;
59
60/** Allocates and initializes a new array with specified capacity */
61static inline ccArray* ccArrayNew(NSUInteger capacity) {
62 if (capacity == 0)
63 capacity = 1;
64
65 ccArray *arr = (ccArray*)malloc( sizeof(ccArray) );
66 arr->num = 0;
67 arr->arr = (id*) malloc( capacity * sizeof(id) );
68 arr->max = capacity;
69
70 return arr;
71}
72
73static inline void ccArrayRemoveAllObjects(ccArray *arr);
74
75/** Frees array after removing all remaining objects. Silently ignores nil arr. */
76static inline void ccArrayFree(ccArray *arr)
77{
78 if( arr == nil ) return;
79
80 ccArrayRemoveAllObjects(arr);
81
82 free(arr->arr);
83 free(arr);
84}
85
86/** Doubles array capacity */
87static inline void ccArrayDoubleCapacity(ccArray *arr)
88{
89 arr->max *= 2;
90 id *newArr = (id *)realloc( arr->arr, arr->max * sizeof(id) );
91 // will fail when there's not enough memory
92 NSCAssert(newArr != NULL, @"ccArrayDoubleCapacity failed. Not enough memory");
93 arr->arr = newArr;
94}
95
96/** Increases array capacity such that max >= num + extra. */
97static inline void ccArrayEnsureExtraCapacity(ccArray *arr, NSUInteger extra)
98{
99 while (arr->max < arr->num + extra)
100 ccArrayDoubleCapacity(arr);
101}
102
103/** shrinks the array so the memory footprint corresponds with the number of items */
104static inline void ccArrayShrink(ccArray *arr)
105{
106 NSUInteger newSize;
107
108 //only resize when necessary
109 if (arr->max > arr->num && !(arr->num==0 && arr->max==1))
110 {
111 if (arr->num!=0)
112 {
113 newSize=arr->num;
114 arr->max=arr->num;
115 }
116 else
117 {//minimum capacity of 1, with 0 elements the array would be free'd by realloc
118 newSize=1;
119 arr->max=1;
120 }
121
122 arr->arr = (id*) realloc(arr->arr,newSize * sizeof(id) );
123 NSCAssert(arr->arr!=NULL,@"could not reallocate the memory");
124 }
125}
126
127/** Returns index of first occurence of object, NSNotFound if object not found. */
128static inline NSUInteger ccArrayGetIndexOfObject(ccArray *arr, id object)
129{
130 for( NSUInteger i = 0; i < arr->num; i++)
131 if( arr->arr[i] == object ) return i;
132
133 return NSNotFound;
134}
135
136/** Returns a Boolean value that indicates whether object is present in array. */
137static inline BOOL ccArrayContainsObject(ccArray *arr, id object)
138{
139 return ccArrayGetIndexOfObject(arr, object) != NSNotFound;
140}
141
142/** Appends an object. Bahaviour undefined if array doesn't have enough capacity. */
143static inline void ccArrayAppendObject(ccArray *arr, id object)
144{
145 arr->arr[arr->num] = [object retain];
146 arr->num++;
147}
148
149/** Appends an object. Capacity of arr is increased if needed. */
150static inline void ccArrayAppendObjectWithResize(ccArray *arr, id object)
151{
152 ccArrayEnsureExtraCapacity(arr, 1);
153 ccArrayAppendObject(arr, object);
154}
155
156/** Appends objects from plusArr to arr. Behaviour undefined if arr doesn't have
157 enough capacity. */
158static inline void ccArrayAppendArray(ccArray *arr, ccArray *plusArr)
159{
160 for( NSUInteger i = 0; i < plusArr->num; i++)
161 ccArrayAppendObject(arr, plusArr->arr[i]);
162}
163
164/** Appends objects from plusArr to arr. Capacity of arr is increased if needed. */
165static inline void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr)
166{
167 ccArrayEnsureExtraCapacity(arr, plusArr->num);
168 ccArrayAppendArray(arr, plusArr);
169}
170
171/** Inserts an object at index */
172static inline void ccArrayInsertObjectAtIndex(ccArray *arr, id object, NSUInteger index)
173{
174 NSCAssert(index<=arr->num, @"Invalid index. Out of bounds");
175
176 ccArrayEnsureExtraCapacity(arr, 1);
177
178 NSUInteger remaining = arr->num - index;
179 if( remaining > 0)
180 memmove(&arr->arr[index+1], &arr->arr[index], sizeof(id) * remaining );
181
182 arr->arr[index] = [object retain];
183 arr->num++;
184}
185
186/** Swaps two objects */
187static inline void ccArraySwapObjectsAtIndexes(ccArray *arr, NSUInteger index1, NSUInteger index2)
188{
189 NSCAssert(index1 < arr->num, @"(1) Invalid index. Out of bounds");
190 NSCAssert(index2 < arr->num, @"(2) Invalid index. Out of bounds");
191
192 id object1 = arr->arr[index1];
193
194 arr->arr[index1] = arr->arr[index2];
195 arr->arr[index2] = object1;
196}
197
198/** Removes all objects from arr */
199static inline void ccArrayRemoveAllObjects(ccArray *arr)
200{
201 while( arr->num > 0 )
202 [arr->arr[--arr->num] release];
203}
204
205/** Removes object at specified index and pushes back all subsequent objects.
206 Behaviour undefined if index outside [0, num-1]. */
207static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
208{
209 [arr->arr[index] release];
210 arr->num--;
211
212 NSUInteger remaining = arr->num - index;
213 if(remaining>0)
214 memmove(&arr->arr[index], &arr->arr[index+1], remaining * sizeof(id));
215}
216
217/** Removes object at specified index and fills the gap with the last object,
218 thereby avoiding the need to push back subsequent objects.
219 Behaviour undefined if index outside [0, num-1]. */
220static inline void ccArrayFastRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
221{
222 [arr->arr[index] release];
223 NSUInteger last = --arr->num;
224 arr->arr[index] = arr->arr[last];
225}
226
227static inline void ccArrayFastRemoveObject(ccArray *arr, id object)
228{
229 NSUInteger index = ccArrayGetIndexOfObject(arr, object);
230 if (index != NSNotFound)
231 ccArrayFastRemoveObjectAtIndex(arr, index);
232}
233
234/** Searches for the first occurance of object and removes it. If object is not
235 found the function has no effect. */
236static inline void ccArrayRemoveObject(ccArray *arr, id object)
237{
238 NSUInteger index = ccArrayGetIndexOfObject(arr, object);
239 if (index != NSNotFound)
240 ccArrayRemoveObjectAtIndex(arr, index);
241}
242
243/** Removes from arr all objects in minusArr. For each object in minusArr, the
244 first matching instance in arr will be removed. */
245static inline void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr)
246{
247 for( NSUInteger i = 0; i < minusArr->num; i++)
248 ccArrayRemoveObject(arr, minusArr->arr[i]);
249}
250
251/** Removes from arr all objects in minusArr. For each object in minusArr, all
252 matching instances in arr will be removed. */
253static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr)
254{
255 NSUInteger back = 0;
256
257 for( NSUInteger i = 0; i < arr->num; i++) {
258 if( ccArrayContainsObject(minusArr, arr->arr[i]) ) {
259 [arr->arr[i] release];
260 back++;
261 } else
262 arr->arr[i - back] = arr->arr[i];
263 }
264
265 arr->num -= back;
266}
267
268/** Sends to each object in arr the message identified by given selector. */
269static inline void ccArrayMakeObjectsPerformSelector(ccArray *arr, SEL sel)
270{
271 for( NSUInteger i = 0; i < arr->num; i++)
272 [arr->arr[i] performSelector:sel];
273}
274
275static inline void ccArrayMakeObjectsPerformSelectorWithObject(ccArray *arr, SEL sel, id object)
276{
277 for( NSUInteger i = 0; i < arr->num; i++)
278 [arr->arr[i] performSelector:sel withObject:object];
279}
280
281
282#pragma mark -
283#pragma mark ccCArray for Values (c structures)
284
285typedef ccArray ccCArray;
286
287static inline void ccCArrayRemoveAllValues(ccCArray *arr);
288
289/** Allocates and initializes a new C array with specified capacity */
290static inline ccCArray* ccCArrayNew(NSUInteger capacity) {
291 if (capacity == 0)
292 capacity = 1;
293
294 ccCArray *arr = (ccCArray*)malloc( sizeof(ccCArray) );
295 arr->num = 0;
296 arr->arr = (id*) malloc( capacity * sizeof(id) );
297 arr->max = capacity;
298
299 return arr;
300}
301
302/** Frees C array after removing all remaining values. Silently ignores nil arr. */
303static inline void ccCArrayFree(ccCArray *arr)
304{
305 if( arr == nil ) return;
306
307 ccCArrayRemoveAllValues(arr);
308
309 free(arr->arr);
310 free(arr);
311}
312
313/** Doubles C array capacity */
314static inline void ccCArrayDoubleCapacity(ccCArray *arr)
315{
316 ccArrayDoubleCapacity(arr);
317}
318
319/** Increases array capacity such that max >= num + extra. */
320static inline void ccCArrayEnsureExtraCapacity(ccCArray *arr, NSUInteger extra)
321{
322 ccArrayEnsureExtraCapacity(arr,extra);
323}
324
325/** Returns index of first occurence of value, NSNotFound if value not found. */
326static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, void* value)
327{
328 for( NSUInteger i = 0; i < arr->num; i++)
329 if( arr->arr[i] == value ) return i;
330 return NSNotFound;
331}
332
333/** Returns a Boolean value that indicates whether value is present in the C array. */
334static inline BOOL ccCArrayContainsValue(ccCArray *arr, void* value)
335{
336 return ccCArrayGetIndexOfValue(arr, value) != NSNotFound;
337}
338
339/** Inserts a value at a certain position. Behaviour undefined if aray doesn't have enough capacity */
340static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, void *value, NSUInteger index)
341{
342 NSCAssert( index < arr->max, @"ccCArrayInsertValueAtIndex: invalid index");
343
344 NSUInteger remaining = arr->num - index;
345
346 // last Value doesn't need to be moved
347 if( remaining > 0) {
348 // tex coordinates
349 memmove( &arr->arr[index+1],&arr->arr[index], sizeof(void*) * remaining );
350 }
351
352 arr->num++;
353 arr->arr[index] = (id) value;
354}
355
356/** Appends an value. Bahaviour undefined if array doesn't have enough capacity. */
357static inline void ccCArrayAppendValue(ccCArray *arr, void* value)
358{
359 arr->arr[arr->num] = (id) value;
360 arr->num++;
361}
362
363/** Appends an value. Capacity of arr is increased if needed. */
364static inline void ccCArrayAppendValueWithResize(ccCArray *arr, void* value)
365{
366 ccCArrayEnsureExtraCapacity(arr, 1);
367 ccCArrayAppendValue(arr, value);
368}
369
370/** Appends values from plusArr to arr. Behaviour undefined if arr doesn't have
371 enough capacity. */
372static inline void ccCArrayAppendArray(ccCArray *arr, ccCArray *plusArr)
373{
374 for( NSUInteger i = 0; i < plusArr->num; i++)
375 ccCArrayAppendValue(arr, plusArr->arr[i]);
376}
377
378/** Appends values from plusArr to arr. Capacity of arr is increased if needed. */
379static inline void ccCArrayAppendArrayWithResize(ccCArray *arr, ccCArray *plusArr)
380{
381 ccCArrayEnsureExtraCapacity(arr, plusArr->num);
382 ccCArrayAppendArray(arr, plusArr);
383}
384
385/** Removes all values from arr */
386static inline void ccCArrayRemoveAllValues(ccCArray *arr)
387{
388 arr->num = 0;
389}
390
391/** Removes value at specified index and pushes back all subsequent values.
392 Behaviour undefined if index outside [0, num-1].
393 @since v0.99.4
394 */
395static inline void ccCArrayRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
396{
397 for( NSUInteger last = --arr->num; index < last; index++)
398 arr->arr[index] = arr->arr[index + 1];
399}
400
401/** Removes value at specified index and fills the gap with the last value,
402 thereby avoiding the need to push back subsequent values.
403 Behaviour undefined if index outside [0, num-1].
404 @since v0.99.4
405 */
406static inline void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
407{
408 NSUInteger last = --arr->num;
409 arr->arr[index] = arr->arr[last];
410}
411
412/** Searches for the first occurance of value and removes it. If value is not found the function has no effect.
413 @since v0.99.4
414 */
415static inline void ccCArrayRemoveValue(ccCArray *arr, void* value)
416{
417 NSUInteger index = ccCArrayGetIndexOfValue(arr, value);
418 if (index != NSNotFound)
419 ccCArrayRemoveValueAtIndex(arr, index);
420}
421
422/** Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
423 @since v0.99.4
424 */
425static inline void ccCArrayRemoveArray(ccCArray *arr, ccCArray *minusArr)
426{
427 for( NSUInteger i = 0; i < minusArr->num; i++)
428 ccCArrayRemoveValue(arr, minusArr->arr[i]);
429}
430
431/** Removes from arr all values in minusArr. For each value in minusArr, all matching instances in arr will be removed.
432 @since v0.99.4
433 */
434static inline void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr)
435{
436 NSUInteger back = 0;
437
438 for( NSUInteger i = 0; i < arr->num; i++) {
439 if( ccCArrayContainsValue(minusArr, arr->arr[i]) ) {
440 back++;
441 } else
442 arr->arr[i - back] = arr->arr[i];
443 }
444
445 arr->num -= back;
446}
447#endif // CC_ARRAY_H
diff --git a/libs/cocos2d/Support/ccUtils.c b/libs/cocos2d/Support/ccUtils.c new file mode 100755 index 0000000..39786ec --- /dev/null +++ b/libs/cocos2d/Support/ccUtils.c
@@ -0,0 +1,20 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 */
5
6/*
7 ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
8 */
9#include "ccUtils.h"
10
11unsigned long ccNextPOT(unsigned long x)
12{
13 x = x - 1;
14 x = x | (x >> 1);
15 x = x | (x >> 2);
16 x = x | (x >> 4);
17 x = x | (x >> 8);
18 x = x | (x >>16);
19 return x + 1;
20} \ No newline at end of file
diff --git a/libs/cocos2d/Support/ccUtils.h b/libs/cocos2d/Support/ccUtils.h new file mode 100755 index 0000000..783fc54 --- /dev/null +++ b/libs/cocos2d/Support/ccUtils.h
@@ -0,0 +1,29 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 */
5
6#ifndef __CC_UTILS_H
7#define __CC_UTILS_H
8
9/** @file ccUtils.h
10 Misc free functions
11 */
12
13/*
14 ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
15 */
16
17/** returns the Next Power of Two value.
18
19 Examples:
20 - If "value" is 15, it will return 16.
21 - If "value" is 16, it will return 16.
22 - If "value" is 17, it will return 32.
23
24 @since v0.99.5
25 */
26
27unsigned long ccNextPOT( unsigned long value );
28
29#endif // ! __CC_UTILS_H
diff --git a/libs/cocos2d/Support/uthash.h b/libs/cocos2d/Support/uthash.h new file mode 100755 index 0000000..a4bdc18 --- /dev/null +++ b/libs/cocos2d/Support/uthash.h
@@ -0,0 +1,972 @@
1/*
2Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*/
23
24#ifndef UTHASH_H
25#define UTHASH_H
26
27#include <string.h> /* memcmp,strlen */
28#include <stddef.h> /* ptrdiff_t */
29
30/* These macros use decltype or the earlier __typeof GNU extension.
31 As decltype is only available in newer compilers (VS2010 or gcc 4.3+
32 when compiling c++ source) this code uses whatever method is needed
33 or, for VS2008 where neither is available, uses casting workarounds. */
34#ifdef _MSC_VER /* MS compiler */
35#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
36#define DECLTYPE(x) (decltype(x))
37#else /* VS2008 or older (or VS2010 in C mode) */
38#define NO_DECLTYPE
39#define DECLTYPE(x)
40#endif
41#else /* GNU, Sun and other compilers */
42#define DECLTYPE(x) (__typeof(x))
43#endif
44
45#ifdef NO_DECLTYPE
46#define DECLTYPE_ASSIGN(dst,src) \
47do { \
48 char **_da_dst = (char**)(&(dst)); \
49 *_da_dst = (char*)(src); \
50} while(0)
51#else
52#define DECLTYPE_ASSIGN(dst,src) \
53do { \
54 (dst) = DECLTYPE(dst)(src); \
55} while(0)
56#endif
57
58/* a number of the hash function use uint32_t which isn't defined on win32 */
59#ifdef _MSC_VER
60typedef unsigned int uint32_t;
61#else
62#include <inttypes.h> /* uint32_t */
63#endif
64
65#define UTHASH_VERSION 1.9.3
66
67#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
68#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
69#define uthash_free(ptr,sz) free(ptr) /* free fcn */
70
71#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
72#define uthash_expand_fyi(tbl) /* can be defined to log expands */
73
74/* initial number of buckets */
75#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
76#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
77#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
78
79/* calculate the element whose hash handle address is hhe */
80#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
81
82#define HASH_FIND(hh,head,keyptr,keylen,out) \
83do { \
84 unsigned _hf_bkt,_hf_hashv; \
85 out=NULL; \
86 if (head) { \
87 HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
88 if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
89 HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
90 keyptr,keylen,out); \
91 } \
92 } \
93} while (0)
94
95#ifdef HASH_BLOOM
96#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
97#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
98#define HASH_BLOOM_MAKE(tbl) \
99do { \
100 (tbl)->bloom_nbits = HASH_BLOOM; \
101 (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
102 if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
103 memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
104 (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
105} while (0);
106
107#define HASH_BLOOM_FREE(tbl) \
108do { \
109 uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
110} while (0);
111
112#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
113#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
114
115#define HASH_BLOOM_ADD(tbl,hashv) \
116 HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
117
118#define HASH_BLOOM_TEST(tbl,hashv) \
119 HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
120
121#else
122#define HASH_BLOOM_MAKE(tbl)
123#define HASH_BLOOM_FREE(tbl)
124#define HASH_BLOOM_ADD(tbl,hashv)
125#define HASH_BLOOM_TEST(tbl,hashv) (1)
126#endif
127
128#define HASH_MAKE_TABLE(hh,head) \
129do { \
130 (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
131 sizeof(UT_hash_table)); \
132 if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
133 memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
134 (head)->hh.tbl->tail = &((head)->hh); \
135 (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
136 (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
137 (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
138 (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
139 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
140 if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
141 memset((head)->hh.tbl->buckets, 0, \
142 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
143 HASH_BLOOM_MAKE((head)->hh.tbl); \
144 (head)->hh.tbl->signature = HASH_SIGNATURE; \
145} while(0)
146
147#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
148 HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
149
150#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
151do { \
152 unsigned _ha_bkt; \
153 (add)->hh.next = NULL; \
154 (add)->hh.key = (char*)keyptr; \
155 (add)->hh.keylen = keylen_in; \
156 if (!(head)) { \
157 head = (add); \
158 (head)->hh.prev = NULL; \
159 HASH_MAKE_TABLE(hh,head); \
160 } else { \
161 (head)->hh.tbl->tail->next = (add); \
162 (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
163 (head)->hh.tbl->tail = &((add)->hh); \
164 } \
165 (head)->hh.tbl->num_items++; \
166 (add)->hh.tbl = (head)->hh.tbl; \
167 HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
168 (add)->hh.hashv, _ha_bkt); \
169 HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
170 HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
171 HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
172 HASH_FSCK(hh,head); \
173} while(0)
174
175#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
176do { \
177 bkt = ((hashv) & ((num_bkts) - 1)); \
178} while(0)
179
180/* delete "delptr" from the hash table.
181 * "the usual" patch-up process for the app-order doubly-linked-list.
182 * The use of _hd_hh_del below deserves special explanation.
183 * These used to be expressed using (delptr) but that led to a bug
184 * if someone used the same symbol for the head and deletee, like
185 * HASH_DELETE(hh,users,users);
186 * We want that to work, but by changing the head (users) below
187 * we were forfeiting our ability to further refer to the deletee (users)
188 * in the patch-up process. Solution: use scratch space to
189 * copy the deletee pointer, then the latter references are via that
190 * scratch pointer rather than through the repointed (users) symbol.
191 */
192#define HASH_DELETE(hh,head,delptr) \
193do { \
194 unsigned _hd_bkt; \
195 struct UT_hash_handle *_hd_hh_del; \
196 if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
197 uthash_free((head)->hh.tbl->buckets, \
198 (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
199 HASH_BLOOM_FREE((head)->hh.tbl); \
200 uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
201 head = NULL; \
202 } else { \
203 _hd_hh_del = &((delptr)->hh); \
204 if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
205 (head)->hh.tbl->tail = \
206 (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
207 (head)->hh.tbl->hho); \
208 } \
209 if ((delptr)->hh.prev) { \
210 ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
211 (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
212 } else { \
213 DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
214 } \
215 if (_hd_hh_del->next) { \
216 ((UT_hash_handle*)((char*)_hd_hh_del->next + \
217 (head)->hh.tbl->hho))->prev = \
218 _hd_hh_del->prev; \
219 } \
220 HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
221 HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
222 (head)->hh.tbl->num_items--; \
223 } \
224 HASH_FSCK(hh,head); \
225} while (0)
226
227
228/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
229#define HASH_FIND_STR(head,findstr,out) \
230 HASH_FIND(hh,head,findstr,strlen(findstr),out)
231#define HASH_ADD_STR(head,strfield,add) \
232 HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
233#define HASH_FIND_INT(head,findint,out) \
234 HASH_FIND(hh,head,findint,sizeof(int),out)
235#define HASH_ADD_INT(head,intfield,add) \
236 HASH_ADD(hh,head,intfield,sizeof(int),add)
237#define HASH_FIND_PTR(head,findptr,out) \
238 HASH_FIND(hh,head,findptr,sizeof(void *),out)
239#define HASH_ADD_PTR(head,ptrfield,add) \
240 HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
241#define HASH_DEL(head,delptr) \
242 HASH_DELETE(hh,head,delptr)
243
244/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
245 * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
246 */
247#ifdef HASH_DEBUG
248#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
249#define HASH_FSCK(hh,head) \
250do { \
251 unsigned _bkt_i; \
252 unsigned _count, _bkt_count; \
253 char *_prev; \
254 struct UT_hash_handle *_thh; \
255 if (head) { \
256 _count = 0; \
257 for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
258 _bkt_count = 0; \
259 _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
260 _prev = NULL; \
261 while (_thh) { \
262 if (_prev != (char*)(_thh->hh_prev)) { \
263 HASH_OOPS("invalid hh_prev %p, actual %p\n", \
264 _thh->hh_prev, _prev ); \
265 } \
266 _bkt_count++; \
267 _prev = (char*)(_thh); \
268 _thh = _thh->hh_next; \
269 } \
270 _count += _bkt_count; \
271 if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
272 HASH_OOPS("invalid bucket count %d, actual %d\n", \
273 (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
274 } \
275 } \
276 if (_count != (head)->hh.tbl->num_items) { \
277 HASH_OOPS("invalid hh item count %d, actual %d\n", \
278 (head)->hh.tbl->num_items, _count ); \
279 } \
280 /* traverse hh in app order; check next/prev integrity, count */ \
281 _count = 0; \
282 _prev = NULL; \
283 _thh = &(head)->hh; \
284 while (_thh) { \
285 _count++; \
286 if (_prev !=(char*)(_thh->prev)) { \
287 HASH_OOPS("invalid prev %p, actual %p\n", \
288 _thh->prev, _prev ); \
289 } \
290 _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
291 _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
292 (head)->hh.tbl->hho) : NULL ); \
293 } \
294 if (_count != (head)->hh.tbl->num_items) { \
295 HASH_OOPS("invalid app item count %d, actual %d\n", \
296 (head)->hh.tbl->num_items, _count ); \
297 } \
298 } \
299} while (0)
300#else
301#define HASH_FSCK(hh,head)
302#endif
303
304/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
305 * the descriptor to which this macro is defined for tuning the hash function.
306 * The app can #include <unistd.h> to get the prototype for write(2). */
307#ifdef HASH_EMIT_KEYS
308#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
309do { \
310 unsigned _klen = fieldlen; \
311 write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
312 write(HASH_EMIT_KEYS, keyptr, fieldlen); \
313} while (0)
314#else
315#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
316#endif
317
318/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
319#ifdef HASH_FUNCTION
320#define HASH_FCN HASH_FUNCTION
321#else
322#define HASH_FCN HASH_JEN
323#endif
324
325/* The Bernstein hash function, used in Perl prior to v5.6 */
326#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
327do { \
328 unsigned _hb_keylen=keylen; \
329 char *_hb_key=(char*)(key); \
330 (hashv) = 0; \
331 while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
332 bkt = (hashv) & (num_bkts-1); \
333} while (0)
334
335
336/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
337 * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
338#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
339do { \
340 unsigned _sx_i; \
341 char *_hs_key=(char*)(key); \
342 hashv = 0; \
343 for(_sx_i=0; _sx_i < keylen; _sx_i++) \
344 hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
345 bkt = hashv & (num_bkts-1); \
346} while (0)
347
348#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
349do { \
350 unsigned _fn_i; \
351 char *_hf_key=(char*)(key); \
352 hashv = 2166136261UL; \
353 for(_fn_i=0; _fn_i < keylen; _fn_i++) \
354 hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
355 bkt = hashv & (num_bkts-1); \
356} while(0);
357
358#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
359do { \
360 unsigned _ho_i; \
361 char *_ho_key=(char*)(key); \
362 hashv = 0; \
363 for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
364 hashv += _ho_key[_ho_i]; \
365 hashv += (hashv << 10); \
366 hashv ^= (hashv >> 6); \
367 } \
368 hashv += (hashv << 3); \
369 hashv ^= (hashv >> 11); \
370 hashv += (hashv << 15); \
371 bkt = hashv & (num_bkts-1); \
372} while(0)
373
374#define HASH_JEN_MIX(a,b,c) \
375do { \
376 a -= b; a -= c; a ^= ( c >> 13 ); \
377 b -= c; b -= a; b ^= ( a << 8 ); \
378 c -= a; c -= b; c ^= ( b >> 13 ); \
379 a -= b; a -= c; a ^= ( c >> 12 ); \
380 b -= c; b -= a; b ^= ( a << 16 ); \
381 c -= a; c -= b; c ^= ( b >> 5 ); \
382 a -= b; a -= c; a ^= ( c >> 3 ); \
383 b -= c; b -= a; b ^= ( a << 10 ); \
384 c -= a; c -= b; c ^= ( b >> 15 ); \
385} while (0)
386
387#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
388do { \
389 unsigned _hj_i,_hj_j,_hj_k; \
390 char *_hj_key=(char*)(key); \
391 hashv = 0xfeedbeef; \
392 _hj_i = _hj_j = 0x9e3779b9; \
393 _hj_k = keylen; \
394 while (_hj_k >= 12) { \
395 _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
396 + ( (unsigned)_hj_key[2] << 16 ) \
397 + ( (unsigned)_hj_key[3] << 24 ) ); \
398 _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
399 + ( (unsigned)_hj_key[6] << 16 ) \
400 + ( (unsigned)_hj_key[7] << 24 ) ); \
401 hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
402 + ( (unsigned)_hj_key[10] << 16 ) \
403 + ( (unsigned)_hj_key[11] << 24 ) ); \
404 \
405 HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
406 \
407 _hj_key += 12; \
408 _hj_k -= 12; \
409 } \
410 hashv += keylen; \
411 switch ( _hj_k ) { \
412 case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
413 case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
414 case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
415 case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
416 case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
417 case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
418 case 5: _hj_j += _hj_key[4]; \
419 case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
420 case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
421 case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
422 case 1: _hj_i += _hj_key[0]; \
423 } \
424 HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
425 bkt = hashv & (num_bkts-1); \
426} while(0)
427
428/* The Paul Hsieh hash function */
429#undef get16bits
430#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
431 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
432#define get16bits(d) (*((const uint16_t *) (d)))
433#endif
434
435#if !defined (get16bits)
436#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
437 +(uint32_t)(((const uint8_t *)(d))[0]) )
438#endif
439#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
440do { \
441 char *_sfh_key=(char*)(key); \
442 uint32_t _sfh_tmp, _sfh_len = keylen; \
443 \
444 int _sfh_rem = _sfh_len & 3; \
445 _sfh_len >>= 2; \
446 hashv = 0xcafebabe; \
447 \
448 /* Main loop */ \
449 for (;_sfh_len > 0; _sfh_len--) { \
450 hashv += get16bits (_sfh_key); \
451 _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
452 hashv = (hashv << 16) ^ _sfh_tmp; \
453 _sfh_key += 2*sizeof (uint16_t); \
454 hashv += hashv >> 11; \
455 } \
456 \
457 /* Handle end cases */ \
458 switch (_sfh_rem) { \
459 case 3: hashv += get16bits (_sfh_key); \
460 hashv ^= hashv << 16; \
461 hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
462 hashv += hashv >> 11; \
463 break; \
464 case 2: hashv += get16bits (_sfh_key); \
465 hashv ^= hashv << 11; \
466 hashv += hashv >> 17; \
467 break; \
468 case 1: hashv += *_sfh_key; \
469 hashv ^= hashv << 10; \
470 hashv += hashv >> 1; \
471 } \
472 \
473 /* Force "avalanching" of final 127 bits */ \
474 hashv ^= hashv << 3; \
475 hashv += hashv >> 5; \
476 hashv ^= hashv << 4; \
477 hashv += hashv >> 17; \
478 hashv ^= hashv << 25; \
479 hashv += hashv >> 6; \
480 bkt = hashv & (num_bkts-1); \
481} while(0);
482
483#ifdef HASH_USING_NO_STRICT_ALIASING
484/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
485 * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
486 * So MurmurHash comes in two versions, the faster unaligned one and the slower
487 * aligned one. We only use the faster one on CPU's where we know it's safe.
488 *
489 * Note the preprocessor built-in defines can be emitted using:
490 *
491 * gcc -m64 -dM -E - < /dev/null (on gcc)
492 * cc -## a.c (where a.c is a simple test file) (Sun Studio)
493 */
494#if (defined(__i386__) || defined(__x86_64__))
495#define HASH_MUR HASH_MUR_UNALIGNED
496#else
497#define HASH_MUR HASH_MUR_ALIGNED
498#endif
499
500/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
501#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
502do { \
503 const unsigned int _mur_m = 0x5bd1e995; \
504 const int _mur_r = 24; \
505 hashv = 0xcafebabe ^ keylen; \
506 char *_mur_key = (char *)(key); \
507 uint32_t _mur_tmp, _mur_len = keylen; \
508 \
509 for (;_mur_len >= 4; _mur_len-=4) { \
510 _mur_tmp = *(uint32_t *)_mur_key; \
511 _mur_tmp *= _mur_m; \
512 _mur_tmp ^= _mur_tmp >> _mur_r; \
513 _mur_tmp *= _mur_m; \
514 hashv *= _mur_m; \
515 hashv ^= _mur_tmp; \
516 _mur_key += 4; \
517 } \
518 \
519 switch(_mur_len) \
520 { \
521 case 3: hashv ^= _mur_key[2] << 16; \
522 case 2: hashv ^= _mur_key[1] << 8; \
523 case 1: hashv ^= _mur_key[0]; \
524 hashv *= _mur_m; \
525 }; \
526 \
527 hashv ^= hashv >> 13; \
528 hashv *= _mur_m; \
529 hashv ^= hashv >> 15; \
530 \
531 bkt = hashv & (num_bkts-1); \
532} while(0)
533
534/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
535#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
536do { \
537 const unsigned int _mur_m = 0x5bd1e995; \
538 const int _mur_r = 24; \
539 hashv = 0xcafebabe ^ (keylen); \
540 char *_mur_key = (char *)(key); \
541 uint32_t _mur_len = keylen; \
542 int _mur_align = (int)_mur_key & 3; \
543 \
544 if (_mur_align && (_mur_len >= 4)) { \
545 unsigned _mur_t = 0, _mur_d = 0; \
546 switch(_mur_align) { \
547 case 1: _mur_t |= _mur_key[2] << 16; \
548 case 2: _mur_t |= _mur_key[1] << 8; \
549 case 3: _mur_t |= _mur_key[0]; \
550 } \
551 _mur_t <<= (8 * _mur_align); \
552 _mur_key += 4-_mur_align; \
553 _mur_len -= 4-_mur_align; \
554 int _mur_sl = 8 * (4-_mur_align); \
555 int _mur_sr = 8 * _mur_align; \
556 \
557 for (;_mur_len >= 4; _mur_len-=4) { \
558 _mur_d = *(unsigned *)_mur_key; \
559 _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
560 unsigned _mur_k = _mur_t; \
561 _mur_k *= _mur_m; \
562 _mur_k ^= _mur_k >> _mur_r; \
563 _mur_k *= _mur_m; \
564 hashv *= _mur_m; \
565 hashv ^= _mur_k; \
566 _mur_t = _mur_d; \
567 _mur_key += 4; \
568 } \
569 _mur_d = 0; \
570 if(_mur_len >= _mur_align) { \
571 switch(_mur_align) { \
572 case 3: _mur_d |= _mur_key[2] << 16; \
573 case 2: _mur_d |= _mur_key[1] << 8; \
574 case 1: _mur_d |= _mur_key[0]; \
575 } \
576 unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
577 _mur_k *= _mur_m; \
578 _mur_k ^= _mur_k >> _mur_r; \
579 _mur_k *= _mur_m; \
580 hashv *= _mur_m; \
581 hashv ^= _mur_k; \
582 _mur_k += _mur_align; \
583 _mur_len -= _mur_align; \
584 \
585 switch(_mur_len) \
586 { \
587 case 3: hashv ^= _mur_key[2] << 16; \
588 case 2: hashv ^= _mur_key[1] << 8; \
589 case 1: hashv ^= _mur_key[0]; \
590 hashv *= _mur_m; \
591 } \
592 } else { \
593 switch(_mur_len) \
594 { \
595 case 3: _mur_d ^= _mur_key[2] << 16; \
596 case 2: _mur_d ^= _mur_key[1] << 8; \
597 case 1: _mur_d ^= _mur_key[0]; \
598 case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
599 hashv *= _mur_m; \
600 } \
601 } \
602 \
603 hashv ^= hashv >> 13; \
604 hashv *= _mur_m; \
605 hashv ^= hashv >> 15; \
606 } else { \
607 for (;_mur_len >= 4; _mur_len-=4) { \
608 unsigned _mur_k = *(unsigned*)_mur_key; \
609 _mur_k *= _mur_m; \
610 _mur_k ^= _mur_k >> _mur_r; \
611 _mur_k *= _mur_m; \
612 hashv *= _mur_m; \
613 hashv ^= _mur_k; \
614 _mur_key += 4; \
615 } \
616 switch(_mur_len) \
617 { \
618 case 3: hashv ^= _mur_key[2] << 16; \
619 case 2: hashv ^= _mur_key[1] << 8; \
620 case 1: hashv ^= _mur_key[0]; \
621 hashv *= _mur_m; \
622 } \
623 \
624 hashv ^= hashv >> 13; \
625 hashv *= _mur_m; \
626 hashv ^= hashv >> 15; \
627 } \
628 bkt = hashv & (num_bkts-1); \
629} while(0)
630#endif /* HASH_USING_NO_STRICT_ALIASING */
631
632/* key comparison function; return 0 if keys equal */
633#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
634
635/* iterate over items in a known bucket to find desired item */
636#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
637do { \
638 if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
639 else out=NULL; \
640 while (out) { \
641 if (out->hh.keylen == keylen_in) { \
642 if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
643 } \
644 if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
645 else out = NULL; \
646 } \
647} while(0)
648
649/* add an item to a bucket */
650#define HASH_ADD_TO_BKT(head,addhh) \
651do { \
652 head.count++; \
653 (addhh)->hh_next = head.hh_head; \
654 (addhh)->hh_prev = NULL; \
655 if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
656 (head).hh_head=addhh; \
657 if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
658 && (addhh)->tbl->noexpand != 1) { \
659 HASH_EXPAND_BUCKETS((addhh)->tbl); \
660 } \
661} while(0)
662
663/* remove an item from a given bucket */
664#define HASH_DEL_IN_BKT(hh,head,hh_del) \
665 (head).count--; \
666 if ((head).hh_head == hh_del) { \
667 (head).hh_head = hh_del->hh_next; \
668 } \
669 if (hh_del->hh_prev) { \
670 hh_del->hh_prev->hh_next = hh_del->hh_next; \
671 } \
672 if (hh_del->hh_next) { \
673 hh_del->hh_next->hh_prev = hh_del->hh_prev; \
674 }
675
676/* Bucket expansion has the effect of doubling the number of buckets
677 * and redistributing the items into the new buckets. Ideally the
678 * items will distribute more or less evenly into the new buckets
679 * (the extent to which this is true is a measure of the quality of
680 * the hash function as it applies to the key domain).
681 *
682 * With the items distributed into more buckets, the chain length
683 * (item count) in each bucket is reduced. Thus by expanding buckets
684 * the hash keeps a bound on the chain length. This bounded chain
685 * length is the essence of how a hash provides constant time lookup.
686 *
687 * The calculation of tbl->ideal_chain_maxlen below deserves some
688 * explanation. First, keep in mind that we're calculating the ideal
689 * maximum chain length based on the *new* (doubled) bucket count.
690 * In fractions this is just n/b (n=number of items,b=new num buckets).
691 * Since the ideal chain length is an integer, we want to calculate
692 * ceil(n/b). We don't depend on floating point arithmetic in this
693 * hash, so to calculate ceil(n/b) with integers we could write
694 *
695 * ceil(n/b) = (n/b) + ((n%b)?1:0)
696 *
697 * and in fact a previous version of this hash did just that.
698 * But now we have improved things a bit by recognizing that b is
699 * always a power of two. We keep its base 2 log handy (call it lb),
700 * so now we can write this with a bit shift and logical AND:
701 *
702 * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
703 *
704 */
705#define HASH_EXPAND_BUCKETS(tbl) \
706do { \
707 unsigned _he_bkt; \
708 unsigned _he_bkt_i; \
709 struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
710 UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
711 _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
712 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
713 if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
714 memset(_he_new_buckets, 0, \
715 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
716 tbl->ideal_chain_maxlen = \
717 (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
718 ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
719 tbl->nonideal_items = 0; \
720 for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
721 { \
722 _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
723 while (_he_thh) { \
724 _he_hh_nxt = _he_thh->hh_next; \
725 HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
726 _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
727 if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
728 tbl->nonideal_items++; \
729 _he_newbkt->expand_mult = _he_newbkt->count / \
730 tbl->ideal_chain_maxlen; \
731 } \
732 _he_thh->hh_prev = NULL; \
733 _he_thh->hh_next = _he_newbkt->hh_head; \
734 if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
735 _he_thh; \
736 _he_newbkt->hh_head = _he_thh; \
737 _he_thh = _he_hh_nxt; \
738 } \
739 } \
740 uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
741 tbl->num_buckets *= 2; \
742 tbl->log2_num_buckets++; \
743 tbl->buckets = _he_new_buckets; \
744 tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
745 (tbl->ineff_expands+1) : 0; \
746 if (tbl->ineff_expands > 1) { \
747 tbl->noexpand=1; \
748 uthash_noexpand_fyi(tbl); \
749 } \
750 uthash_expand_fyi(tbl); \
751} while(0)
752
753
754/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
755/* Note that HASH_SORT assumes the hash handle name to be hh.
756 * HASH_SRT was added to allow the hash handle name to be passed in. */
757#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
758#define HASH_SRT(hh,head,cmpfcn) \
759do { \
760 unsigned _hs_i; \
761 unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
762 struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
763 if (head) { \
764 _hs_insize = 1; \
765 _hs_looping = 1; \
766 _hs_list = &((head)->hh); \
767 while (_hs_looping) { \
768 _hs_p = _hs_list; \
769 _hs_list = NULL; \
770 _hs_tail = NULL; \
771 _hs_nmerges = 0; \
772 while (_hs_p) { \
773 _hs_nmerges++; \
774 _hs_q = _hs_p; \
775 _hs_psize = 0; \
776 for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
777 _hs_psize++; \
778 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
779 ((void*)((char*)(_hs_q->next) + \
780 (head)->hh.tbl->hho)) : NULL); \
781 if (! (_hs_q) ) break; \
782 } \
783 _hs_qsize = _hs_insize; \
784 while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
785 if (_hs_psize == 0) { \
786 _hs_e = _hs_q; \
787 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
788 ((void*)((char*)(_hs_q->next) + \
789 (head)->hh.tbl->hho)) : NULL); \
790 _hs_qsize--; \
791 } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
792 _hs_e = _hs_p; \
793 _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
794 ((void*)((char*)(_hs_p->next) + \
795 (head)->hh.tbl->hho)) : NULL); \
796 _hs_psize--; \
797 } else if (( \
798 cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
799 DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
800 ) <= 0) { \
801 _hs_e = _hs_p; \
802 _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
803 ((void*)((char*)(_hs_p->next) + \
804 (head)->hh.tbl->hho)) : NULL); \
805 _hs_psize--; \
806 } else { \
807 _hs_e = _hs_q; \
808 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
809 ((void*)((char*)(_hs_q->next) + \
810 (head)->hh.tbl->hho)) : NULL); \
811 _hs_qsize--; \
812 } \
813 if ( _hs_tail ) { \
814 _hs_tail->next = ((_hs_e) ? \
815 ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
816 } else { \
817 _hs_list = _hs_e; \
818 } \
819 _hs_e->prev = ((_hs_tail) ? \
820 ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
821 _hs_tail = _hs_e; \
822 } \
823 _hs_p = _hs_q; \
824 } \
825 _hs_tail->next = NULL; \
826 if ( _hs_nmerges <= 1 ) { \
827 _hs_looping=0; \
828 (head)->hh.tbl->tail = _hs_tail; \
829 DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
830 } \
831 _hs_insize *= 2; \
832 } \
833 HASH_FSCK(hh,head); \
834 } \
835} while (0)
836
837/* This function selects items from one hash into another hash.
838 * The end result is that the selected items have dual presence
839 * in both hashes. There is no copy of the items made; rather
840 * they are added into the new hash through a secondary hash
841 * hash handle that must be present in the structure. */
842#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
843do { \
844 unsigned _src_bkt, _dst_bkt; \
845 void *_last_elt=NULL, *_elt; \
846 UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
847 ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
848 if (src) { \
849 for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
850 for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
851 _src_hh; \
852 _src_hh = _src_hh->hh_next) { \
853 _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
854 if (cond(_elt)) { \
855 _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
856 _dst_hh->key = _src_hh->key; \
857 _dst_hh->keylen = _src_hh->keylen; \
858 _dst_hh->hashv = _src_hh->hashv; \
859 _dst_hh->prev = _last_elt; \
860 _dst_hh->next = NULL; \
861 if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
862 if (!dst) { \
863 DECLTYPE_ASSIGN(dst,_elt); \
864 HASH_MAKE_TABLE(hh_dst,dst); \
865 } else { \
866 _dst_hh->tbl = (dst)->hh_dst.tbl; \
867 } \
868 HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
869 HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
870 (dst)->hh_dst.tbl->num_items++; \
871 _last_elt = _elt; \
872 _last_elt_hh = _dst_hh; \
873 } \
874 } \
875 } \
876 } \
877 HASH_FSCK(hh_dst,dst); \
878} while (0)
879
880#define HASH_CLEAR(hh,head) \
881do { \
882 if (head) { \
883 uthash_free((head)->hh.tbl->buckets, \
884 (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
885 uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
886 (head)=NULL; \
887 } \
888} while(0)
889
890#ifdef NO_DECLTYPE
891#define HASH_ITER(hh,head,el,tmp) \
892for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
893 el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
894#else
895#define HASH_ITER(hh,head,el,tmp) \
896for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
897 el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
898#endif
899
900/* obtain a count of items in the hash */
901#define HASH_COUNT(head) HASH_CNT(hh,head)
902#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
903
904typedef struct UT_hash_bucket {
905 struct UT_hash_handle *hh_head;
906 unsigned count;
907
908 /* expand_mult is normally set to 0. In this situation, the max chain length
909 * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
910 * the bucket's chain exceeds this length, bucket expansion is triggered).
911 * However, setting expand_mult to a non-zero value delays bucket expansion
912 * (that would be triggered by additions to this particular bucket)
913 * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
914 * (The multiplier is simply expand_mult+1). The whole idea of this
915 * multiplier is to reduce bucket expansions, since they are expensive, in
916 * situations where we know that a particular bucket tends to be overused.
917 * It is better to let its chain length grow to a longer yet-still-bounded
918 * value, than to do an O(n) bucket expansion too often.
919 */
920 unsigned expand_mult;
921
922} UT_hash_bucket;
923
924/* random signature used only to find hash tables in external analysis */
925#define HASH_SIGNATURE 0xa0111fe1
926#define HASH_BLOOM_SIGNATURE 0xb12220f2
927
928typedef struct UT_hash_table {
929 UT_hash_bucket *buckets;
930 unsigned num_buckets, log2_num_buckets;
931 unsigned num_items;
932 struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
933 ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
934
935 /* in an ideal situation (all buckets used equally), no bucket would have
936 * more than ceil(#items/#buckets) items. that's the ideal chain length. */
937 unsigned ideal_chain_maxlen;
938
939 /* nonideal_items is the number of items in the hash whose chain position
940 * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
941 * hash distribution; reaching them in a chain traversal takes >ideal steps */
942 unsigned nonideal_items;
943
944 /* ineffective expands occur when a bucket doubling was performed, but
945 * afterward, more than half the items in the hash had nonideal chain
946 * positions. If this happens on two consecutive expansions we inhibit any
947 * further expansion, as it's not helping; this happens when the hash
948 * function isn't a good fit for the key domain. When expansion is inhibited
949 * the hash will still work, albeit no longer in constant time. */
950 unsigned ineff_expands, noexpand;
951
952 uint32_t signature; /* used only to find hash tables in external analysis */
953#ifdef HASH_BLOOM
954 uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
955 uint8_t *bloom_bv;
956 char bloom_nbits;
957#endif
958
959} UT_hash_table;
960
961typedef struct UT_hash_handle {
962 struct UT_hash_table *tbl;
963 void *prev; /* prev element in app order */
964 void *next; /* next element in app order */
965 struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
966 struct UT_hash_handle *hh_next; /* next hh in bucket order */
967 void *key; /* ptr to enclosing struct's key */
968 unsigned keylen; /* enclosing struct's key len */
969 unsigned hashv; /* result of hash-fcn(key) */
970} UT_hash_handle;
971
972#endif /* UTHASH_H */
diff --git a/libs/cocos2d/Support/utlist.h b/libs/cocos2d/Support/utlist.h new file mode 100755 index 0000000..34c725b --- /dev/null +++ b/libs/cocos2d/Support/utlist.h
@@ -0,0 +1,490 @@
1/*
2Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*/
23
24#ifndef UTLIST_H
25#define UTLIST_H
26
27#define UTLIST_VERSION 1.9.1
28
29/*
30 * This file contains macros to manipulate singly and doubly-linked lists.
31 *
32 * 1. LL_ macros: singly-linked lists.
33 * 2. DL_ macros: doubly-linked lists.
34 * 3. CDL_ macros: circular doubly-linked lists.
35 *
36 * To use singly-linked lists, your structure must have a "next" pointer.
37 * To use doubly-linked lists, your structure must "prev" and "next" pointers.
38 * Either way, the pointer to the head of the list must be initialized to NULL.
39 *
40 * ----------------.EXAMPLE -------------------------
41 * struct item {
42 * int id;
43 * struct item *prev, *next;
44 * }
45 *
46 * struct item *list = NULL:
47 *
48 * int main() {
49 * struct item *item;
50 * ... allocate and populate item ...
51 * DL_APPEND(list, item);
52 * }
53 * --------------------------------------------------
54 *
55 * For doubly-linked lists, the append and delete macros are O(1)
56 * For singly-linked lists, append and delete are O(n) but prepend is O(1)
57 * The sort macro is O(n log(n)) for all types of single/double/circular lists.
58 */
59
60/* These macros use decltype or the earlier __typeof GNU extension.
61 As decltype is only available in newer compilers (VS2010 or gcc 4.3+
62 when compiling c++ code), this code uses whatever method is needed
63 or, for VS2008 where neither is available, uses casting workarounds. */
64#ifdef _MSC_VER /* MS compiler */
65#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
66#define LDECLTYPE(x) decltype(x)
67#else /* VS2008 or older (or VS2010 in C mode) */
68#define NO_DECLTYPE
69#define LDECLTYPE(x) char*
70#endif
71#else /* GNU, Sun and other compilers */
72#define LDECLTYPE(x) __typeof(x)
73#endif
74
75/* for VS2008 we use some workarounds to get around the lack of decltype,
76 * namely, we always reassign our tmp variable to the list head if we need
77 * to dereference its prev/next pointers, and save/restore the real head.*/
78#ifdef NO_DECLTYPE
79#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
80#define _NEXT(elt,list) ((char*)((list)->next))
81#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
82#define _PREV(elt,list) ((char*)((list)->prev))
83#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
84#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
85#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
86#else
87#define _SV(elt,list)
88#define _NEXT(elt,list) ((elt)->next)
89#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
90#define _PREV(elt,list) ((elt)->prev)
91#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
92#define _RS(list)
93#define _CASTASGN(a,b) (a)=(b)
94#endif
95
96/******************************************************************************
97 * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
98 * Unwieldy variable names used here to avoid shadowing passed-in variables. *
99 *****************************************************************************/
100#define LL_SORT(list, cmp) \
101do { \
102 LDECLTYPE(list) _ls_p; \
103 LDECLTYPE(list) _ls_q; \
104 LDECLTYPE(list) _ls_e; \
105 LDECLTYPE(list) _ls_tail; \
106 LDECLTYPE(list) _ls_oldhead; \
107 LDECLTYPE(list) _tmp; \
108 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
109 if (list) { \
110 _ls_insize = 1; \
111 _ls_looping = 1; \
112 while (_ls_looping) { \
113 _CASTASGN(_ls_p,list); \
114 _CASTASGN(_ls_oldhead,list); \
115 list = NULL; \
116 _ls_tail = NULL; \
117 _ls_nmerges = 0; \
118 while (_ls_p) { \
119 _ls_nmerges++; \
120 _ls_q = _ls_p; \
121 _ls_psize = 0; \
122 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
123 _ls_psize++; \
124 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
125 if (!_ls_q) break; \
126 } \
127 _ls_qsize = _ls_insize; \
128 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
129 if (_ls_psize == 0) { \
130 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
131 } else if (_ls_qsize == 0 || !_ls_q) { \
132 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
133 } else if (cmp(_ls_p,_ls_q) <= 0) { \
134 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
135 } else { \
136 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
137 } \
138 if (_ls_tail) { \
139 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
140 } else { \
141 _CASTASGN(list,_ls_e); \
142 } \
143 _ls_tail = _ls_e; \
144 } \
145 _ls_p = _ls_q; \
146 } \
147 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
148 if (_ls_nmerges <= 1) { \
149 _ls_looping=0; \
150 } \
151 _ls_insize *= 2; \
152 } \
153 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
154} while (0)
155
156#define DL_SORT(list, cmp) \
157do { \
158 LDECLTYPE(list) _ls_p; \
159 LDECLTYPE(list) _ls_q; \
160 LDECLTYPE(list) _ls_e; \
161 LDECLTYPE(list) _ls_tail; \
162 LDECLTYPE(list) _ls_oldhead; \
163 LDECLTYPE(list) _tmp; \
164 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
165 if (list) { \
166 _ls_insize = 1; \
167 _ls_looping = 1; \
168 while (_ls_looping) { \
169 _CASTASGN(_ls_p,list); \
170 _CASTASGN(_ls_oldhead,list); \
171 list = NULL; \
172 _ls_tail = NULL; \
173 _ls_nmerges = 0; \
174 while (_ls_p) { \
175 _ls_nmerges++; \
176 _ls_q = _ls_p; \
177 _ls_psize = 0; \
178 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
179 _ls_psize++; \
180 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
181 if (!_ls_q) break; \
182 } \
183 _ls_qsize = _ls_insize; \
184 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
185 if (_ls_psize == 0) { \
186 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
187 } else if (_ls_qsize == 0 || !_ls_q) { \
188 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
189 } else if (cmp(_ls_p,_ls_q) <= 0) { \
190 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
191 } else { \
192 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
193 } \
194 if (_ls_tail) { \
195 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
196 } else { \
197 _CASTASGN(list,_ls_e); \
198 } \
199 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
200 _ls_tail = _ls_e; \
201 } \
202 _ls_p = _ls_q; \
203 } \
204 _CASTASGN(list->prev, _ls_tail); \
205 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
206 if (_ls_nmerges <= 1) { \
207 _ls_looping=0; \
208 } \
209 _ls_insize *= 2; \
210 } \
211 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
212} while (0)
213
214#define CDL_SORT(list, cmp) \
215do { \
216 LDECLTYPE(list) _ls_p; \
217 LDECLTYPE(list) _ls_q; \
218 LDECLTYPE(list) _ls_e; \
219 LDECLTYPE(list) _ls_tail; \
220 LDECLTYPE(list) _ls_oldhead; \
221 LDECLTYPE(list) _tmp; \
222 LDECLTYPE(list) _tmp2; \
223 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
224 if (list) { \
225 _ls_insize = 1; \
226 _ls_looping = 1; \
227 while (_ls_looping) { \
228 _CASTASGN(_ls_p,list); \
229 _CASTASGN(_ls_oldhead,list); \
230 list = NULL; \
231 _ls_tail = NULL; \
232 _ls_nmerges = 0; \
233 while (_ls_p) { \
234 _ls_nmerges++; \
235 _ls_q = _ls_p; \
236 _ls_psize = 0; \
237 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
238 _ls_psize++; \
239 _SV(_ls_q,list); \
240 if (_NEXT(_ls_q,list) == _ls_oldhead) { \
241 _ls_q = NULL; \
242 } else { \
243 _ls_q = _NEXT(_ls_q,list); \
244 } \
245 _RS(list); \
246 if (!_ls_q) break; \
247 } \
248 _ls_qsize = _ls_insize; \
249 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
250 if (_ls_psize == 0) { \
251 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
252 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
253 } else if (_ls_qsize == 0 || !_ls_q) { \
254 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
255 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
256 } else if (cmp(_ls_p,_ls_q) <= 0) { \
257 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
258 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
259 } else { \
260 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
261 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
262 } \
263 if (_ls_tail) { \
264 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
265 } else { \
266 _CASTASGN(list,_ls_e); \
267 } \
268 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
269 _ls_tail = _ls_e; \
270 } \
271 _ls_p = _ls_q; \
272 } \
273 _CASTASGN(list->prev,_ls_tail); \
274 _CASTASGN(_tmp2,list); \
275 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
276 if (_ls_nmerges <= 1) { \
277 _ls_looping=0; \
278 } \
279 _ls_insize *= 2; \
280 } \
281 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
282} while (0)
283
284/******************************************************************************
285 * singly linked list macros (non-circular) *
286 *****************************************************************************/
287#define LL_PREPEND(head,add) \
288do { \
289 (add)->next = head; \
290 head = add; \
291} while (0)
292
293#define LL_APPEND(head,add) \
294do { \
295 LDECLTYPE(head) _tmp; \
296 (add)->next=NULL; \
297 if (head) { \
298 _tmp = head; \
299 while (_tmp->next) { _tmp = _tmp->next; } \
300 _tmp->next=(add); \
301 } else { \
302 (head)=(add); \
303 } \
304} while (0)
305
306#define LL_DELETE(head,del) \
307do { \
308 LDECLTYPE(head) _tmp; \
309 if ((head) == (del)) { \
310 (head)=(head)->next; \
311 } else { \
312 _tmp = head; \
313 while (_tmp->next && (_tmp->next != (del))) { \
314 _tmp = _tmp->next; \
315 } \
316 if (_tmp->next) { \
317 _tmp->next = ((del)->next); \
318 } \
319 } \
320} while (0)
321
322/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
323#define LL_APPEND_VS2008(head,add) \
324do { \
325 if (head) { \
326 (add)->next = head; /* use add->next as a temp variable */ \
327 while ((add)->next->next) { (add)->next = (add)->next->next; } \
328 (add)->next->next=(add); \
329 } else { \
330 (head)=(add); \
331 } \
332 (add)->next=NULL; \
333} while (0)
334
335#define LL_DELETE_VS2008(head,del) \
336do { \
337 if ((head) == (del)) { \
338 (head)=(head)->next; \
339 } else { \
340 char *_tmp = (char*)(head); \
341 while (head->next && (head->next != (del))) { \
342 head = head->next; \
343 } \
344 if (head->next) { \
345 head->next = ((del)->next); \
346 } \
347 { \
348 char **_head_alias = (char**)&(head); \
349 *_head_alias = _tmp; \
350 } \
351 } \
352} while (0)
353#ifdef NO_DECLTYPE
354#undef LL_APPEND
355#define LL_APPEND LL_APPEND_VS2008
356#undef LL_DELETE
357#define LL_DELETE LL_DELETE_VS2008
358#endif
359/* end VS2008 replacements */
360
361#define LL_FOREACH(head,el) \
362 for(el=head;el;el=el->next)
363
364#define LL_FOREACH_SAFE(head,el,tmp) \
365 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
366
367#define LL_SEARCH_SCALAR(head,out,field,val) \
368do { \
369 LL_FOREACH(head,out) { \
370 if ((out)->field == (val)) break; \
371 } \
372} while(0)
373
374#define LL_SEARCH(head,out,elt,cmp) \
375do { \
376 LL_FOREACH(head,out) { \
377 if ((cmp(out,elt))==0) break; \
378 } \
379} while(0)
380
381/******************************************************************************
382 * doubly linked list macros (non-circular) *
383 *****************************************************************************/
384#define DL_PREPEND(head,add) \
385do { \
386 (add)->next = head; \
387 if (head) { \
388 (add)->prev = (head)->prev; \
389 (head)->prev = (add); \
390 } else { \
391 (add)->prev = (add); \
392 } \
393 (head) = (add); \
394} while (0)
395
396#define DL_APPEND(head,add) \
397do { \
398 if (head) { \
399 (add)->prev = (head)->prev; \
400 (head)->prev->next = (add); \
401 (head)->prev = (add); \
402 (add)->next = NULL; \
403 } else { \
404 (head)=(add); \
405 (head)->prev = (head); \
406 (head)->next = NULL; \
407 } \
408} while (0);
409
410#define DL_DELETE(head,del) \
411do { \
412 if ((del)->prev == (del)) { \
413 (head)=NULL; \
414 } else if ((del)==(head)) { \
415 (del)->next->prev = (del)->prev; \
416 (head) = (del)->next; \
417 } else { \
418 (del)->prev->next = (del)->next; \
419 if ((del)->next) { \
420 (del)->next->prev = (del)->prev; \
421 } else { \
422 (head)->prev = (del)->prev; \
423 } \
424 } \
425} while (0);
426
427
428#define DL_FOREACH(head,el) \
429 for(el=head;el;el=el->next)
430
431/* this version is safe for deleting the elements during iteration */
432#define DL_FOREACH_SAFE(head,el,tmp) \
433 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
434
435/* these are identical to their singly-linked list counterparts */
436#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
437#define DL_SEARCH LL_SEARCH
438
439/******************************************************************************
440 * circular doubly linked list macros *
441 *****************************************************************************/
442#define CDL_PREPEND(head,add) \
443do { \
444 if (head) { \
445 (add)->prev = (head)->prev; \
446 (add)->next = (head); \
447 (head)->prev = (add); \
448 (add)->prev->next = (add); \
449 } else { \
450 (add)->prev = (add); \
451 (add)->next = (add); \
452 } \
453(head)=(add); \
454} while (0)
455
456#define CDL_DELETE(head,del) \
457do { \
458 if ( ((head)==(del)) && ((head)->next == (head))) { \
459 (head) = 0L; \
460 } else { \
461 (del)->next->prev = (del)->prev; \
462 (del)->prev->next = (del)->next; \
463 if ((del) == (head)) (head)=(del)->next; \
464 } \
465} while (0);
466
467#define CDL_FOREACH(head,el) \
468 for(el=head;el;el=(el->next==head ? 0L : el->next))
469
470#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
471 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
472 (el) && ((tmp2)=(el)->next, 1); \
473 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
474
475#define CDL_SEARCH_SCALAR(head,out,field,val) \
476do { \
477 CDL_FOREACH(head,out) { \
478 if ((out)->field == (val)) break; \
479 } \
480} while(0)
481
482#define CDL_SEARCH(head,out,elt,cmp) \
483do { \
484 CDL_FOREACH(head,out) { \
485 if ((cmp(out,elt))==0) break; \
486 } \
487} while(0)
488
489#endif /* UTLIST_H */
490
diff --git a/libs/cocos2d/ccConfig.h b/libs/cocos2d/ccConfig.h new file mode 100755 index 0000000..55b4cd8 --- /dev/null +++ b/libs/cocos2d/ccConfig.h
@@ -0,0 +1,334 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import <Availability.h>
28
29/**
30 @file
31 cocos2d (cc) configuration file
32*/
33
34/** @def CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
35 If enabled, the texture coordinates will be calculated by using this formula:
36 - texCoord.left = (rect.origin.x*2+1) / (texture.wide*2);
37 - texCoord.right = texCoord.left + (rect.size.width*2-2)/(texture.wide*2);
38
39 The same for bottom and top.
40
41 This formula prevents artifacts by using 99% of the texture.
42 The "correct" way to prevent artifacts is by using the spritesheet-artifact-fixer.py or a similar tool.
43
44 Affected nodes:
45 - CCSprite / CCSpriteBatchNode and subclasses: CCLabelBMFont, CCTMXTiledMap
46 - CCLabelAtlas
47 - CCQuadParticleSystem
48 - CCTileMap
49
50 To enabled set it to 1. Disabled by default.
51
52 @since v0.99.5
53 */
54#ifndef CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
55#define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 0
56#endif
57
58
59/** @def CC_FONT_LABEL_SUPPORT
60 If enabled, FontLabel will be used to render .ttf files.
61 If the .ttf file is not found, then it will use the standard UIFont class
62 If disabled, the standard UIFont class will be used.
63
64 To disable set it to 0. Enabled by default.
65
66 Only valid for cocos2d-ios. Not supported on cocos2d-mac
67 */
68#ifndef CC_FONT_LABEL_SUPPORT
69#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
70#define CC_FONT_LABEL_SUPPORT 1
71#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
72#define CC_FONT_LABEL_SUPPORT 0
73#endif
74#endif
75
76/** @def CC_DIRECTOR_FAST_FPS
77 If enabled, then the FPS will be drawn using CCLabelAtlas (fast rendering).
78 You will need to add the fps_images.png to your project.
79 If disabled, the FPS will be rendered using CCLabel (slow rendering)
80
81 To enable set it to a value different than 0. Enabled by default.
82 */
83#ifndef CC_DIRECTOR_FAST_FPS
84#define CC_DIRECTOR_FAST_FPS 1
85#endif
86
87/** @def CC_DIRECTOR_FPS_INTERVAL
88 Senconds between FPS updates.
89 0.5 seconds, means that the FPS number will be updated every 0.5 seconds.
90 Having a bigger number means a more reliable FPS
91
92 Default value: 0.1f
93 */
94#ifndef CC_DIRECTOR_FPS_INTERVAL
95#define CC_DIRECTOR_FPS_INTERVAL (0.1f)
96#endif
97
98/** @def CC_DIRECTOR_DISPATCH_FAST_EVENTS
99 If enabled, and only when it is used with CCFastDirector, the main loop will wait 0.04 seconds to
100 dispatch all the events, even if there are not events to dispatch.
101 If your game uses lot's of events (eg: touches) it might be a good idea to enable this feature.
102 Otherwise, it is safe to leave it disabled.
103
104 To enable set it to 1. Disabled by default.
105
106 @warning This feature is experimental
107 */
108#ifndef CC_DIRECTOR_DISPATCH_FAST_EVENTS
109#define CC_DIRECTOR_DISPATCH_FAST_EVENTS 0
110#endif
111
112/** @def CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
113 If enabled, cocos2d-mac will run on the Display Link thread. If disabled cocos2d-mac will run in its own thread.
114
115 If enabled, the images will be drawn at the "correct" time, but the events might not be very responsive.
116 If disabled, some frames might be skipped, but the events will be dispatched as they arrived.
117
118 To enable set it to a 1, to disable it set to 0. Enabled by default.
119
120 Only valid for cocos2d-mac. Not supported on cocos2d-ios.
121
122 */
123#ifndef CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
124#define CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 1
125#endif
126
127/** @def CC_COCOSNODE_RENDER_SUBPIXEL
128 If enabled, the CCNode objects (CCSprite, CCLabel,etc) will be able to render in subpixels.
129 If disabled, integer pixels will be used.
130
131 To enable set it to 1. Enabled by default.
132 */
133#ifndef CC_COCOSNODE_RENDER_SUBPIXEL
134#define CC_COCOSNODE_RENDER_SUBPIXEL 1
135#endif
136
137/** @def CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
138 If enabled, the CCSprite objects rendered with CCSpriteBatchNode will be able to render in subpixels.
139 If disabled, integer pixels will be used.
140
141 To enable set it to 1. Enabled by default.
142 */
143#ifndef CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
144#define CC_SPRITEBATCHNODE_RENDER_SUBPIXEL 1
145#endif
146
147/** @def CC_USES_VBO
148 If enabled, batch nodes (texture atlas and particle system) will use VBO instead of vertex list (VBO is recommended by Apple)
149
150 To enable set it to 1.
151 Enabled by default on iPhone with ARMv7 processors, iPhone Simulator and Mac
152 Disabled by default on iPhone with ARMv6 processors.
153
154 @since v0.99.5
155 */
156#ifndef CC_USES_VBO
157#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
158#define CC_USES_VBO 1
159#else
160#define CC_USES_VBO 0
161#endif
162#endif
163
164/** @def CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
165 If enabled, CCNode will transform the nodes using a cached Affine matrix.
166 If disabled, the node will be transformed using glTranslate,glRotate,glScale.
167 Using the affine matrix only requires 2 GL calls.
168 Using the translate/rotate/scale requires 5 GL calls.
169 But computing the Affine matrix is relative expensive.
170 But according to performance tests, Affine matrix performs better.
171 This parameter doesn't affect CCSpriteBatchNode nodes.
172
173 To enable set it to a value different than 0. Enabled by default.
174
175 */
176#ifndef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
177#define CC_NODE_TRANSFORM_USING_AFFINE_MATRIX 1
178#endif
179
180/** @def CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
181 If most of your imamges have pre-multiplied alpha, set it to 1 (if you are going to use .PNG/.JPG file images).
182 Only set to 0 if ALL your images by-pass Apple UIImage loading system (eg: if you use libpng or PVR images)
183
184 To enable set it to a value different than 0. Enabled by default.
185
186 @since v0.99.5
187 */
188#ifndef CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
189#define CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA 1
190#endif
191
192/** @def CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
193 Use GL_TRIANGLE_STRIP instead of GL_TRIANGLES when rendering the texture atlas.
194 It seems it is the recommend way, but it is much slower, so, enable it at your own risk
195
196 To enable set it to a value different than 0. Disabled by default.
197
198 */
199#ifndef CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
200#define CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP 0
201#endif
202
203/** @def CC_TEXTURE_NPOT_SUPPORT
204 If enabled, NPOT textures will be used where available. Only 3rd gen (and newer) devices support NPOT textures.
205 NPOT textures have the following limitations:
206 - They can't have mipmaps
207 - They only accept GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}
208
209 To enable set it to a value different than 0. Disabled by default.
210
211 This value governs only the PNG, GIF, BMP, images.
212 This value DOES NOT govern the PVR (PVR.GZ, PVR.CCZ) files. If NPOT PVR is loaded, then it will create an NPOT texture ignoring this value.
213
214 @deprecated This value will be removed in 1.1 and NPOT textures will be loaded by default if the device supports it.
215
216 @since v0.99.2
217 */
218#ifndef CC_TEXTURE_NPOT_SUPPORT
219#define CC_TEXTURE_NPOT_SUPPORT 0
220#endif
221
222/** @def CC_RETINA_DISPLAY_SUPPORT
223 If enabled, cocos2d supports retina display.
224 For performance reasons, it's recommended disable it in games without retina display support, like iPad only games.
225
226 To enable set it to 1. Use 0 to disable it. Enabled by default.
227
228 @since v0.99.5
229 */
230#ifndef CC_RETINA_DISPLAY_SUPPORT
231#define CC_RETINA_DISPLAY_SUPPORT 1
232#endif
233
234/** @def CC_RETINA_DISPLAY_FILENAME_SUFFIX
235 It's the suffix that will be appended to the files in order to load "retina display" images.
236
237 On an iPhone4 with Retina Display support enabled, the file @"sprite-hd.png" will be loaded instead of @"sprite.png".
238 If the file doesn't exist it will use the non-retina display image.
239
240 Platforms: Only used on Retina Display devices like iPhone 4.
241
242 @since v0.99.5
243 */
244#ifndef CC_RETINA_DISPLAY_FILENAME_SUFFIX
245#define CC_RETINA_DISPLAY_FILENAME_SUFFIX @"-hd"
246#endif
247
248/** @def CC_USE_LA88_LABELS_ON_NEON_ARCH
249 If enabled, it will use LA88 (16-bit textures) on Neon devices for CCLabelTTF objects.
250 If it is disabled, or if it is used on another architecture it will use A8 (8-bit textures).
251 On Neon devices, LA88 textures are 6% faster than A8 textures, but then will consume 2x memory.
252
253 This feature is disabled by default.
254
255 Platforms: Only used on ARM Neon architectures like iPhone 3GS or newer and iPad.
256
257 @since v0.99.5
258 */
259#ifndef CC_USE_LA88_LABELS_ON_NEON_ARCH
260#define CC_USE_LA88_LABELS_ON_NEON_ARCH 0
261#endif
262
263/** @def CC_SPRITE_DEBUG_DRAW
264 If enabled, all subclasses of CCSprite will draw a bounding box
265 Useful for debugging purposes only. It is recommened to leave it disabled.
266
267 To enable set it to a value different than 0. Disabled by default:
268 0 -- disabled
269 1 -- draw bounding box
270 2 -- draw texture box
271 */
272#ifndef CC_SPRITE_DEBUG_DRAW
273#define CC_SPRITE_DEBUG_DRAW 0
274#endif
275
276/** @def CC_SPRITEBATCHNODE_DEBUG_DRAW
277 If enabled, all subclasses of CCSprite that are rendered using an CCSpriteBatchNode draw a bounding box.
278 Useful for debugging purposes only. It is recommened to leave it disabled.
279
280 To enable set it to a value different than 0. Disabled by default.
281 */
282#ifndef CC_SPRITEBATCHNODE_DEBUG_DRAW
283#define CC_SPRITEBATCHNODE_DEBUG_DRAW 0
284#endif
285
286/** @def CC_LABELBMFONT_DEBUG_DRAW
287 If enabled, all subclasses of CCLabelBMFont will draw a bounding box
288 Useful for debugging purposes only. It is recommened to leave it disabled.
289
290 To enable set it to a value different than 0. Disabled by default.
291 */
292#ifndef CC_LABELBMFONT_DEBUG_DRAW
293#define CC_LABELBMFONT_DEBUG_DRAW 0
294#endif
295
296/** @def CC_LABELBMFONT_DEBUG_DRAW
297 If enabled, all subclasses of CCLabeltAtlas will draw a bounding box
298 Useful for debugging purposes only. It is recommened to leave it disabled.
299
300 To enable set it to a value different than 0. Disabled by default.
301 */
302#ifndef CC_LABELATLAS_DEBUG_DRAW
303#define CC_LABELATLAS_DEBUG_DRAW 0
304#endif
305
306/** @def CC_ENABLE_PROFILERS
307 If enabled, will activate various profilers withing cocos2d. This statistical data will be output to the console
308 once per second showing average time (in milliseconds) required to execute the specific routine(s).
309 Useful for debugging purposes only. It is recommened to leave it disabled.
310
311 To enable set it to a value different than 0. Disabled by default.
312 */
313#ifndef CC_ENABLE_PROFILERS
314#define CC_ENABLE_PROFILERS 0
315#endif
316
317//
318// DON'T edit this macro.
319//
320#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
321
322#if CC_RETINA_DISPLAY_SUPPORT
323#define CC_IS_RETINA_DISPLAY_SUPPORTED 1
324#else
325#define CC_IS_RETINA_DISPLAY_SUPPORTED 0
326#endif
327
328#elif __MAC_OS_X_VERSION_MAX_ALLOWED
329
330#define CC_IS_RETINA_DISPLAY_SUPPORTED 0
331
332#endif
333
334
diff --git a/libs/cocos2d/ccMacros.h b/libs/cocos2d/ccMacros.h new file mode 100755 index 0000000..4e08725 --- /dev/null +++ b/libs/cocos2d/ccMacros.h
@@ -0,0 +1,253 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import <math.h>
28#import "ccConfig.h"
29
30#import <Foundation/Foundation.h>
31#import <Availability.h>
32
33/**
34 @file
35 cocos2d helper macros
36 */
37
38/*
39 * if COCOS2D_DEBUG is not defined, or if it is 0 then
40 * all CCLOGXXX macros will be disabled
41 *
42 * if COCOS2D_DEBUG==1 then:
43 * CCLOG() will be enabled
44 * CCLOGERROR() will be enabled
45 * CCLOGINFO() will be disabled
46 *
47 * if COCOS2D_DEBUG==2 or higher then:
48 * CCLOG() will be enabled
49 * CCLOGERROR() will be enabled
50 * CCLOGINFO() will be enabled
51 */
52#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
53#define CCLOG(...) do {} while (0)
54#define CCLOGINFO(...) do {} while (0)
55#define CCLOGERROR(...) do {} while (0)
56
57#elif COCOS2D_DEBUG == 1
58#define CCLOG(...) NSLog(__VA_ARGS__)
59#define CCLOGERROR(...) NSLog(__VA_ARGS__)
60#define CCLOGINFO(...) do {} while (0)
61
62#elif COCOS2D_DEBUG > 1
63#define CCLOG(...) NSLog(__VA_ARGS__)
64#define CCLOGERROR(...) NSLog(__VA_ARGS__)
65#define CCLOGINFO(...) NSLog(__VA_ARGS__)
66#endif // COCOS2D_DEBUG
67
68/** @def CC_SWAP
69simple macro that swaps 2 variables
70*/
71#define CC_SWAP( x, y ) \
72({ __typeof__(x) temp = (x); \
73 x = y; y = temp; \
74})
75
76
77/** @def CCRANDOM_MINUS1_1
78 returns a random float between -1 and 1
79 */
80#define CCRANDOM_MINUS1_1() ((random() / (float)0x3fffffff )-1.0f)
81
82/** @def CCRANDOM_0_1
83 returns a random float between 0 and 1
84 */
85#define CCRANDOM_0_1() ((random() / (float)0x7fffffff ))
86
87/** @def CC_DEGREES_TO_RADIANS
88 converts degrees to radians
89 */
90#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180
91
92/** @def CC_RADIANS_TO_DEGREES
93 converts radians to degrees
94 */
95#define CC_RADIANS_TO_DEGREES(__ANGLE__) ((__ANGLE__) * 57.29577951f) // PI * 180
96
97/** @def CC_BLEND_SRC
98default gl blend src function. Compatible with premultiplied alpha images.
99*/
100#if CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
101#define CC_BLEND_SRC GL_ONE
102#define CC_BLEND_DST GL_ONE_MINUS_SRC_ALPHA
103#else
104#define CC_BLEND_SRC GL_SRC_ALPHA
105#define CC_BLEND_DST GL_ONE_MINUS_SRC_ALPHA
106#endif // ! CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
107
108/** @def CC_ENABLE_DEFAULT_GL_STATES
109 GL states that are enabled:
110 - GL_TEXTURE_2D
111 - GL_VERTEX_ARRAY
112 - GL_TEXTURE_COORD_ARRAY
113 - GL_COLOR_ARRAY
114 */
115#define CC_ENABLE_DEFAULT_GL_STATES() { \
116 glEnableClientState(GL_VERTEX_ARRAY); \
117 glEnableClientState(GL_COLOR_ARRAY); \
118 glEnableClientState(GL_TEXTURE_COORD_ARRAY); \
119 glEnable(GL_TEXTURE_2D); \
120}
121
122/** @def CC_DISABLE_DEFAULT_GL_STATES
123 Disable default GL states:
124 - GL_TEXTURE_2D
125 - GL_VERTEX_ARRAY
126 - GL_TEXTURE_COORD_ARRAY
127 - GL_COLOR_ARRAY
128 */
129#define CC_DISABLE_DEFAULT_GL_STATES() { \
130 glDisable(GL_TEXTURE_2D); \
131 glDisableClientState(GL_TEXTURE_COORD_ARRAY); \
132 glDisableClientState(GL_COLOR_ARRAY); \
133 glDisableClientState(GL_VERTEX_ARRAY); \
134}
135
136/** @def CC_DIRECTOR_INIT
137 - Initializes an EAGLView with 0-bit depth format, and RGB565 render buffer.
138 - The EAGLView view will have multiple touches disabled.
139 - It will create a UIWindow and it will assign it the 'window' variable. 'window' must be declared before calling this marcro.
140 - It will parent the EAGLView to the created window
141 - If the firmware >= 3.1 it will create a Display Link Director. Else it will create an NSTimer director.
142 - It will try to run at 60 FPS.
143 - The FPS won't be displayed.
144 - The orientation will be portrait.
145 - It will connect the director with the EAGLView.
146
147 IMPORTANT: If you want to use another type of render buffer (eg: RGBA8)
148 or if you want to use a 16-bit or 24-bit depth buffer, you should NOT
149 use this macro. Instead, you should create the EAGLView manually.
150
151 @since v0.99.4
152 */
153
154#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
155
156#define CC_DIRECTOR_INIT() \
157do { \
158 window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; \
159 if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] ) \
160 [CCDirector setDirectorType:kCCDirectorTypeNSTimer]; \
161 CCDirector *__director = [CCDirector sharedDirector]; \
162 [__director setDeviceOrientation:kCCDeviceOrientationPortrait]; \
163 [__director setDisplayFPS:NO]; \
164 [__director setAnimationInterval:1.0/60]; \
165 EAGLView *__glView = [EAGLView viewWithFrame:[window bounds] \
166 pixelFormat:kEAGLColorFormatRGB565 \
167 depthFormat:0 /* GL_DEPTH_COMPONENT24_OES */ \
168 preserveBackbuffer:NO \
169 sharegroup:nil \
170 multiSampling:NO \
171 numberOfSamples:0 \
172 ]; \
173 [__director setOpenGLView:__glView]; \
174 [window addSubview:__glView]; \
175 [window makeKeyAndVisible]; \
176} while(0)
177
178
179#elif __MAC_OS_X_VERSION_MAX_ALLOWED
180
181#import "Platforms/Mac/MacWindow.h"
182
183#define CC_DIRECTOR_INIT(__WINSIZE__) \
184do { \
185 NSRect frameRect = NSMakeRect(0, 0, (__WINSIZE__).width, (__WINSIZE__).height); \
186 self.window = [[MacWindow alloc] initWithFrame:frameRect fullscreen:NO]; \
187 self.glView = [[MacGLView alloc] initWithFrame:frameRect shareContext:nil]; \
188 [self.window setContentView:self.glView]; \
189 CCDirector *__director = [CCDirector sharedDirector]; \
190 [__director setDisplayFPS:NO]; \
191 [__director setOpenGLView:self.glView]; \
192 [(CCDirectorMac*)__director setOriginalWinSize:__WINSIZE__]; \
193 [self.window makeMainWindow]; \
194 [self.window makeKeyAndOrderFront:self]; \
195} while(0)
196
197#endif
198
199
200 /** @def CC_DIRECTOR_END
201 Stops and removes the director from memory.
202 Removes the EAGLView from its parent
203
204 @since v0.99.4
205 */
206#define CC_DIRECTOR_END() \
207do { \
208 CCDirector *__director = [CCDirector sharedDirector]; \
209 CC_GLVIEW *__view = [__director openGLView]; \
210 [__view removeFromSuperview]; \
211 [__director end]; \
212} while(0)
213
214
215#if CC_IS_RETINA_DISPLAY_SUPPORTED
216
217/****************************/
218/** RETINA DISPLAY ENABLED **/
219/****************************/
220
221/** @def CC_CONTENT_SCALE_FACTOR
222 On Mac it returns 1;
223 On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1
224 */
225#import "Platforms/iOS/CCDirectorIOS.h"
226#define CC_CONTENT_SCALE_FACTOR() __ccContentScaleFactor
227
228
229/** @def CC_RECT_PIXELS_TO_POINTS
230 Converts a rect in pixels to points
231 */
232#define CC_RECT_PIXELS_TO_POINTS(__pixels__) \
233 CGRectMake( (__pixels__).origin.x / CC_CONTENT_SCALE_FACTOR(), (__pixels__).origin.y / CC_CONTENT_SCALE_FACTOR(), \
234 (__pixels__).size.width / CC_CONTENT_SCALE_FACTOR(), (__pixels__).size.height / CC_CONTENT_SCALE_FACTOR() )
235
236/** @def CC_RECT_POINTS_TO_PIXELS
237 Converts a rect in points to pixels
238 */
239#define CC_RECT_POINTS_TO_PIXELS(__points__) \
240 CGRectMake( (__points__).origin.x * CC_CONTENT_SCALE_FACTOR(), (__points__).origin.y * CC_CONTENT_SCALE_FACTOR(), \
241 (__points__).size.width * CC_CONTENT_SCALE_FACTOR(), (__points__).size.height * CC_CONTENT_SCALE_FACTOR() )
242
243#else // retina disabled
244
245/*****************************/
246/** RETINA DISPLAY DISABLED **/
247/*****************************/
248
249#define CC_CONTENT_SCALE_FACTOR() 1
250#define CC_RECT_PIXELS_TO_POINTS(__pixels__) __pixels__
251#define CC_RECT_POINTS_TO_PIXELS(__points__) __points__
252
253#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
diff --git a/libs/cocos2d/ccTypes.h b/libs/cocos2d/ccTypes.h new file mode 100755 index 0000000..46917b3 --- /dev/null +++ b/libs/cocos2d/ccTypes.h
@@ -0,0 +1,287 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27/**
28 @file
29 cocos2d (cc) types
30*/
31
32#import <Availability.h>
33#import <Foundation/Foundation.h>
34
35#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
36#import <CoreGraphics/CGGeometry.h> // CGPoint
37#endif
38
39#import "Platforms/CCGL.h"
40
41/** RGB color composed of bytes 3 bytes
42@since v0.8
43 */
44typedef struct _ccColor3B
45{
46 GLubyte r;
47 GLubyte g;
48 GLubyte b;
49} ccColor3B;
50
51//! helper macro that creates an ccColor3B type
52static inline ccColor3B
53ccc3(const GLubyte r, const GLubyte g, const GLubyte b)
54{
55 ccColor3B c = {r, g, b};
56 return c;
57}
58//ccColor3B predefined colors
59//! White color (255,255,255)
60static const ccColor3B ccWHITE = {255,255,255};
61//! Yellow color (255,255,0)
62static const ccColor3B ccYELLOW = {255,255,0};
63//! Blue color (0,0,255)
64static const ccColor3B ccBLUE = {0,0,255};
65//! Green Color (0,255,0)
66static const ccColor3B ccGREEN = {0,255,0};
67//! Red Color (255,0,0,)
68static const ccColor3B ccRED = {255,0,0};
69//! Magenta Color (255,0,255)
70static const ccColor3B ccMAGENTA = {255,0,255};
71//! Black Color (0,0,0)
72static const ccColor3B ccBLACK = {0,0,0};
73//! Orange Color (255,127,0)
74static const ccColor3B ccORANGE = {255,127,0};
75//! Gray Color (166,166,166)
76static const ccColor3B ccGRAY = {166,166,166};
77
78/** RGBA color composed of 4 bytes
79@since v0.8
80*/
81typedef struct _ccColor4B
82{
83 GLubyte r;
84 GLubyte g;
85 GLubyte b;
86 GLubyte a;
87} ccColor4B;
88//! helper macro that creates an ccColor4B type
89static inline ccColor4B
90ccc4(const GLubyte r, const GLubyte g, const GLubyte b, const GLubyte o)
91{
92 ccColor4B c = {r, g, b, o};
93 return c;
94}
95
96
97/** RGBA color composed of 4 floats
98@since v0.8
99*/
100typedef struct _ccColor4F {
101 GLfloat r;
102 GLfloat g;
103 GLfloat b;
104 GLfloat a;
105} ccColor4F;
106
107/** Returns a ccColor4F from a ccColor3B. Alpha will be 1.
108 @since v0.99.1
109 */
110static inline ccColor4F ccc4FFromccc3B(ccColor3B c)
111{
112 return (ccColor4F){c.r/255.f, c.g/255.f, c.b/255.f, 1.f};
113}
114
115/** Returns a ccColor4F from a ccColor4B.
116 @since v0.99.1
117 */
118static inline ccColor4F ccc4FFromccc4B(ccColor4B c)
119{
120 return (ccColor4F){c.r/255.f, c.g/255.f, c.b/255.f, c.a/255.f};
121}
122
123/** returns YES if both ccColor4F are equal. Otherwise it returns NO.
124 @since v0.99.1
125 */
126static inline BOOL ccc4FEqual(ccColor4F a, ccColor4F b)
127{
128 return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
129}
130
131/** A vertex composed of 2 GLfloats: x, y
132 @since v0.8
133 */
134typedef struct _ccVertex2F
135{
136 GLfloat x;
137 GLfloat y;
138} ccVertex2F;
139
140/** A vertex composed of 2 floats: x, y
141 @since v0.8
142 */
143typedef struct _ccVertex3F
144{
145 GLfloat x;
146 GLfloat y;
147 GLfloat z;
148} ccVertex3F;
149
150/** A texcoord composed of 2 floats: u, y
151 @since v0.8
152 */
153typedef struct _ccTex2F {
154 GLfloat u;
155 GLfloat v;
156} ccTex2F;
157
158
159//! Point Sprite component
160typedef struct _ccPointSprite
161{
162 ccVertex2F pos; // 8 bytes
163 ccColor4B color; // 4 bytes
164 GLfloat size; // 4 bytes
165} ccPointSprite;
166
167//! A 2D Quad. 4 * 2 floats
168typedef struct _ccQuad2 {
169 ccVertex2F tl;
170 ccVertex2F tr;
171 ccVertex2F bl;
172 ccVertex2F br;
173} ccQuad2;
174
175
176//! A 3D Quad. 4 * 3 floats
177typedef struct _ccQuad3 {
178 ccVertex3F bl;
179 ccVertex3F br;
180 ccVertex3F tl;
181 ccVertex3F tr;
182} ccQuad3;
183
184//! A 2D grid size
185typedef struct _ccGridSize
186{
187 NSInteger x;
188 NSInteger y;
189} ccGridSize;
190
191//! helper function to create a ccGridSize
192static inline ccGridSize
193ccg(const NSInteger x, const NSInteger y)
194{
195 ccGridSize v = {x, y};
196 return v;
197}
198
199//! a Point with a vertex point, a tex coord point and a color 4B
200typedef struct _ccV2F_C4B_T2F
201{
202 //! vertices (2F)
203 ccVertex2F vertices;
204 //! colors (4B)
205 ccColor4B colors;
206 //! tex coords (2F)
207 ccTex2F texCoords;
208} ccV2F_C4B_T2F;
209
210//! a Point with a vertex point, a tex coord point and a color 4F
211typedef struct _ccV2F_C4F_T2F
212{
213 //! vertices (2F)
214 ccVertex2F vertices;
215 //! colors (4F)
216 ccColor4F colors;
217 //! tex coords (2F)
218 ccTex2F texCoords;
219} ccV2F_C4F_T2F;
220
221//! a Point with a vertex point, a tex coord point and a color 4B
222typedef struct _ccV3F_C4B_T2F
223{
224 //! vertices (3F)
225 ccVertex3F vertices; // 12 bytes
226// char __padding__[4];
227
228 //! colors (4B)
229 ccColor4B colors; // 4 bytes
230// char __padding2__[4];
231
232 // tex coords (2F)
233 ccTex2F texCoords; // 8 byts
234} ccV3F_C4B_T2F;
235
236//! 4 ccVertex2FTex2FColor4B Quad
237typedef struct _ccV2F_C4B_T2F_Quad
238{
239 //! bottom left
240 ccV2F_C4B_T2F bl;
241 //! bottom right
242 ccV2F_C4B_T2F br;
243 //! top left
244 ccV2F_C4B_T2F tl;
245 //! top right
246 ccV2F_C4B_T2F tr;
247} ccV2F_C4B_T2F_Quad;
248
249//! 4 ccVertex3FTex2FColor4B
250typedef struct _ccV3F_C4B_T2F_Quad
251{
252 //! top left
253 ccV3F_C4B_T2F tl;
254 //! bottom left
255 ccV3F_C4B_T2F bl;
256 //! top right
257 ccV3F_C4B_T2F tr;
258 //! bottom right
259 ccV3F_C4B_T2F br;
260} ccV3F_C4B_T2F_Quad;
261
262//! 4 ccVertex2FTex2FColor4F Quad
263typedef struct _ccV2F_C4F_T2F_Quad
264{
265 //! bottom left
266 ccV2F_C4F_T2F bl;
267 //! bottom right
268 ccV2F_C4F_T2F br;
269 //! top left
270 ccV2F_C4F_T2F tl;
271 //! top right
272 ccV2F_C4F_T2F tr;
273} ccV2F_C4F_T2F_Quad;
274
275//! Blend Function used for textures
276typedef struct _ccBlendFunc
277{
278 //! source blend function
279 GLenum src;
280 //! destination blend function
281 GLenum dst;
282} ccBlendFunc;
283
284//! delta time type
285//! if you want more resolution redefine it as a double
286typedef float ccTime;
287//typedef double ccTime;
diff --git a/libs/cocos2d/cocos2d.h b/libs/cocos2d/cocos2d.h new file mode 100755 index 0000000..fed2a9b --- /dev/null +++ b/libs/cocos2d/cocos2d.h
@@ -0,0 +1,161 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26/** @mainpage cocos2d for iPhone API reference
27 *
28 * @image html Icon.png
29 *
30 * @section intro Introduction
31 * This is cocos2d API reference
32 *
33 * The programming guide is hosted here: http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:index
34 *
35 * <hr>
36 *
37 * @todo A native english speaker should check the grammar. We need your help!
38 *
39 */
40
41// 0x00 HI ME LO
42// 00 01 00 00
43#define COCOS2D_VERSION 0x00010000
44
45#import <Availability.h>
46
47//
48// all cocos2d include files
49//
50#import "ccConfig.h" // should be included first
51
52#import "CCActionManager.h"
53#import "CCAction.h"
54#import "CCActionInstant.h"
55#import "CCActionInterval.h"
56#import "CCActionEase.h"
57#import "CCActionCamera.h"
58#import "CCActionTween.h"
59#import "CCActionEase.h"
60#import "CCActionTiledGrid.h"
61#import "CCActionGrid3D.h"
62#import "CCActionGrid.h"
63#import "CCActionProgressTimer.h"
64#import "CCActionPageTurn3D.h"
65
66#import "CCAnimation.h"
67#import "CCAnimationCache.h"
68#import "CCSprite.h"
69#import "CCSpriteFrame.h"
70#import "CCSpriteBatchNode.h"
71#import "CCSpriteFrameCache.h"
72
73#import "CCLabelTTF.h"
74#import "CCLabelBMFont.h"
75#import "CCLabelAtlas.h"
76
77#import "CCParticleSystem.h"
78#import "CCParticleSystemPoint.h"
79#import "CCParticleSystemQuad.h"
80#import "CCParticleExamples.h"
81
82#import "CCTexture2D.h"
83#import "CCTexturePVR.h"
84#import "CCTextureCache.h"
85#import "CCTextureAtlas.h"
86
87#import "CCTransition.h"
88#import "CCTransitionPageTurn.h"
89#import "CCTransitionRadial.h"
90
91#import "CCTMXTiledMap.h"
92#import "CCTMXLayer.h"
93#import "CCTMXObjectGroup.h"
94#import "CCTMXXMLParser.h"
95#import "CCTileMapAtlas.h"
96
97#import "CCLayer.h"
98#import "CCMenu.h"
99#import "CCMenuItem.h"
100#import "CCDrawingPrimitives.h"
101#import "CCScene.h"
102#import "CCScheduler.h"
103#import "CCBlockSupport.h"
104#import "CCCamera.h"
105#import "CCProtocols.h"
106#import "CCNode.h"
107#import "CCDirector.h"
108#import "CCAtlasNode.h"
109#import "CCGrabber.h"
110#import "CCGrid.h"
111#import "CCParallaxNode.h"
112#import "CCRenderTexture.h"
113#import "CCMotionStreak.h"
114#import "CCConfiguration.h"
115
116//
117// cocos2d macros
118//
119#import "ccTypes.h"
120#import "ccMacros.h"
121
122
123// Platform common
124#import "Platforms/CCGL.h"
125#import "Platforms/CCNS.h"
126
127#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
128#import "Platforms/iOS/CCTouchDispatcher.h"
129#import "Platforms/iOS/CCTouchDelegateProtocol.h"
130#import "Platforms/iOS/CCTouchHandler.h"
131#import "Platforms/iOS/EAGLView.h"
132#import "Platforms/iOS/CCDirectorIOS.h"
133
134#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
135#import "Platforms/Mac/MacGLView.h"
136#import "Platforms/Mac/CCDirectorMac.h"
137#endif
138
139//
140// cocos2d helper files
141//
142#import "Support/OpenGL_Internal.h"
143#import "Support/CCFileUtils.h"
144#import "Support/CGPointExtension.h"
145#import "Support/ccCArray.h"
146#import "Support/CCArray.h"
147#import "Support/ccUtils.h"
148
149#if CC_ENABLE_PROFILERS
150#import "Support/CCProfiling.h"
151#endif // CC_ENABLE_PROFILERS
152
153
154// free functions
155NSString * cocos2dVersion(void);
156
157#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
158#ifndef __IPHONE_4_0
159#error "If you are targeting iPad, you should set BASE SDK = 4.0 (or 4.1, or 4.2), and set the 'iOS deploy target' = 3.2"
160#endif
161#endif
diff --git a/libs/cocos2d/cocos2d.m b/libs/cocos2d/cocos2d.m new file mode 100755 index 0000000..8df3b6f --- /dev/null +++ b/libs/cocos2d/cocos2d.m
@@ -0,0 +1,34 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26
27#import <Foundation/Foundation.h>
28#import "cocos2d.h"
29static NSString *version = @"cocos2d v1.0.0";
30
31NSString *cocos2dVersion()
32{
33 return version;
34}
diff --git a/libs/cocoslive/CLScoreServerPost.h b/libs/cocoslive/CLScoreServerPost.h new file mode 100755 index 0000000..e782b90 --- /dev/null +++ b/libs/cocoslive/CLScoreServerPost.h
@@ -0,0 +1,142 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import <UIKit/UIKit.h>
30
31// for MD5 signing
32#import <CommonCrypto/CommonDigest.h>
33
34// cocoslive definitions
35#import "cocoslive.h"
36
37// Score Server protocol version
38#define SCORE_SERVER_PROTOCOL_VERSION @"1.1"
39
40// Server URL
41#ifdef USE_LOCAL_SERVER
42#define SCORE_SERVER_SEND_URL @"http://localhost:8080/api/post-score"
43#define SCORE_SERVER_UPDATE_URL @"http://localhost:8080/api/update-score"
44#else
45#define SCORE_SERVER_SEND_URL @"http://fourislandscores.appspot.com/api/post-score"
46#define SCORE_SERVER_UPDATE_URL @"http://fourislandscores.appspot.com/api/update-score"
47#endif
48
49/// Type of errors from the Post Score request
50typedef enum {
51 /// post request successful
52 kPostStatusOK = 0,
53 /// post request failed to establish a connection. wi-fi isn't enabled.
54 /// Don't retry when this option is preset
55 kPostStatusConnectionFailed = 1,
56 /// post request failed to post the score. Server might be busy.
57 /// Retry is suggested
58 kPostStatusPostFailed = 2,
59} tPostStatus;
60
61enum {
62 //! Invalid Ranking. Valid rankins are from 1 to ...
63 kServerPostInvalidRanking = 0,
64};
65
66/**
67 * Handles the Score Post to the cocos live server
68 */
69@interface CLScoreServerPost : NSObject {
70 /// game key. secret shared with the server.
71 /// used to sign the values to prevent spoofing.
72 NSString *gameKey;
73
74 /// game name, used as a login name.
75 NSString *gameName;
76
77 /// delegate instance of fetch score
78 id delegate;
79
80 /// ranking
81 NSUInteger ranking_;
82
83 /// score was updated
84 BOOL scoreDidUpdate_;
85
86 /// data received
87 NSMutableData *receivedData;
88
89 /// values to send in the POST
90 NSMutableArray *bodyValues;
91
92 /// status of the request
93 tPostStatus postStatus_;
94
95 /// mdt context
96 CC_MD5_CTX md5Ctx;
97
98 /// the connection
99 NSURLConnection *connection_;
100}
101
102/** status from the score post */
103@property (nonatomic,readonly) tPostStatus postStatus;
104
105/** connection to the server */
106@property (nonatomic, retain) NSURLConnection *connection;
107
108/** ranking of your score
109 @since v0.7.3
110 */
111@property (nonatomic,readonly) NSUInteger ranking;
112
113/** whether or not the score was updated
114 @since v0.7.3
115 */
116@property (nonatomic,readonly) BOOL scoreDidUpdate;
117
118/** creates a cocos server with a game name and a game key */
119+(id) serverWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id)delegate;
120
121/** initializes a cocos server with a game name and a game key */
122-(id) initWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id)delegate;
123
124/** send the scores to the server. A new entre will be created on the server */
125-(BOOL) sendScore: (NSDictionary*) dict;
126
127/**
128 * Sends a score dictionary to the server for updating an existing entry by playername and device id, or creating a new one.
129 * The passed dictionary must contain a cc_playername key, otherwise it will raise and exception.
130 * @since v0.7.1
131 */
132-(BOOL) updateScore: (NSDictionary*) dict;
133
134@end
135
136/** CocosLivePost protocol */
137@protocol CLPostDelegate <NSObject>
138/** callback method that will be called if the post is successful */
139-(void) scorePostOk:(id) sender;
140/** callback method that will be called if the post fails */
141-(void) scorePostFail:(id) sender;
142@end
diff --git a/libs/cocoslive/CLScoreServerPost.m b/libs/cocoslive/CLScoreServerPost.m new file mode 100755 index 0000000..43ee7b2 --- /dev/null +++ b/libs/cocoslive/CLScoreServerPost.m
@@ -0,0 +1,335 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CLScoreServerPost.h"
29#import "ccMacros.h"
30
31// free function used to sort
32NSInteger alphabeticSort(id string1, id string2, void *reverse);
33
34NSInteger alphabeticSort(id string1, id string2, void *reverse)
35{
36 if ((NSInteger *)reverse == NO)
37 return [string2 localizedCaseInsensitiveCompare:string1];
38 return [string1 localizedCaseInsensitiveCompare:string2];
39}
40
41
42@interface CLScoreServerPost (Private)
43-(void) addValue:(NSString*)value key:(NSString*)key;
44-(void) calculateHashAndAddValue:(id)value key:(NSString*)key;
45-(NSString*) getHashForData;
46-(NSData*) getBodyValues;
47-(NSString*) encodeData:(NSString*)data;
48-(NSMutableURLRequest *) scoreServerRequestWithURLString:(NSString *)url;
49-(BOOL) submitScore:(NSDictionary*)dict forUpdate:(BOOL)isUpdate;
50@end
51
52
53@implementation CLScoreServerPost
54
55@synthesize postStatus = postStatus_;
56@synthesize ranking = ranking_;
57@synthesize scoreDidUpdate = scoreDidUpdate_;
58@synthesize connection = connection_;
59
60+(id) serverWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id) delegate
61{
62 return [[[self alloc] initWithGameName:name gameKey:key delegate:delegate] autorelease];
63}
64
65-(id) initWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id)aDelegate
66{
67 self = [super init];
68 if( self ) {
69 gameKey = [key retain];
70 gameName = [name retain];
71 bodyValues = [[NSMutableArray arrayWithCapacity:5] retain];
72 delegate = [aDelegate retain];
73 receivedData = [[NSMutableData data] retain];
74
75 ranking_ = kServerPostInvalidRanking;
76 }
77
78 return self;
79}
80
81-(void) dealloc
82{
83 CCLOGINFO(@"deallocing %@", self);
84 [delegate release];
85 [gameKey release];
86 [gameName release];
87 [bodyValues release];
88 [receivedData release];
89 [connection_ release];
90 [super dealloc];
91}
92
93
94#pragma mark ScoreServer send scores
95-(BOOL) sendScore: (NSDictionary*) dict
96{
97 return [self submitScore:dict forUpdate:NO];
98}
99
100-(BOOL) updateScore: (NSDictionary*) dict
101{
102 if (![dict objectForKey:@"cc_playername"]) {
103 // fail. cc_playername + cc_device_id are needed to update an score
104 [NSException raise:@"cocosLive:updateScore" format:@"cc_playername not found"];
105 }
106 return [self submitScore:dict forUpdate:YES];
107}
108
109-(BOOL) submitScore: (NSDictionary*)dict forUpdate:(BOOL)isUpdate
110{
111 [receivedData setLength:0];
112 [bodyValues removeAllObjects];
113
114 // reset status
115 postStatus_ = kPostStatusOK;
116
117 // create the request
118 NSMutableURLRequest *post = [self scoreServerRequestWithURLString:(isUpdate ? SCORE_SERVER_UPDATE_URL : SCORE_SERVER_SEND_URL)];
119
120 CC_MD5_Init( &md5Ctx);
121
122 // hash SHALL be calculated in certain order
123 NSArray *keys = [dict allKeys];
124 int reverseSort = NO;
125 NSArray *sortedKeys = [keys sortedArrayUsingFunction:alphabeticSort context:&reverseSort];
126 for( id key in sortedKeys )
127 [self calculateHashAndAddValue:[dict objectForKey:key] key:key];
128
129 // device id is hashed to prevent spoofing this same score from different devices
130 // one way to prevent a replay attack is to send cc_id & cc_time and use it as primary keys
131
132 [self addValue:[[UIDevice currentDevice] uniqueIdentifier] key:@"cc_device_id"];
133 [self addValue:gameName key:@"cc_gamename"];
134 [self addValue:[self getHashForData] key:@"cc_hash"];
135 [self addValue:SCORE_SERVER_PROTOCOL_VERSION key:@"cc_prot_ver"];
136
137 [post setHTTPBody: [self getBodyValues] ];
138
139 // create the connection with the request
140 // and start loading the data
141 self.connection=[NSURLConnection connectionWithRequest:post delegate:self];
142
143 if ( ! connection_)
144 return NO;
145
146 return YES;
147}
148
149-(NSMutableURLRequest *) scoreServerRequestWithURLString:(NSString *)url {
150 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString: url]
151 cachePolicy:NSURLRequestUseProtocolCachePolicy
152 timeoutInterval:10.0];
153
154 [request setHTTPMethod: @"POST"];
155 [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
156 return request;
157}
158
159-(void) calculateHashAndAddValue:(id) value key:(NSString*) key
160{
161 NSString *val;
162 // value shall be a string or nsnumber
163 if( [value respondsToSelector:@selector(stringValue)] )
164 val = [value stringValue];
165 else if( [value isKindOfClass:[NSString class]] )
166 val = value;
167 else
168 [NSException raise:@"Invalid format for value" format:@"Invalid format for value. addValue"];
169
170 [self addValue:val key:key];
171
172 const char * data = [val UTF8String];
173 CC_MD5_Update( &md5Ctx, data, strlen(data) );
174}
175
176-(void) addValue:(NSString*)value key:(NSString*) key
177{
178
179 NSString *encodedValue = [self encodeData:value];
180 NSString *encodedKey = [self encodeData:key];
181
182 [bodyValues addObject: [NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue] ];
183}
184
185-(NSData*) getBodyValues {
186 NSMutableData *data = [[NSMutableData alloc] init];
187
188 BOOL first=YES;
189 for( NSString *s in bodyValues ) {
190 if( !first)
191 [data appendBytes:"&" length:1];
192
193 [data appendBytes:[s UTF8String] length:[s length]];
194 first = NO;
195 }
196
197 return [data autorelease];
198}
199
200-(NSString*) getHashForData
201{
202 NSString *ret;
203 unsigned char pTempKey[16];
204
205 // update the hash with the secret key
206 const char *data = [gameKey UTF8String];
207 CC_MD5_Update(&md5Ctx, data, strlen(data));
208
209 // then get the hash
210 CC_MD5_Final( pTempKey, &md5Ctx);
211
212// NSData *nsdata = [NSData dataWithBytes:pTempKey length:16];
213 ret = [NSString stringWithString:@""];
214 for( int i=0;i<16;i++) {
215 ret = [NSString stringWithFormat:@"%@%02x", ret, pTempKey[i] ];
216 }
217
218 return ret;
219}
220
221-(NSString*) encodeData:(NSString*) data
222{
223 NSString *newData;
224
225 newData = [data stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
226
227 // '&' and '=' should be encoded manually
228 newData = [newData stringByReplacingOccurrencesOfString:@"&" withString:@"%26"];
229 newData = [newData stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"];
230
231 return newData;
232}
233
234#pragma mark NSURLConnection Delegate
235
236- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
237{
238 // this method is called when the server has determined that it
239 // has enough information to create the NSURLResponse
240
241 // it can be called multiple times, for example in the case of a
242 // redirect, so each time we reset the data.
243 // receivedData is declared as a method instance elsewhere
244 [receivedData setLength:0];
245}
246
247- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
248{
249 // append the new data to the receivedData
250 // receivedData is declared as a method instance elsewhere
251 [receivedData appendData:data];
252
253// NSString *dataString = [NSString stringWithCString:[data bytes] length: [data length]];
254// CCLOG( @"data: %@", dataString);
255}
256
257- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
258{
259 CCLOG(@"Connection failed");
260
261 // wifi problems ?
262 postStatus_ = kPostStatusConnectionFailed;
263
264 // release the connection
265 self.connection = nil;
266
267 if( [delegate respondsToSelector:@selector(scorePostFail:) ] )
268 [delegate scorePostFail:self];
269}
270
271- (void)connectionDidFinishLoading:(NSURLConnection *)connection
272{
273 // release the connection
274 self.connection = nil;
275
276// NSString *dataString = [NSString stringWithCString:[receivedData bytes] length: [receivedData length]];
277 NSString *dataString = [NSString stringWithCString:[receivedData bytes] encoding: NSASCIIStringEncoding];
278
279 if( [dataString hasPrefix:@"OK:"] ) {
280 // parse ranking and other possible answers
281 NSArray *values = [dataString componentsSeparatedByString:@":"];
282 NSArray *answer = [ [values objectAtIndex:1] componentsSeparatedByString:@","];
283 NSEnumerator *nse = [answer objectEnumerator];
284
285 // Create a holder for each line we are going to work with
286 NSString *line;
287
288 // Loop through all the lines in the lines array processing each one
289 while( (line = [nse nextObject]) ) {
290 NSArray *keyvalue = [line componentsSeparatedByString:@"="];
291// NSLog(@"%@",keyvalue);
292 if( [[keyvalue objectAtIndex:0] isEqual:@"ranking"] ) {
293 ranking_ = [[keyvalue objectAtIndex:1] intValue];
294 } else if( [[keyvalue objectAtIndex:0] isEqual:@"score_updated"] ) {
295 scoreDidUpdate_ = [[keyvalue objectAtIndex:1] boolValue];
296 }
297
298 }
299 if( [delegate respondsToSelector:@selector(scorePostOk:) ] )
300 [delegate scorePostOk:self];
301
302 } else if( [dataString hasPrefix: @"OK"] ) {
303
304 // Ok
305 postStatus_ = kPostStatusOK;
306
307 if( [delegate respondsToSelector:@selector(scorePostOk:) ] )
308 [delegate scorePostOk:self];
309
310
311 } else {
312
313 NSLog(@"cocoslive: Post Score failed. Reason: %@", dataString);
314
315 // Error parsing answer
316 postStatus_ = kPostStatusPostFailed;
317
318 if( [delegate respondsToSelector:@selector(scorePostFail:) ] )
319 [delegate scorePostFail:self];
320 }
321}
322
323-(NSURLRequest *)connection:(NSURLConnection *)connection
324 willSendRequest:(NSURLRequest *)request
325 redirectResponse:(NSURLResponse *)redirectResponse
326{
327 NSURLRequest *newRequest=request;
328 if (redirectResponse) {
329 newRequest=nil;
330 }
331
332 return newRequest;
333}
334
335@end
diff --git a/libs/cocoslive/CLScoreServerRequest.h b/libs/cocoslive/CLScoreServerRequest.h new file mode 100755 index 0000000..2002d4c --- /dev/null +++ b/libs/cocoslive/CLScoreServerRequest.h
@@ -0,0 +1,122 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import <UIKit/UIKit.h>
30
31// cocoslive definitions
32#import "cocoslive.h"
33
34// Server URL
35#if USE_LOCAL_SERVER
36#define SCORE_SERVER_REQUEST_URL @"http://localhost:8080/api/get-scores"
37#define SCORE_SERVER_GETRANK_URL @"http://localhost:8080/api/get-rank-for-score"
38#else
39#define SCORE_SERVER_REQUEST_URL @"http://fourislandscores.appspot.com/api/get-scores"
40#define SCORE_SERVER_GETRANK_URL @"http://fourislandscores.appspot.com/api/get-rank-for-score"
41#endif
42
43/** Type of predefined Query */
44typedef enum {
45 kQueryIgnore = 0,
46 kQueryDay = 1,
47 kQueryWeek = 2,
48 kQueryMonth = 3,
49 kQueryAllTime = 4,
50} tQueryType;
51
52/** Flags that can be added to the query */
53typedef enum {
54 kQueryFlagIgnore = 0,
55 kQueryFlagByCountry = 1 << 0,
56 kQueryFlagByDevice = 1 << 1,
57} tQueryFlags;
58
59/**
60 * Handles the Request Scores to the cocos live server
61 */
62@interface CLScoreServerRequest : NSObject {
63
64 /// game name, used as a login name.
65 NSString *gameName;
66
67 /// delegate instance of fetch score
68 id delegate;
69
70 // data received
71 NSMutableData *receivedData;
72
73 // To determine which delegate method will be called in connectionDidFinishLoading: of NSURLConnection Delegate
74 BOOL reqRankOnly;
75
76 /// the connection
77 NSURLConnection *connection_;
78}
79
80/** connection to the server */
81@property (nonatomic, retain) NSURLConnection *connection;
82
83
84/** creates a ScoreServerRequest server with a game name*/
85+(id) serverWithGameName:(NSString*) name delegate:(id)delegate;
86
87/** initializes a ScoreServerRequest with a game name*/
88-(id) initWithGameName:(NSString*) name delegate:(id)delegate;
89
90/** request scores from server using a predefined query. This is an asyncronous request.
91 * limit: how many scores are being requested. Maximun is 100
92 * flags: can be kQueryFlagByCountry (fetches only scores from country)
93 * category: an NSString. For example: 'easy', 'medium', 'type1'... When requesting scores, they can be filtered by this field.
94 */
95-(BOOL) requestScores: (tQueryType) type limit:(int)limit offset:(int)offset flags:(tQueryFlags)flags category:(NSString*)category;
96
97/** request scores from server using a predefined query. This is an asyncronous request.
98 * limit: how many scores are being requested. Maximun is 100
99 * flags: can be kQueryFlagByCountry (fetches only scores from country)
100 */
101-(BOOL) requestScores: (tQueryType) type limit:(int)limit offset:(int)offset flags:(tQueryFlags)flags;
102
103/** parse the received JSON scores and convert it to objective-c objects */
104-(NSArray*) parseScores;
105
106/** request rank for a given score using a predefined query. This is an asyncronous request.
107 * score: int for a score
108 * category: an NSString. For example: 'easy', 'medium', 'type1'... When requesting ranks, they can be filtered by this field.
109 */
110-(BOOL) requestRankForScore:(int)score andCategory:(NSString*)category;
111
112/** It's actually not parsing anything, just returning int for a rank. Kept name PARSE for convinience with parseScores */
113-(int) parseRank;
114
115@end
116
117/** CocosLive Request protocol */
118@protocol CLRequestDelegate <NSObject>
119-(void) scoreRequestOk:(id) sender;
120-(void) scoreRequestRankOk:(id) sender;
121-(void) scoreRequestFail:(id) sender;
122@end
diff --git a/libs/cocoslive/CLScoreServerRequest.m b/libs/cocoslive/CLScoreServerRequest.m new file mode 100755 index 0000000..e16b895 --- /dev/null +++ b/libs/cocoslive/CLScoreServerRequest.m
@@ -0,0 +1,257 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28// 3rd party imports
29#import "CJSONDeserializer.h"
30
31// local imports
32#import "CLScoreServerPost.h"
33#import "CLScoreServerRequest.h"
34#import "ccMacros.h"
35
36@implementation CLScoreServerRequest
37
38@synthesize connection=connection_;
39
40+(id) serverWithGameName:(NSString*) name delegate:(id)delegate
41{
42 return [[[self alloc] initWithGameName:name delegate:delegate] autorelease];
43}
44
45-(id) initWithGameName:(NSString*) name delegate:(id)aDelegate
46{
47 self = [super init];
48 if( self ) {
49 gameName = [[name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] retain];
50 delegate = [aDelegate retain];
51 receivedData = [[NSMutableData data] retain];
52 }
53 return self;
54}
55
56-(void) dealloc
57{
58 CCLOGINFO(@"deallocing %@", self);
59
60 [delegate release];
61 [gameName release];
62 [receivedData release];
63 [connection_ release];
64 [super dealloc];
65}
66
67-(BOOL) requestScores:(tQueryType)type
68 limit:(int)limit
69 offset:(int)offset
70 flags:(tQueryFlags)flags
71 category:(NSString*)category
72{
73 // create the request
74 [receivedData setLength:0];
75
76 // it's not a call for rank
77 reqRankOnly = NO;
78
79 NSString *device = @"";
80 if( flags & kQueryFlagByDevice )
81 device = [[UIDevice currentDevice] uniqueIdentifier];
82
83 // arguments:
84 // query: type of query
85 // limit: how many scores are being requested. Default is 25. Maximun is 100
86 // offset: offset of the scores
87 // flags: bring only country scores, world scores, etc.
88 // category: string user defined string used to filter
89 NSString *url= [NSString stringWithFormat:@"%@?gamename=%@&querytype=%d&offset=%d&limit=%d&flags=%d&category=%@&device=%@",
90 SCORE_SERVER_REQUEST_URL,
91 gameName,
92 type,
93 offset,
94 limit,
95 flags,
96 [category stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding],
97 device
98 ];
99
100 // NSLog(@"%@", url);
101
102 NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
103 cachePolicy:NSURLRequestUseProtocolCachePolicy
104 timeoutInterval:10.0];
105
106 // create the connection with the request
107 // and start loading the data
108 self.connection=[NSURLConnection connectionWithRequest:request delegate:self];
109 if (! connection_)
110 return NO;
111
112 return YES;
113}
114
115-(BOOL) requestScores:(tQueryType)type
116 limit:(int)limit
117 offset:(int)offset
118 flags:(tQueryFlags)flags
119{
120 // create the request
121 [receivedData setLength:0];
122
123 // arguments:
124 // query: type of query
125 // limit: how many scores are being requested. Maximun is 100
126 // offset: offset of the scores
127 // flags: bring only country scores, world scores, etc.
128 return [self requestScores:type limit:limit offset:offset flags:flags category:@""];
129}
130
131-(NSArray*) parseScores
132{
133 NSArray *array = nil;
134 NSError *error = nil;
135 NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:receivedData error:&error];
136
137// NSLog(@"r: %@", dictionary);
138 if( ! error ) {
139 array = [dictionary objectForKey:@"scores"];
140 } else {
141 CCLOG(@"Error parsing scores: %@", error);
142 }
143 return array;
144}
145
146#pragma mark Request rank for score
147
148-(BOOL) requestRankForScore:(int)score andCategory:(NSString*)category {
149 // create the request
150 [receivedData setLength:0];
151
152 reqRankOnly = YES;
153
154 // arguments:
155 // score: score for which you need rank
156 // category: user defined string used to filter
157 NSString *url= [NSString stringWithFormat:@"%@?gamename=%@&category=%@&score=%d",
158 SCORE_SERVER_GETRANK_URL,
159 gameName,
160 [category stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding],
161 score
162 ];
163
164 NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
165 cachePolicy:NSURLRequestUseProtocolCachePolicy
166 timeoutInterval:10.0];
167
168 // create the connection with the request
169 // and start loading the data
170 self.connection=[NSURLConnection connectionWithRequest:request delegate:self];
171 if (! connection_)
172 return NO;
173
174 return YES;
175}
176
177-(int) parseRank {
178// NSString *rankStr = [NSString stringWithCString:[receivedData bytes] length: [receivedData length]];
179 NSString *rankStr = [NSString stringWithCString:[receivedData bytes] encoding: NSASCIIStringEncoding];
180
181// NSLog(@"XXXX: Ranking: %@", rankStr);
182
183 // creating trimmed string by trimming everything that's not numbers from the receivedData
184 NSString *trimmedStr = [rankStr stringByTrimmingCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
185
186 int scoreInt = [trimmedStr intValue];
187
188 return scoreInt;
189}
190
191
192#pragma mark NSURLConnection Delegate
193
194- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
195{
196 // this method is called when the server has determined that it
197 // has enough information to create the NSURLResponse
198
199 // it can be called multiple times, for example in the case of a
200 // redirect, so each time we reset the data.
201 // receivedData is declared as a method instance elsewhere
202
203 [receivedData setLength:0];
204}
205
206- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
207{
208 // append the new data to the receivedData
209 // receivedData is declared as a method instance elsewhere
210 [receivedData appendData:data];
211}
212
213- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
214{
215 // release the connection, and the data object
216 self.connection = nil;
217
218
219 CCLOG(@"Error getting scores: %@", error);
220
221 if( [delegate respondsToSelector:@selector(scoreRequestFail:) ] )
222 [delegate scoreRequestFail:self];
223
224}
225
226- (void)connectionDidFinishLoading:(NSURLConnection *)connection
227{
228 // release the connection, and the data object
229 self.connection = nil;
230
231
232 if(reqRankOnly) {
233 // because it's request for rank, different delegate method is called scoreRequestRankOk:
234 // if connection failed the same delegate method is used as for standard scores - scoreRequestFail:
235 if( [delegate respondsToSelector:@selector(scoreRequestRankOk:) ] ) {
236 [delegate scoreRequestRankOk:self];
237 }
238 } else {
239 if( [delegate respondsToSelector:@selector(scoreRequestOk:) ] ) {
240 [delegate scoreRequestOk:self];
241 }
242
243 }
244}
245
246-(NSURLRequest *)connection:(NSURLConnection *)connection
247 willSendRequest:(NSURLRequest *)request
248 redirectResponse:(NSURLResponse *)redirectResponse
249{
250 NSURLRequest *newRequest=request;
251 if (redirectResponse) {
252 newRequest=nil;
253 }
254 return newRequest;
255}
256
257@end
diff --git a/libs/cocoslive/cocoslive.h b/libs/cocoslive/cocoslive.h new file mode 100755 index 0000000..15dbe1a --- /dev/null +++ b/libs/cocoslive/cocoslive.h
@@ -0,0 +1,43 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29// 0x00 HI ME LO
30// 00 00 03 02
31#define COCOSLIVE_VERSION 0x00000302
32
33// to use localserver. DEBUG ONLY
34//#define USE_LOCAL_SERVER 1
35
36// all cocos live include files
37//
38#import "CLScoreServerPost.h"
39#import "CLScoreServerRequest.h"
40
41
42// free functions
43NSString * cocosLiveVersion(void);
diff --git a/libs/cocoslive/cocoslive.m b/libs/cocoslive/cocoslive.m new file mode 100755 index 0000000..613a9d7 --- /dev/null +++ b/libs/cocoslive/cocoslive.m
@@ -0,0 +1,37 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <UIKit/UIKit.h>
29
30#import "cocoslive.h"
31
32static NSString *version = @"cocoslive v0.3.2";
33
34NSString *cocosLiveVersion()
35{
36 return version;
37}