/**
* This module has now been replaced by `Matter.Detector`.
*
* All usage should be migrated to `Matter.Detector` or another alternative.
* For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
*
* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
*
* @class Grid
* @deprecated
*/
var Grid = {};
module.exports = Grid;
var Pair = require('./Pair');
var Common = require('../core/Common');
var deprecated = Common.deprecated;
(function() {
/**
* Creates a new grid.
* @deprecated replaced by Matter.Detector
* @method create
* @param {} options
* @return {grid} A new grid
*/
Grid.create = function(options) {
var defaults = {
buckets: {},
pairs: {},
pairsList: [],
bucketWidth: 48,
bucketHeight: 48
};
return Common.extend(defaults, options);
};
/**
* The width of a single grid bucket.
*
* @property bucketWidth
* @type number
* @default 48
*/
/**
* The height of a single grid bucket.
*
* @property bucketHeight
* @type number
* @default 48
*/
/**
* Updates the grid.
* @deprecated replaced by Matter.Detector
* @method update
* @param {grid} grid
* @param {body[]} bodies
* @param {engine} engine
* @param {boolean} forceUpdate
*/
Grid.update = function(grid, bodies, engine, forceUpdate) {
var i, col, row,
world = engine.world,
buckets = grid.buckets,
bucket,
bucketId,
gridChanged = false;
for (i = 0; i < bodies.length; i++) {
var body = bodies[i];
if (body.isSleeping && !forceUpdate)
continue;
// temporary back compatibility bounds check
if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x
|| body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y))
continue;
var newRegion = Grid._getRegion(grid, body);
// if the body has changed grid region
if (!body.region || newRegion.id !== body.region.id || forceUpdate) {
if (!body.region || forceUpdate)
body.region = newRegion;
var union = Grid._regionUnion(newRegion, body.region);
// update grid buckets affected by region change
// iterate over the union of both regions
for (col = union.startCol; col <= union.endCol; col++) {
for (row = union.startRow; row <= union.endRow; row++) {
bucketId = Grid._getBucketId(col, row);
bucket = buckets[bucketId];
var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol
&& row >= newRegion.startRow && row <= newRegion.endRow);
var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol
&& row >= body.region.startRow && row <= body.region.endRow);
// remove from old region buckets
if (!isInsideNewRegion && isInsideOldRegion) {
if (isInsideOldRegion) {
if (bucket)
Grid._bucketRemoveBody(grid, bucket, body);
}
}
// add to new region buckets
if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) {
if (!bucket)
bucket = Grid._createBucket(buckets, bucketId);
Grid._bucketAddBody(grid, bucket, body);
}
}
}
// set the new region
body.region = newRegion;
// flag changes so we can update pairs
gridChanged = true;
}
}
// update pairs list only if pairs changed (i.e. a body changed region)
if (gridChanged)
grid.pairsList = Grid._createActivePairsList(grid);
};
deprecated(Grid, 'update', 'Grid.update ➤ replaced by Matter.Detector');
/**
* Clears the grid.
* @deprecated replaced by Matter.Detector
* @method clear
* @param {grid} grid
*/
Grid.clear = function(grid) {
grid.buckets = {};
grid.pairs = {};
grid.pairsList = [];
};
deprecated(Grid, 'clear', 'Grid.clear ➤ replaced by Matter.Detector');
/**
* Finds the union of two regions.
* @method _regionUnion
* @deprecated replaced by Matter.Detector
* @private
* @param {} regionA
* @param {} regionB
* @return {} region
*/
Grid._regionUnion = function(regionA, regionB) {
var startCol = Math.min(regionA.startCol, regionB.startCol),
endCol = Math.max(regionA.endCol, regionB.endCol),
startRow = Math.min(regionA.startRow, regionB.startRow),
endRow = Math.max(regionA.endRow, regionB.endRow);
return Grid._createRegion(startCol, endCol, startRow, endRow);
};
/**
* Gets the region a given body falls in for a given grid.
* @method _getRegion
* @deprecated replaced by Matter.Detector
* @private
* @param {} grid
* @param {} body
* @return {} region
*/
Grid._getRegion = function(grid, body) {
var bounds = body.bounds,
startCol = Math.floor(bounds.min.x / grid.bucketWidth),
endCol = Math.floor(bounds.max.x / grid.bucketWidth),
startRow = Math.floor(bounds.min.y / grid.bucketHeight),
endRow = Math.floor(bounds.max.y / grid.bucketHeight);
return Grid._createRegion(startCol, endCol, startRow, endRow);
};
/**
* Creates a region.
* @method _createRegion
* @deprecated replaced by Matter.Detector
* @private
* @param {} startCol
* @param {} endCol
* @param {} startRow
* @param {} endRow
* @return {} region
*/
Grid._createRegion = function(startCol, endCol, startRow, endRow) {
return {
id: startCol + ',' + endCol + ',' + startRow + ',' + endRow,
startCol: startCol,
endCol: endCol,
startRow: startRow,
endRow: endRow
};
};
/**
* Gets the bucket id at the given position.
* @method _getBucketId
* @deprecated replaced by Matter.Detector
* @private
* @param {} column
* @param {} row
* @return {string} bucket id
*/
Grid._getBucketId = function(column, row) {
return 'C' + column + 'R' + row;
};
/**
* Creates a bucket.
* @method _createBucket
* @deprecated replaced by Matter.Detector
* @private
* @param {} buckets
* @param {} bucketId
* @return {} bucket
*/
Grid._createBucket = function(buckets, bucketId) {
var bucket = buckets[bucketId] = [];
return bucket;
};
/**
* Adds a body to a bucket.
* @method _bucketAddBody
* @deprecated replaced by Matter.Detector
* @private
* @param {} grid
* @param {} bucket
* @param {} body
*/
Grid._bucketAddBody = function(grid, bucket, body) {
var gridPairs = grid.pairs,
pairId = Pair.id,
bucketLength = bucket.length,
i;
// add new pairs
for (i = 0; i < bucketLength; i++) {
var bodyB = bucket[i];
if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic))
continue;
// keep track of the number of buckets the pair exists in
// important for Grid.update to work
var id = pairId(body, bodyB),
pair = gridPairs[id];
if (pair) {
pair[2] += 1;
} else {
gridPairs[id] = [body, bodyB, 1];
}
}
// add to bodies (after pairs, otherwise pairs with self)
bucket.push(body);
};
/**
* Removes a body from a bucket.
* @method _bucketRemoveBody
* @deprecated replaced by Matter.Detector
* @private
* @param {} grid
* @param {} bucket
* @param {} body
*/
Grid._bucketRemoveBody = function(grid, bucket, body) {
var gridPairs = grid.pairs,
pairId = Pair.id,
i;
// remove from bucket
bucket.splice(Common.indexOf(bucket, body), 1);
var bucketLength = bucket.length;
// update pair counts
for (i = 0; i < bucketLength; i++) {
// keep track of the number of buckets the pair exists in
// important for _createActivePairsList to work
var pair = gridPairs[pairId(body, bucket[i])];
if (pair)
pair[2] -= 1;
}
};
/**
* Generates a list of the active pairs in the grid.
* @method _createActivePairsList
* @deprecated replaced by Matter.Detector
* @private
* @param {} grid
* @return [] pairs
*/
Grid._createActivePairsList = function(grid) {
var pair,
gridPairs = grid.pairs,
pairKeys = Common.keys(gridPairs),
pairKeysLength = pairKeys.length,
pairs = [],
k;
// iterate over grid.pairs
for (k = 0; k < pairKeysLength; k++) {
pair = gridPairs[pairKeys[k]];
// if pair exists in at least one bucket
// it is a pair that needs further collision testing so push it
if (pair[2] > 0) {
pairs.push(pair);
} else {
delete gridPairs[pairKeys[k]];
}
}
return pairs;
};
})();