package ae { import flash.display.Sprite; import flash.events.MouseEvent; // quad tree used to delegate mouse events class CircleNode { //each Node has an associated Circle sprite public var parentCircle:Circle = null; //the tree has 2-way links protected var parent:CircleNode = null; //the children protected var child1:CircleNode = null; protected var child2:CircleNode = null; protected var child3:CircleNode = null; protected var child4:CircleNode = null; //boundaries used to select children when traversing public var xThresh:Number; public var yThresh:Number; //set up the connections to a Circle public function CircleNode(pc:Circle) { parentCircle = pc; pc.node = this; } // self explanatory public function addChildren(c1:CircleNode, c2:CircleNode, c3:CircleNode, c4:CircleNode) : void { child1 = c1; child2 = c2; child3 = c3; child4 = c4; c1.parent = this; c2.parent = this; c3.parent = this; c4.parent = this; } // recurse through the tree to find the handler for the mouse event public function findTarget(e:MouseEvent) : void { if(child1 == null && child2 == null && child3 == null && child4 == null) { //we are at a leaf node, split if(parentCircle != null) parentCircle.handleMouseOver(e); return; } //check the stage coords of the mouse event and compare with the //thresholds to determine which child to recurse down into //we must check it that child was null, it's possible that part of the //tree is already at the max depth if (e.stageX < xThresh && e.stageY < yThresh && child1 != null) child1.findTarget(e); else if(e.stageX > xThresh && e.stageY < yThresh && child2 != null) child2.findTarget(e); else if(e.stageX < xThresh && e.stageY > yThresh && child3 != null) child3.findTarget(e); else if(e.stageX > xThresh && e.stageY > yThresh && child4 != null) child4.findTarget(e); } //null out references to a given child public function killChild(c:CircleNode) : void { if(c == child1) child1 = null; if(c == child2) child2 = null; if(c == child3) child3 = null; if(c == child4) child4 = null; if(isEmpty()) //this node is useless, delete it from the parent deleteMe(); } public function isEmpty() : Boolean { return child1 == null && child2 == null && child3 == null && child4 == null; } // "delete" in this case just means to remove all references to the node so it can be GC'ed public function deleteMe() : void { parentCircle = null; child1 = null; child2 = null; child3 = null; child4 = null; if(parent != null) // this could be the root node { parent.killChild(this); parent = null; } } } }