1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  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  * @ignore
 27  */
 28 ccs.PT_RATIO = 32;
 29 /**
 30  * Base class for ccs.ColliderFilter
 31  * @class
 32  * @extends ccs.Class
 33  */
 34 ccs.ColliderFilter = ccs.Class.extend(/** @lends ccs.ColliderFilter# */{
 35     _collisionType: 0,
 36     _group: 0,
 37     ctor: function (collisionType, group) {
 38         this._collisionType = collisionType || 0;
 39         this._group = group || 0;
 40     },
 41     updateShape: function (shape) {
 42         shape.collision_type = this._collisionType;
 43         shape.group = this._group;
 44     }
 45 });
 46 /**
 47  * Base class for ccs.ColliderBody
 48  * @class
 49  * @extends ccs.Class
 50  *
 51  * @property {ccs.ContourData}      contourData     - The contour data of collider body
 52  * @property {ccs.Shape}            shape           - The shape of collider body
 53  * @property {ccs.ColliderFilter}   colliderFilter  - The collider filter of collider body
 54  *
 55  */
 56 ccs.ColliderBody = ccs.Class.extend(/** @lends ccs.ColliderBody# */{
 57     shape: null,
 58     coutourData: null,
 59     colliderFilter:null,
 60     _calculatedVertexList:null,
 61     ctor: function (contourData) {
 62         this.shape = null;
 63         this.coutourData = contourData;
 64         this.colliderFilter = new ccs.ColliderFilter();
 65         if(ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX){
 66             this._calculatedVertexList = [];
 67         }
 68     },
 69 
 70     /**
 71      * contourData getter
 72      * @returns {ccs.ContourData}
 73      */
 74     getContourData: function () {
 75         return this.coutourData;
 76     },
 77 
 78     /**
 79      * contourData setter
 80      * @param {ccs.ContourData} contourData
 81      */
 82     setContourData: function (contourData) {
 83         this.coutourData = contourData;
 84     },
 85 
 86     /**
 87      * shape setter
 88      * @return {ccs.Shape}
 89      */
 90     getShape: function () {
 91         return this.shape;
 92     },
 93 
 94     /**
 95      * shape getter
 96      * @param {ccs.Shape} shape
 97      */
 98     setShape: function (shape) {
 99         this.shape = shape;
100     },
101 
102     /**
103      * colliderFilter getter
104      * @returns {ccs.ColliderFilter}
105      */
106     getColliderFilter: function () {
107         return this.colliderFilter;
108     },
109 
110     /**
111      * colliderFilter setter
112      * @param {ccs.ColliderFilter} colliderFilter
113      */
114     setColliderFilter: function (colliderFilter) {
115         this.colliderFilter = colliderFilter;
116     },
117 
118     /**
119      * get calculated vertex list
120      * @returns {Array}
121      */
122     getCalculatedVertexList:function(){
123         return this._calculatedVertexList;
124     }
125 });
126 
127 /**
128  * Base class for ccs.ColliderDetector
129  * @class
130  * @extends ccs.Class
131  *
132  * @property {ccs.ColliderFilter}   colliderFilter  - The collider filter of the collider detector
133  * @property {Boolean}              active          - Indicate whether the collider detector is active
134  * @property {Object}               body            - The collider body
135  */
136 ccs.ColliderDetector = ccs.Class.extend(/** @lends ccs.ColliderDetector# */{
137     _colliderBodyList: null,
138     _bone: null,
139     _body: null,
140     _active: false,
141     _filter: null,
142     ctor: function () {
143         this._colliderBodyList = [];
144         this._bone = null;
145         this._body = null;
146         this._active = false;
147         this._filter = null;
148     },
149     init: function (bone) {
150         this._colliderBodyList = [];
151         if (bone)
152             this._bone = bone;
153         this._filter = new ccs.ColliderFilter();
154         return true;
155     },
156 
157     /**
158      *  add contourData
159      * @param {ccs.ContourData} contourData
160      */
161     addContourData: function (contourData) {
162         var colliderBody = new ccs.ColliderBody(contourData);
163         this._colliderBodyList.push(colliderBody);
164         if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
165             var calculatedVertexList = colliderBody.getCalculatedVertexList();
166             var vertexList = contourData.vertexList;
167             for (var i = 0; i < vertexList.length; i++) {
168                 var newVertex = new ccs.ContourVertex2(0, 0);
169                 calculatedVertexList.push(newVertex);
170             }
171         }
172     },
173 
174     /**
175      * add contourData
176      * @param {Array} contourDataList
177      */
178     addContourDataList: function (contourDataList) {
179         for (var i = 0; i < contourDataList.length; i++) {
180             this.addContourData(contourDataList[i]);
181         }
182     },
183 
184     /**
185      * remove contourData
186      * @param contourData
187      */
188     removeContourData: function (contourData) {
189         var locColliderBodyList = this._colliderBodyList;
190         for (var i = 0; i < locColliderBodyList.length; i++) {
191             if(locColliderBodyList[i].getContourData()==contourData){
192                 locColliderBodyList.splice(i, 1);
193                 return;
194             }
195         }
196     },
197 
198     /**
199      * remove all body
200      */
201     removeAll: function () {
202         this._colliderBodyList = [];
203     },
204 
205     /**
206      * set colliderFilter
207      * @param {ccs.ColliderFilter} filter
208      */
209     setColliderFilter: function (filter) {
210         this._filter = filter;
211         for (var i = 0; i < this._colliderBodyList.length; i++) {
212             var colliderBody = this._colliderBodyList[i];
213             colliderBody.setColliderFilter(filter);
214             if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
215                 if (colliderBody.getShape()) {
216                     colliderBody.getColliderFilter().updateShape(colliderBody.getShape());
217                 }
218             }
219         }
220     },
221 
222     /**
223      * get colliderFilter
224      * @returns {ccs.ColliderFilter}
225      */
226     getColliderFilter:function(){
227         return this._filter;
228     },
229 
230     setActive: function (active) {
231         if (this._active == active)
232             return;
233         this._active = active;
234         var locBody = this._body;
235         var locShape;
236         if (locBody) {
237             var colliderBody = null;
238             if (this._active) {
239                 for (var i = 0; i < this._colliderBodyList.length; i++) {
240                     colliderBody = this._colliderBodyList[i];
241                     locShape = colliderBody.getShape();
242                     locBody.space.addShape(locShape);
243                 }
244             }
245             else {
246                 for (var i = 0; i < this._colliderBodyList.length; i++) {
247                     colliderBody = this._colliderBodyList[i];
248                     locShape = colliderBody.getShape();
249                     locBody.space.removeShape(locShape);
250                 }
251             }
252         }
253     },
254     getActive: function () {
255         return this._active;
256     },
257     getColliderBodyList: function () {
258         return this._colliderBodyList;
259     },
260     helpPoint: cc.p(0, 0),
261     updateTransform: function (t) {
262         if (!this._active)
263             return;
264 
265         var colliderBody = null;
266         var locBody = this._body;
267         var locHelpPoint = this.helpPoint;
268         for (var i = 0; i < this._colliderBodyList.length; i++) {
269             colliderBody = this._colliderBodyList[i];
270             var contourData = colliderBody.getContourData();
271             var shape = null;
272             if (locBody) {
273                 shape = colliderBody.getShape();
274             }
275             var vs = contourData.vertexList;
276             var cvs = colliderBody.getCalculatedVertexList();
277             for (var j = 0; j < vs.length; j++) {
278                 locHelpPoint.x = vs[j].x;
279                 locHelpPoint.y = vs[j].y;
280                 locHelpPoint = cc.PointApplyAffineTransform(locHelpPoint, t);
281                 if (shape) {
282                     shape.verts[j * 2] = locHelpPoint.x;
283                     shape.verts[j * 2 + 1] = locHelpPoint.y;
284                 }
285                 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
286                     var v =  cc.p(0, 0);
287                     v.x = locHelpPoint.x;
288                     v.y = locHelpPoint.y;
289                     cvs[j] = v;
290                 }
291             }
292             if (shape) {
293                 for (var j = 0; j < vs.length; j++)            {
294                     var b = shape.verts[(j + 1) % shape.verts.length];
295                     var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[j])));
296                     shape.axes[j].n = n;
297                     shape.axes[j].d = cp.v.dot(n, shape.verts[j]);
298                 }
299             }
300         }
301     },
302     getBody: function () {
303         return this._body;
304     },
305     setBody: function (body) {
306         this._body = body;
307         var colliderBody;
308         for (var i = 0; i < this._colliderBodyList.length; i++) {
309             colliderBody = this._colliderBodyList[i];
310             var contourData = colliderBody.getContourData();
311             var verts = [];
312             var vs = contourData.vertexList;
313             for (var i = 0; i < vs.length; i++) {
314                 var v = vs[i];
315                 verts.push(v.x);
316                 verts.push(v.y);
317             }
318             var shape = new cp.PolyShape(this._body, verts, cp.vzero);
319             shape.sensor = true;
320             shape.data = this._bone;
321             if (this._active){
322                 this._body.space.addShape(shape);
323             }
324             colliderBody.setShape(shape);
325             colliderBody.getColliderFilter().updateShape(shape);
326         }
327     }
328 });
329 
330 window._p = ccs.ColliderDetector.prototype;
331 
332 // Extended properties
333 /** @expose */
334 _p.colliderFilter;
335 cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
336 /** @expose */
337 _p.active;
338 cc.defineGetterSetter(_p, "active", _p.getActive, _p.setActive);
339 /** @expose */
340 _p.body;
341 cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
342 
343 delete window._p;
344 
345 ccs.ColliderDetector.create = function (bone) {
346     var colliderDetector = new ccs.ColliderDetector();
347     if (colliderDetector && colliderDetector.init(bone)) {
348         return colliderDetector;
349     }
350     return null;
351 };