1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  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  * copy an new object
 29  * @function
 30  * @param {object|Array} obj source object
 31  * @return {Array|object}
 32  */
 33 cc.clone = function (obj) {
 34     // Cloning is better if the new object is having the same prototype chain
 35     // as the copied obj (or otherwise, the cloned object is certainly going to
 36     // have a different hidden class). Play with C1/C2 of the
 37     // PerformanceVirtualMachineTests suite to see how this makes an impact
 38     // under extreme conditions.
 39     //
 40     // Object.create(Object.getPrototypeOf(obj)) doesn't work well because the
 41     // prototype lacks a link to the constructor (Carakan, V8) so the new
 42     // object wouldn't have the hidden class that's associated with the
 43     // constructor (also, for whatever reasons, utilizing
 44     // Object.create(Object.getPrototypeOf(obj)) + Object.defineProperty is even
 45     // slower than the original in V8). Therefore, we call the constructor, but
 46     // there is a big caveat - it is possible that the this.init() in the
 47     // constructor would throw with no argument. It is also possible that a
 48     // derived class forgets to set "constructor" on the prototype. We ignore
 49     // these possibities for and the ultimate solution is a standardized
 50     // Object.clone(<object>).
 51     var newObj = (obj.constructor) ? new obj.constructor : {};
 52 
 53         // Assuming that the constuctor above initialized all properies on obj, the
 54     // following keyed assignments won't turn newObj into dictionary mode
 55     // becasue they're not *appending new properties* but *assigning existing
 56     // ones* (note that appending indexed properties is another story). See
 57     // CCClass.js for a link to the devils when the assumption fails.
 58     for (var key in obj) {
 59         var copy = obj[key];
 60         // Beware that typeof null == "object" !
 61         if (((typeof copy) == "object") && copy &&
 62             !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) {
 63             newObj[key] = cc.clone(copy);
 64         } else {
 65             newObj[key] = copy;
 66         }
 67     }
 68     return newObj;
 69 };
 70 
 71 /**
 72  * Function added for JS bindings compatibility. Not needed in cocos2d-html5.
 73  * @function
 74  * @param {object} jsObj subclass
 75  * @param {object} superclass
 76  */
 77 cc.associateWithNative = function (jsObj, superclass) {
 78 };
 79 
 80 /**
 81  * keymap
 82  * @example
 83  * //Example
 84  * //to mark a keydown
 85  * cc.keyDown[65] = true;
 86  * //or
 87  * cc.keyMap[cc.KEY.a]
 88  *
 89  * //to mark a keyup
 90  * do cc.keyDown[65] = false;
 91  *
 92  * //to find out if a key is down, check
 93  * if(cc.keyDown[65])
 94  * //or
 95  * if,(cc.keyDown[cc.KEY.space])
 96  * //if its undefined or false or null, its not pressed
 97  * @constant
 98  * @type object
 99  */
