/** Internal function to update an area of the graph.
* \todo Messy code, clean it up. */
public void UpdateArea(GraphUpdateObject o)
{
if (nodes == null) {
Debug.LogWarning ("The Grid Graph is not scanned, cannot update area ");
//Not scanned
return;
}
//Copy the bounds
Bounds b = o.bounds;
//Matrix inverse
//node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));
Vector3 min, max;
GetBoundsMinMax (b,inverseMatrix,out min, out max);
int minX = Mathf.RoundToInt (min.x-0.5F);
int maxX = Mathf.RoundToInt (max.x-0.5F);
int minZ = Mathf.RoundToInt (min.z-0.5F);
int maxZ = Mathf.RoundToInt (max.z-0.5F);
//We now have coordinates in local space (i.e 1 unit = 1 node)
int ominx = minX;
int omaxx = maxX;
int ominz = minZ;
int omaxz = maxZ;
if (o.updatePhysics && !o.modifyWalkability) {
//Add the collision.diameter margin for physics calls
if (collision.collisionCheck) {
Vector3 margin = new Vector3 (collision.diameter,0,collision.diameter)*0.5F;
min -= margin*1.02F;//0.02 safety margin, physics is rarely very accurate
max += margin*1.02F;
#if DEBUG
Debug.DrawLine (matrix.MultiplyPoint3x4(min),matrix.MultiplyPoint3x4(max),Color.cyan);
#endif
minX = Mathf.RoundToInt (min.x-0.5F);
maxX = Mathf.RoundToInt (max.x-0.5F);
minZ = Mathf.RoundToInt (min.z-0.5F);
maxZ = Mathf.RoundToInt (max.z-0.5F);
}
collision.Initialize (matrix,nodeSize);
for (int x = minX;x <= maxX;x++) {
for (int z = minZ;z <= maxZ;z++) {
if (x < 0 || z < 0) {
continue;
}
if (z >= depth || x >= width) {
break;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
//Register that this node will eventually have some settings changed
o.WillUpdateNode (node);
UpdateNodePositionCollision (node,x,z);
}
}
}
//This is the area inside the bounding box, call Apply on it
for (int x = ominx;x <= omaxx;x++) {
for (int z = ominz;z <= omaxz;z++) {
if (x < 0 || z < 0) {
continue;
}
if (z >= depth || x >= width) {
break;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
if (!o.updatePhysics || o.modifyWalkability) {
//Register that this node will eventually have some settings changed
//If the above IF evaluates to false, the node will already have been added before in the function
o.WillUpdateNode (node);
}
node.walkable = node.WalkableErosion;
o.Apply (node);
node.WalkableErosion = node.walkable;
}
}
//Recalculate connections
if ((o.updatePhysics || o.modifyWalkability) && erodeIterations == 0) {
//Add some margin
minX--;
maxX++;
minZ--;
maxZ++;
for (int x = minX;x <= maxX;x++) {
for (int z = minZ;z <= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) {
continue;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
CalculateConnections (graphNodes,x,z,node);
}
}
//Remove margin
minX++;
maxX--;
minZ++;
maxZ--;
}
if ((o.updatePhysics || o.modifyWalkability) && erodeIterations > 0) {
minX -= erodeIterations;
maxX += erodeIterations;
minZ -= erodeIterations;
maxZ += erodeIterations;
for (int x = minX;x <= maxX;x++) {
for (int z = minZ;z <= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) {
continue;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
node.walkable = node.WalkableErosion;
}
}
//Add some margin
minX--;
maxX++;
minZ--;
maxZ++;
//Loop through all nodes at the edge of the current bounds and swap their walkable and WalkableErosion flags
for (int x=minX, z=minZ;x<= maxX;x++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
//Debug.DrawRay (node.position,Vector3.up,Color.red);
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int x=minX, z=maxZ;x<= maxX;x++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
//Debug.DrawRay (node.position,Vector3.up,Color.red);
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int z=minZ, x=minX;z<= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
//Debug.DrawRay (node.position,Vector3.up,Color.red);
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int z=minZ, x=maxX;z<= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
//Debug.DrawRay (node.position,Vector3.up,Color.red);
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
//Remove margin
minX++;
maxX--;
minZ++;
maxZ--;
//Calculate connections for all nodes
for (int x = minX;x <= maxX;x++) {
for (int z = minZ;z <= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) {
continue;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
CalculateConnections (graphNodes,x,z,node);
}
}
//Erode function uses < not <=
maxX++;
maxZ++;
/*for (int x = minX;x < maxX;x++) {
for (int z = minZ;z < maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) {
continue;
}
int index = z*width+x;
GridNode node = graphNodes[index];
//Debug.DrawRay (node.position,Vector3.up*0.5F,Color.green);
}
}*/
//Erode area
ErodeWalkableArea (minX,minZ,maxX,maxZ);
maxX--;
maxZ--;
//Add some margin
minX--;
maxX++;
minZ--;
maxZ++;
for (int x=minX, z=minZ;x<= maxX;x++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int x=minX, z=maxZ;x<= maxX;x++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int z=minZ, x=minX;z<= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int z=minZ, x=maxX;z<= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) continue;
GridNode node = nodes[z*width+x] as GridNode;
bool tmp = node.walkable;
node.walkable = node.WalkableErosion;
node.WalkableErosion = tmp;
}
for (int x = minX;x <= maxX;x++) {
for (int z = minZ;z <= maxZ;z++) {
if (x < 0 || z < 0 || x >= width || z >= depth) {
continue;
}
int index = z*width+x;
GridNode node = nodes[index] as GridNode;
CalculateConnections (graphNodes,x,z,node);
}
}
//Remove margin
minX++;
maxX--;
minZ++;
maxZ--;
}
}