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 //
 29 // POINT
 30 //
 31 //--------------------------------------------------------
 32 /**
 33  * @class
 34  * @param {Number} _x
 35  * @param {Number} _y
 36  * Constructor
 37  */
 38 cc.Point = function (_x, _y) {
 39     this.x = _x || 0;
 40     this.y = _y || 0;
 41 };
 42 
 43 cc._PointConst = function (x, y) {
 44     this._x = x || 0;
 45     this._y = y || 0;
 46 
 47     this.setX = function (x) {
 48         this._x = x;
 49     };
 50     this.setY = function (y) {
 51         this._y = y;
 52     }
 53 };
 54 
 55 cc._pConst = function (x, y) {
 56     return new cc._PointConst(x, y);
 57 };
 58 
 59 Object.defineProperties(cc._PointConst.prototype, {
 60     x: {
 61         get: function () {
 62             return this._x;
 63         },
 64         set: function () {
 65             console.warn("Warning of _PointConst: Modification to const or private property is forbidden");
 66         },
 67         enumerable: true
 68     },
 69 
 70     y: {
 71         get: function () {
 72             return this._y;
 73         },
 74         set: function () {
 75             console.warn("Warning of _PointConst: Modification to const or private property is forbidden");
 76         },
 77         enumerable: true
 78     }
 79 });
 80 
 81 /**
 82  * @function
 83  * @param {Number} x
 84  * @param {Number} y
 85  * @return {cc.Point}
 86  */
 87 cc.PointMake = function (x, y) {
 88     cc.log("cc.PointMake will be deprecated sooner or later. Use cc.p instead.");
 89     return new cc.Point(x, y);
 90 };
 91 
 92 /**
 93  * Helper macro that creates a cc.Point.
 94  * @param {Number} x
 95  * @param {Number} y
 96  */
 97 cc.p = function (x, y) {
 98     // This can actually make use of "hidden classes" in JITs and thus decrease
 99     // memory usage and overall performance drastically
100     //return new cc.Point(x, y);
101     // but this one will instead flood the heap with newly allocated hash maps
102     // giving little room for optimization by the JIT,
103     // note: we have tested this item on Chrome and firefox, it is faster than new cc.Point(x, y)
104     return {x: x, y: y};
105 };
106 
107 // JSB compatbility: in JSB, cc._p reuses objects instead of creating new ones
108 cc._p = cc.p;
109 
110 /**
111  * The "left bottom" point -- equivalent to cc.p(0, 0).
112  * @function
113  * @return {cc.Point}
114  */
115 cc.PointZero = function () {
116     return cc.p(0, 0);
117 };
118 
119 /**
120  * @function
121  * @param {cc.Point} point1
122  * @param {cc.Point} point2
123  * @return {Boolean}
124  */
125 cc.pointEqualToPoint = function (point1, point2) {
126     if (!point1 || !point2)
127         return false;
128     return ((point1.x === point2.x) && (point1.y === point2.y));
129 };
130 
131 // deprecated
132 //cc.Point.CCPointEqualToPoint = cc.pointEqualToPoint;
133 
134 
135 //--------------------------------------------------------
136 //
137 // SIZE
138 //
139 //--------------------------------------------------------
140 
141 /**
142  * @class
143  * @param {Number} _width
144  * @param {Number} _height
145  * Constructor
146  */
147 cc.Size = function (_width, _height) {
148     this.width = _width || 0;
149     this.height = _height || 0;
150 };
151 
152 cc._SizeConst = function (width, height) {
153     this._width = width || 0;
154     this._height = height || 0;
155 
156     this.setWidth = function (width) {
157         this._width = width;
158     };
159     this.setHeight = function (height) {
160         this._height = height;
161     }
162 };
163 
164 cc._sizeConst = function (width, height) {
165     return new cc._SizeConst(width, height);
166 };
167 
168 Object.defineProperties(cc._SizeConst.prototype, {
169     width: {
170         get: function () {
171             return this._width;
172         },
173         set: function () {
174             console.warn("Warning of _SizeConst: Modification to const or private property is forbidden");
175         },
176         enumerable: true
177     },
178 
179     height: {
180         get: function () {
181             return this._height;
182         },
183         set: function () {
184             console.warn("Warning of _SizeConst: Modification to const or private property is forbidden");
185         },
186         enumerable: true
187     }
188 });
189 
190 /**
191  * @function
192  * @param {Number} width
193  * @param {Number} height
194  * @return {cc.Size}
195  */
196 cc.SizeMake = function (width, height) {
197     cc.log("cc.SizeMake will be deprecated sooner or later. Use cc.size instead.");
198     return cc.size(width, height);
199 };
200 
201 /**
202  * @function
203  * @param {Number} w width
204  * @param {Number} h height
205  * @return {cc.Size}
206  */
207 cc.size = function (w, h) {
208     // This can actually make use of "hidden classes" in JITs and thus decrease
209     // memory usage and overall peformance drastically
210     //return new cc.Size(w, h);
211     // but this one will instead flood the heap with newly allocated hash maps
212     // giving little room for optimization by the JIT
213     // note: we have tested this item on Chrome and firefox, it is faster than new cc.Size(w, h)
214     return { width: w, height: h};
215 };
216 
217 // JSB compatbility: in JSB, cc._size reuses objects instead of creating new ones
218 cc._size = cc.size;
219 
220 /**
221  * The "zero" size -- equivalent to cc.size(0, 0).
222  * @function
223  * @return {cc.Size}
224  */
225 cc.SizeZero = function () {
226     return cc.size(0, 0);
227 };
228 
229 cc._zeroConsts = {pointZero: cc._pConst(0,0), sizeZero: cc._sizeConst(0,0)};
230 
231 Object.defineProperties(cc, {
232     POINT_ZERO:{
233         get:function () {
234             return cc._zeroConsts.pointZero;
235         }
236     },
237     SIZE_ZERO:{
238         get:function () {
239             return cc._zeroConsts.sizeZero;
240         }
241     },
242     RECT_ZERO:{
243         get:function () {
244             return cc.rect(0, 0, 0, 0);
245         }
246     }
247 });
248 
249 
250 /**
251  * @function
252  * @param {cc.Size} size1
253  * @param {cc.Size} size2
254  * @return {Boolean}
255  */
256 cc.sizeEqualToSize = function (size1, size2) {
257     if (!size1 || !size2)
258         return false;
259     return ((size1.width == size2.width) && (size1.height == size2.height));
260 };
261 
262 // deprecated
263 //cc.Size.CCSizeEqualToSize = cc.sizeEqualToSize;
264 
265 //--------------------------------------------------------
266 //
267 // RECT
268 //
269 //--------------------------------------------------------
270 
271 /**
272  * @class
273  * @param {Number|cc.Point|cc.Rect} [x1] a Number value as x or a cc.Point object as origin or a cc.Rect clone object
274  * @param {Number|cc.Size} [y1] x1 a Number value as y or a cc.Size object as size
275  * @param {Number} [width1]
276  * @param {Number} [height1]
277  * Constructor
278  */
279 cc.Rect = function (x1, y1, width1, height1) {
280     var argLen =arguments.length;
281     if(argLen === 4){
282         this._origin = new cc.Point(x1 || 0, y1 || 0);
283         this._size = new cc.Size(width1 || 0, height1 || 0);
284         return;
285     }
286     if(argLen === 1) {
287         this._origin = new cc.Point(x1._origin.x, x1._origin.y);
288         this._size = new cc.Size(x1._size.width, x1._size.height);
289         return;
290     }
291     if(argLen === 0) {
292         this._origin = new cc.Point(0, 0);
293         this._size = new cc.Size(0,0);
294         return;
295     }
296     if(argLen === 2) {
297         this._origin = new cc.Point(x1.x, x1.y);
298         this._size = new cc.Size(y1.width,y1.height);
299         return;
300     }
301     throw "unknown argument type";
302 };
303 
304 /**
305  * @function
306  * @param {Number} x
307  * @param {Number} y
308  * @param {Number} width
309  * @param {Number} height
310  * @return {cc.Rect}
311  */
312 cc.RectMake = function (x, y, width, height) {
313     cc.log("cc.RectMake will be deprecated sooner or later. Use cc.rect instead.");
314     return cc.rect(x, y, width, height);
315 };
316 
317 // backward compatible
318 cc.rect = function (x, y, w, h) {
319     var argLen =arguments.length;
320     if(argLen === 0)
321         return new cc.Rect(0,0,0,0);
322 
323     if(argLen === 1)
324         return new cc.Rect(x.x, x.y, x.width, x.height);
325 
326     if(argLen === 2)
327         return new cc.Rect(x.x, x.y, y.width, y.height);
328 
329     if(argLen === 4)
330         return new cc.Rect(x,y,w,h);
331 
332     throw "unknown argument type";
333 };
334 
335 // JSB compatbility: in JSB, cc._rect reuses objects instead of creating new ones
336 cc._rect = cc.rect;
337 
338 /**
339  * The "zero" rectangle -- equivalent to cc.rect(0, 0, 0, 0).
340  * @function
341  * @return {cc.Rect}
342  */
343 cc.RectZero = function () {
344     return cc.rect(0, 0, 0, 0);
345 };
346 
347 /**
348  * @function
349  * @param {cc.Rect} rect1
350  * @param {cc.Rect} rect2
351  * @return {Boolean}
352  */
353 cc.rectEqualToRect = function (rect1, rect2) {
354     if(!rect1 || !rect2)
355         return false;
356     return ((cc.pointEqualToPoint(rect1._origin, rect2._origin)) &&
357         (cc.sizeEqualToSize(rect1._size, rect2._size)));
358 };
359 
360 cc._rectEqualToZero = function(rect){
361     if(!rect)
362         return false;
363     return (rect.x === 0) && (rect.y === 0) && (rect.width === 0) && (rect.height === 0);
364 };
365 
366 /**
367  * @function
368  * @param {cc.Rect} rect1
369  * @param {cc.Rect} rect2
370  * @return {Boolean}
371  */
372 cc.rectContainsRect = function (rect1, rect2) {
373     if (!rect1 || !rect2)
374         return false;
375 
376     return !((rect1.x >= rect2.x) || (rect1.y >= rect2.y) ||
377         ( rect1.x + rect1.width <= rect2.x + rect2.width) ||
378         ( rect1.y + rect1.height <= rect2.y + rect2.height));
379 };
380 
381 /**
382  * return the rightmost x-value of 'rect'
383  * @function
384  * @param {cc.Rect} rect
385  * @return {Number}
386  */
387 cc.rectGetMaxX = function (rect) {
388     return (rect.x + rect.width);
389 };
390 
391 /**
392  * return the midpoint x-value of 'rect'
393  * @function
394  * @param {cc.Rect} rect
395  * @return {Number}
396  */
397 cc.rectGetMidX = function (rect) {
398     return (rect.x + rect.width / 2.0);
399 };
400 /**
401  * return the leftmost x-value of 'rect'
402  * @function
403  * @param {cc.Rect} rect
404  * @return {Number}
405  */
406 cc.rectGetMinX = function (rect) {
407     return rect.x;
408 };
409 
410 /**
411  * Return the topmost y-value of `rect'
412  * @function
413  * @param {cc.Rect} rect
414  * @return {Number}
415  */
416 cc.rectGetMaxY = function (rect) {
417     return(rect.y + rect.height);
418 };
419 
420 /**
421  * Return the midpoint y-value of `rect'
422  * @function
423  * @param {cc.Rect} rect
424  * @return {Number}
425  */
426 cc.rectGetMidY = function (rect) {
427     return rect.y + rect.height / 2.0;
428 };
429 
430 /**
431  * Return the bottommost y-value of `rect'
432  * @function
433  * @param {cc.Rect} rect
434  * @return {Number}
435  */
436 cc.rectGetMinY = function (rect) {
437     return rect.y;
438 };
439 
440 /**
441  * @function
442  * @param {cc.Rect} rect
443  * @param {cc.Point} point
444  * @return {Boolean}
445  */
446 cc.rectContainsPoint = function (rect, point) {
447     return (point.x >= cc.rectGetMinX(rect) && point.x <= cc.rectGetMaxX(rect) &&
448         point.y >= cc.rectGetMinY(rect) && point.y <= cc.rectGetMaxY(rect)) ;
449 };
450 
451 /**
452  * @function
453  * @param {cc.Rect} rectA
454  * @param {cc.Rect} rectB
455  * @return {Boolean}
456  */
457 cc.rectIntersectsRect = function (rectA, rectB) {
458     return !(cc.rectGetMaxX(rectA) < cc.rectGetMinX(rectB) ||
459         cc.rectGetMaxX(rectB) < cc.rectGetMinX(rectA) ||
460         cc.rectGetMaxY(rectA) < cc.rectGetMinY(rectB) ||
461         cc.rectGetMaxY(rectB) < cc.rectGetMinY(rectA));
462 };
463 
464 /**
465  * @function
466  * @param {cc.Rect} rectA
467  * @param {cc.Rect} rectB
468  * @return {Boolean}
469  */
470 cc.rectOverlapsRect = function (rectA, rectB) {
471     return !((rectA.x + rectA.width < rectB.x) ||
472         (rectB.x + rectB.width < rectA.x) ||
473         (rectA.y + rectA.height < rectB.y) ||
474         (rectB.y + rectB.height < rectA.y));
475 };
476 
477 /**
478  * Returns the smallest rectangle that contains the two source rectangles.
479  * @function
480  * @param {cc.Rect} rectA
481  * @param {cc.Rect} rectB
482  * @return {cc.Rect}
483  */
484 cc.rectUnion = function (rectA, rectB) {
485     var rect = cc.rect(0, 0, 0, 0);
486     rect.x = Math.min(rectA.x, rectB.x);
487     rect.y = Math.min(rectA.y, rectB.y);
488     rect.width = Math.max(rectA.x + rectA.width, rectB.x + rectB.width) - rect.x;
489     rect.height = Math.max(rectA.y + rectA.height, rectB.y + rectB.height) - rect.y;
490     return rect;
491 };
492 
493 /**
494  * Returns the overlapping portion of 2 rectangles
495  * @function
496  * @param {cc.Rect} rectA
497  * @param {cc.Rect} rectB
498  * @return {cc.Rect}
499  */
500 cc.rectIntersection = function (rectA, rectB) {
501     var intersection = cc.rect(
502         Math.max(cc.rectGetMinX(rectA), cc.rectGetMinX(rectB)),
503         Math.max(cc.rectGetMinY(rectA), cc.rectGetMinY(rectB)),
504         0, 0);
505 
506     intersection.width = Math.min(cc.rectGetMaxX(rectA), cc.rectGetMaxX(rectB)) - cc.rectGetMinX(intersection);
507     intersection.height = Math.min(cc.rectGetMaxY(rectA), cc.rectGetMaxY(rectB)) - cc.rectGetMinY(intersection);
508     return intersection;
509 };
510 
511 //
512 // Rect JSB compatibility
513 // JSB uses:
514 //   rect.x, rect.y, rect.width and rect.height
515 // while HTML5 uses:
516 //   rect.origin, rect.size
517 //
518 cc.Rect.prototype.getX = function() {
519     return this._origin.x;
520 };
521 cc.Rect.prototype.setX = function(x) {
522     this._origin.x = x;
523 };
524 cc.Rect.prototype.getY = function() {
525     return this._origin.y;
526 };
527 cc.Rect.prototype.setY = function(y) {
528     this._origin.y = y;
529 };
530 cc.Rect.prototype.getWidth = function(){
531     return this._size.width;
532 };
533 cc.Rect.prototype.setWidth = function(w){
534     this._size.width = w;
535 };
536 cc.Rect.prototype.getHeight = function(){
537     return this._size.height;
538 };
539 cc.Rect.prototype.setHeight = function(h){
540     this._size.height = h;
541 };
542 
543 Object.defineProperties(cc.Rect.prototype,
544     {
545         "x": {
546             get: function () {
547                 return this.getX();
548             },
549             set: function (newValue) {
550                 this.setX(newValue);
551             },
552             enumerable: true,
553             configurable: true
554         },
555         "y": {
556             get: function () {
557                 return this.getY();
558             },
559             set: function (newValue) {
560                 this.setY(newValue);
561             },
562             enumerable: true,
563             configurable: true
564         },
565         "width": {
566             get: function () {
567                 return this.getWidth();
568             },
569             set: function (newValue) {
570                 this.setWidth(newValue);
571             },
572             enumerable: true,
573             configurable: true
574         },
575         "height": {
576             get: function () {
577                 return this.getHeight();
578             },
579             set: function (newValue) {
580                 this.setHeight(newValue);
581             },
582             enumerable: true,
583             configurable: true
584         }
585     }
586 );
587 
588 // Deprecated
589 /*cc.Rect.CCRectEqualToRect = cc.rectEqualToRect;
590 cc.Rect.CCRectContainsRect = cc.rectContainsRect;
591 cc.Rect.CCRectGetMaxX = cc.rectGetMaxX;
592 cc.Rect.CCRectGetMidX = cc.rectGetMidX;
593 cc.Rect.CCRectGetMinX = cc.rectGetMinX;
594 cc.Rect.CCRectGetMaxY = cc.rectGetMaxY;
595 cc.Rect.CCRectGetMidY = cc.rectGetMidY;
596 cc.Rect.CCRectGetMinY = cc.rectGetMinY;
597 cc.Rect.CCRectContainsPoint = cc.rectContainsPoint;
598 cc.Rect.CCRectIntersectsRect = cc.rectIntersectsRect;
599 cc.Rect.CCRectUnion = cc.rectUnion;
600 cc.Rect.CCRectIntersection = cc.rectIntersection;*/
601 
602