Pathfinding.GridGraph.UpdateArea C# (CSharp) Method

UpdateArea() public method

public UpdateArea ( GraphUpdateObject o ) : void
o GraphUpdateObject
return void
        public void UpdateArea(GraphUpdateObject o)
        {
            if (nodes == null || nodes.Length != width*depth) {
                Debug.LogWarning ("The Grid Graph is not scanned, cannot update area ");
                //Not scanned
                return;
            }

            //Copy the bounds
            Bounds b = o.bounds;

            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)

            IntRect originalRect = new IntRect(minX,minZ,maxX,maxZ);
            IntRect affectRect = originalRect;

            IntRect gridRect = new IntRect(0,0,width-1,depth-1);

            IntRect physicsRect = originalRect;

            int erosion = o.updateErosion ? erodeIterations : 0;

            bool willChangeWalkability = o.updatePhysics || o.modifyWalkability;

            //Calculate the largest bounding box which might be affected

            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;

                    physicsRect = new IntRect(
                                                Mathf.RoundToInt (min.x-0.5F),
                                                Mathf.RoundToInt (min.z-0.5F),
                                                Mathf.RoundToInt (max.x-0.5F),
                                                Mathf.RoundToInt (max.z-0.5F)
                                                );

                    affectRect = IntRect.Union (physicsRect, affectRect);
                }
            }

            if (willChangeWalkability || erosion > 0) {
                //Add affect radius for erosion. +1 for updating connectivity info at the border
                affectRect = affectRect.Expand (erosion +1);
            }

            IntRect clampedRect = IntRect.Intersection (affectRect,gridRect);

            //Mark nodes that might be changed
            for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) {
                for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) {
                    o.WillUpdateNode (nodes[z*width+x]);
                }
            }

            //Update Physics
            if (o.updatePhysics && !o.modifyWalkability) {

                collision.Initialize (matrix,nodeSize);

                clampedRect = IntRect.Intersection (physicsRect,gridRect);

                for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) {
                    for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) {

                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;

                        UpdateNodePositionCollision (node,x,z);
                    }
                }
            }

            //Apply GUO

            clampedRect = IntRect.Intersection (originalRect, gridRect);
            for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) {
                for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) {
                    int index = z*width+x;

                    GridNode node = nodes[index] as GridNode;

                    if (willChangeWalkability) {
                        node.walkable = node.WalkableErosion;
                        o.Apply (node);
                        node.WalkableErosion = node.walkable;
                    } else {
                        o.Apply (node);
                    }
                }
            }

            //Recalculate connections
            if (willChangeWalkability && erosion == 0) {

                clampedRect = IntRect.Intersection (affectRect, gridRect);
                for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) {
                    for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) {
                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;

                        CalculateConnections (nodes,x,z,node);
                    }
                }
            } else if (willChangeWalkability && erosion > 0) {

                clampedRect = IntRect.Union (originalRect, physicsRect);

                IntRect erosionRect1 = clampedRect.Expand (erosion);
                IntRect erosionRect2 = erosionRect1.Expand (erosion);

                erosionRect1 = IntRect.Intersection (erosionRect1,gridRect);
                erosionRect2 = IntRect.Intersection (erosionRect2,gridRect);

                /*
                all nodes inside clampedRect might have had their walkability changed
                all nodes inside erosionRect1 might get affected by erosion from clampedRect and erosionRect2
                all nodes inside erosionRect2 (but outside erosionRect1) will be reset to previous walkability
                after calculation since their erosion might not be correctly calculated (nodes outside erosionRect2 would maybe have effect)
                */

                for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) {
                    for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) {

                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;

                        bool tmp = node.walkable;
                        node.walkable = node.WalkableErosion;

                        if (!erosionRect1.Contains (x,z)) {
                            //Save the border's walkabilty data in bit 16 (will be reset later)
                            node.Bit16 = tmp;
                        }
                    }
                }

                for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) {
                    for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) {
                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;

                        CalculateConnections (nodes,x,z,node);
                    }
                }

                //Erode the walkable area
                ErodeWalkableArea (erosionRect2.xmin,erosionRect2.ymin,erosionRect2.xmax+1,erosionRect2.ymax+1);

                for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) {
                    for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) {
                        if (erosionRect1.Contains (x,z)) continue;

                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;

                        //Restore temporarily stored data
                        node.walkable = node.Bit16;
                    }
                }

                //Recalculate connections of all affected nodes
                for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) {
                    for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) {
                        int index = z*width+x;

                        GridNode node = nodes[index] as GridNode;
                        CalculateConnections (nodes,x,z,node);
                    }
                }
            }
        }