100 cc.KEY = {
101     backspace:8,
102     tab:9,
103     enter:13,
104     shift:16, //should use shiftkey instead
105     ctrl:17, //should use ctrlkey
106     alt:18, //should use altkey
107     pause:19,
108     capslock:20,
109     escape:27,
110     pageup:33,
111     pagedown:34,
112     end:35,
113     home:36,
114     left:37,
115     up:38,
116     right:39,
117     down:40,
118     insert:45,
119     Delete:46,
120     0:48,
121     1:49,
122     2:50,
123     3:51,
124     4:52,
125     5:53,
126     6:54,
127     7:55,
128     8:56,
129     9:57,
130     a:65,
131     b:66,
132     c:67,
133     d:68,
134     e:69,
135     f:70,
136     g:71,
137     h:72,
138     i:73,
139     j:74,
140     k:75,
141     l:76,
142     m:77,
143     n:78,
144     o:79,
145     p:80,
146     q:81,
147     r:82,
148     s:83,
149     t:84,
150     u:85,
151     v:86,
152     w:87,
153     x:88,
154     y:89,
155     z:90,
156     num0:96,
157     num1:97,
158     num2:98,
159     num3:99,
160     num4:100,
161     num5:101,
162     num6:102,
163     num7:103,
164     num8:104,
165     num9:105,
166     '*':106,
167     '+':107,
168     '-':109,
169     'numdel':110,
170     '/':111,
171     f1:112, //f1-f12 dont work on ie
172     f2:113,
173     f3:114,
174     f4:115,
175     f5:116,
176     f6:117,
177     f7:118,
178     f8:119,
179     f9:120,
180     f10:121,
181     f11:122,
182     f12:123,
183     numlock:144,
184     scrolllock:145,
185     semicolon:186,
186     ',':186,
187     equal:187,
188     '=':187,
189     ';':188,
190     comma:188,
191     dash:189,
192     '.':190,
193     period:190,
194     forwardslash:191,
195     grave:192,
196     '[':219,
197     openbracket:219,
198     ']':221,
199     closebracket:221,
200     backslash:220,
201     quote:222,
202     space:32
203 };
204 
205 
206 /**
207  * Image Format:JPG
208  * @constant
209  * @type Number
210  */
211 cc.FMT_JPG = 0;
212 
213 /**
214  * Image Format:PNG
215  * @constant
216  * @type Number
217  */
218 cc.FMT_PNG = 1;
219 
220 /**
221  * Image Format:TIFF
222  * @constant
223  * @type Number
224  */
225 cc.FMT_TIFF = 2;
226 
227 /**
228  * Image Format:RAWDATA
229  * @constant
230  * @type Number
231  */
232 cc.FMT_RAWDATA = 3;
233 
234 /**
235  * Image Format:WEBP
236  * @constant
237  * @type Number
238  */
239 cc.FMT_WEBP = 4;
240 
241 /**
242  * Image Format:UNKNOWN
243  * @constant
244  * @type Number
245  */
246 cc.FMT_UNKNOWN = 5;
247 
248 cc.getImageFormatByData = function (imgData) {
249 	// if it is a png file buffer.
250 	if (imgData.length > 8) {
251 		if (imgData[0] == 0x89
252 			&& imgData[1] == 0x50
253 			&& imgData[2] == 0x4E
254 			&& imgData[3] == 0x47
255 			&& imgData[4] == 0x0D
256 			&& imgData[5] == 0x0A
257 			&& imgData[6] == 0x1A
258 			&& imgData[7] == 0x0A) {
259 			return cc.FMT_PNG;
260 		}
261 	}
262 
263 	// if it is a tiff file buffer.
264 	if (imgData.length > 2) {
265 		if ((imgData[0] == 0x49 && imgData[1] == 0x49)
266 			|| (imgData[0] == 0x4d && imgData[1] == 0x4d)
267 			|| (imgData[0] == 0xff && imgData[1] == 0xd8)) {
268 			return cc.FMT_TIFF;
269 		}
270 	}
271 
272 	return cc.FMT_UNKNOWN;
273 };
274 
275 
276 /**
277  * Common getter setter configuration function
278  * @function
279  * @param {Object}   proto      A class prototype or an object to config<br/>
280  * @param {String}   prop       Property name
281  * @param {function} getter     Getter function for the property
282  * @param {function} setter     Setter function for the property
283  * @param {String}   getterName Name of getter function for the property
284  * @param {String}   setterName Name of setter function for the property
285  */
286 cc.defineGetterSetter = function (proto, prop, getter, setter, getterName, setterName)
287 {
288 	if (proto.__defineGetter__) {
289 		getter && proto.__defineGetter__(prop, getter);
290 		setter && proto.__defineSetter__(prop, setter);
291 	}
292 	else if (Object.defineProperty) {
293 		var desc = { enumerable: false, configurable: true };
294 		getter && (desc.get = getter);
295 		setter && (desc.set = setter);
296 		Object.defineProperty(proto, prop, desc);
297 	}
298 	else {
299 		throw new Error("browser does not support getters");
300 		return;
301 	}
302 
303 	if(!getterName && !setterName) {
304 		// Lookup getter/setter function
305 		var hasGetter = (getter != null), hasSetter = (setter != undefined);
306 		var props = Object.getOwnPropertyNames(proto);
307 		for (var i = 0; i < props.length; i++) {
308 			var name = props[i];
309 			if( proto.__lookupGetter__(name) || typeof proto[name] !== "function" ) continue;
310 			var func = proto[name];
311 			if (hasGetter && func === getter) {
312 				getterName = name;
313 				if(!hasSetter || setterName) break;
314 			}
315 			if (hasSetter && func === setter) {
316 				setterName = name;
317 				if(!hasGetter || getterName) break;
318 			}
319 		}
320 	}
321 
322 	// Found getter/setter
323 	var ctor = proto.constructor;
324 	if (getterName) {
325 		if (!ctor.__getters__) {
326 			ctor.__getters__ = {};
327 		}
328 		ctor.__getters__[getterName] = prop;
329 	}
330 	if (setterName) {
331 		if (!ctor.__setters__) {
332 			ctor.__setters__ = {};
333 		}
334 		ctor.__setters__[setterName] = prop;
335 	}
336 };
337 
338 /**
339  * copy an array's item to a new array (its performance is better than Array.slice)
340  * @param {Array} arr
341  * @returns {Array}
342  */
343 cc.copyArray = function(arr){
344 	var i, len = arr.length, arr_clone = new Array(len);
345 	for (i = 0; i < len; i += 1)
346 		arr_clone[i] = arr[i];
347 	return arr_clone;
348 };
349