Esempio n. 1
0
        public int RemoveCollisionShapesWithHandleInternal(long handle)
        {
            // The dumb version: iterate over all containment spheres
            // looking for obstacles with the given handle, returning true
            // if a child changed.  (The smarter version would maintain an
            // index mapping handles to SphereTreeNodes whose
            // containedShape or intersectingShapes have a shape with
            // that handle.)
            //
            // This runs bottom-up, to provide an opportunity to coalesce
            // the sphere tree.

            // intersectingShapes are easy - - just remove if they have a
            // matching handle, since their removal doesn't change the tree
            int removeCount = 0;

            for (int i = 0; i < intersectingShapes.Count; i++)
            {
                CollisionShape obstacle = intersectingShapes[i];
                if (obstacle.handle == handle)
                {
                    if (MO.DoLog)
                    {
                        MO.Log(" Removing intersecting shape {0} of {1}", obstacle, this);
                    }
                    intersectingShapes.RemoveAt(i);
                    i--;
                    sphereTree.intersectingShapeCount--;
                    Debug.Assert(sphereTree.intersectingShapeCount >= 0, "intersectingShapeCount < 0!");
                }
            }

            // Now handle the children
            for (int i = 0; i < childCount; i++)
            {
                SphereTreeNode child = children[i];
                if (child != null)
                {
                    if (child.leafNode && child.containedShape.handle == handle)
                    {
                        if (MO.DoLog)
                        {
                            MO.Log(" Removing child leaf {0} of {1}", child, this);
                        }
                        children[i]  = null;
                        child.parent = null;
                        RenderedNode.RemoveNodeRendering(child.id, ref child.renderedNodes);
                        sphereTree.shapesRemoved++;
                        sphereTree.nodeCount--;
                        removeCount++;
                    }
                    else if (!child.leafNode)
                    {
                        removeCount += child.RemoveCollisionShapesWithHandleInternal(handle);
                    }
                }
            }

            int count = CountChildren();

            if (count == 0 && containedShape == null)
            {
                // This is now a truly pointless node - - remove from its
                // parent.  Parent will only be null for the root node
                if (parent != null)
                {
                    if (MO.DoLog)
                    {
                        MO.Log(" Removing branch with no kids {0} of {1}", this, parent);
                    }
                    parent.RemoveChild(this);
                    sphereTree.nodeCount--;
                    Debug.Assert(sphereTree.nodeCount > 0, "nodeCount <= 0");
                    return(removeCount);
                }
            }
            else if (count == 1)
            {
                if (parent != null)
                {
                    // Make my child the child of my parent
                    if (MO.DoLog)
                    {
                        MO.Log(" Replacing 1-child node {0} in parent {1}", this, parent);
                    }
                    parent.ReplaceChild(this, FindFirstChild());
                    sphereTree.nodeCount--;
                    Debug.Assert(sphereTree.nodeCount > 0, "nodeCount <= 0");
                    return(removeCount);
                }
            }
            if (removeCount > 0)
            {
                RecalculateCenterAndRadius();
            }
            return(removeCount);
        }