package be.nascom.flash.util{ import flash.display.DisplayObject; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.geom.Rectangle; public class graphic_player_10_cube_be_nascom_flash_util_DisplayObjectsIntoUnitGridUtil extends EventDispatcher{ private var _min_rect:Rectangle; private var _max_rect:Rectangle; private var _target_rectangle:Rectangle; private var _unit_grid:UnitGrid; public function get display_objects():Array{ return _display_objects.slice(); } private var _display_objects:Array; public function get placed_display_objects():Array{ return _placed_display_objects.slice(); } private var _placed_display_objects:Array; private var _seed_stack:Array;//list of rectangles, added to stage, which have not yet been used as "seeds" for positioning rectangles. public function graphic_player_10_cube_be_nascom_flash_util_DisplayObjectsIntoUnitGridUtil(target:IEventDispatcher=null){ super(target); } public function init(display_objects:Array,unit_grid:UnitGrid,delay:uint=0):void{ _display_objects=display_objects; _placed_display_objects=new Array(); updateMaxAndMinRectangles(); _unit_grid=unit_grid; } protected function updateMaxAndMinRectangles():void{ var s:DisplayObject=DisplayObject(_display_objects[0]); var biggest:uint=Math.max(s.width,s.height); _min_rect=new Rectangle(0,0,biggest,biggest); _max_rect=_min_rect.clone(); for each(s in _display_objects){ biggest=Math.max(s.width,s.height); if(biggest>_max_rect.width)_max_rect=new Rectangle(0,0,biggest,biggest); if(biggest<_min_rect.width)_min_rect=new Rectangle(0,0,biggest,biggest); } /* trace("updateMaxAndMinRectangles()"); trace("\tmin_rect:"+_min_rect); trace("\tmax_rect:"+_max_rect); */ } private function extractDisplayObjectByIndex(index:uint):DisplayObject{ return DisplayObject(_display_objects.splice(index,1)[0]); } private function getRandomDisplayObject():DisplayObject{ var index:uint=Math.floor(Math.random()*_display_objects.length); return extractDisplayObjectByIndex(index); } private function getRectFromDisplayObject(_do:DisplayObject):Rectangle{ return new Rectangle(_do.x,_do.y,_do.width,_do.height); } private function placeFirstDisplayObject():DisplayObject{ var center_index:uint=_unit_grid.getCenterCellIndex(); //trace("placeFirstRectangle()1 center_index:"+center_index); var display_object:DisplayObject=getRandomDisplayObject(); //trace("placeFirstRectangle()2 getCellX:"+_unit_grid.getCellXByIndex(center_index)); //trace("placeFirstRectangle()3 getCellY:"+_unit_grid.getCellYByIndex(center_index)); //trace("placeFirstRectangle()4 rect:"+getRectFromDisplayObject(display_object)); display_object.x=Math.floor(_unit_grid.getCellXByIndex(center_index)-display_object.width/2); display_object.y=Math.floor(_unit_grid.getCellYByIndex(center_index)-display_object.height/2); //trace("placeFirstRectangle()5 rect:"+getRectFromDisplayObject(display_object)); _unit_grid.disableCellsUnderRect(getRectFromDisplayObject(display_object)); //return DisplayObject(addChild(rect)); return display_object; } public function placeDisplayObjectsIntoUnitGridRandom():void{ //var rect:DisplayObject; _seed_stack=new Array(); _seed_stack.push(placeFirstDisplayObject()); updateMaxAndMinRectangles(); var max_iterations:uint=200; var cur_iteration:uint=0; while(_display_objects.length && _seed_stack.length){ populateFromSeed(DisplayObject(_seed_stack.shift())); if(++cur_iteration>max_iterations)break; //trace("fitRectangles() Looping : "+cur_iteration+", _display_objects:"+_display_objects.length+",_seed_stack.length:"+_seed_stack.length); } } private var _place_rect_functions:Array=new Array(placeDisplayObjectToTheRight,placeDisplayObjectBelow,placeDisplayObjectToTheLeft,placeDisplayObjectAbove); private function populateFromSeed(rect:DisplayObject):void{ //var source_bounds:Rectangle=rect.getBounds(stage); var source_bounds:Rectangle=new Rectangle(rect.x,rect.y,rect.width,rect.height); //trace(source_bounds); //trace("populateFromSeed() : source_bounds:"+source_bounds); var indeces:Array=new Array(0,1,2,3); var order:Array=new Array(); while(indeces.length){ order.push(indeces.splice(Math.floor(Math.random()*indeces.length),1)); } for(var i:uint=0;i<4;i++){ _place_rect_functions[order[i]](source_bounds); } /* placeDisplayObjectToTheRight(source_bounds); placeDisplayObjectBelow(source_bounds); placeDisplayObjectToTheLeft(source_bounds); placeDisplayObjectAbove(source_bounds); */ } private function placeAvailableDisplayObjectIntoRectangle(source_rect:Rectangle,unit_grid_rect:Rectangle):void{ if(source_rect==null || unit_grid_rect==null)return; if(unit_grid_rect.width>=_min_rect.width){ var available:DisplayObject=findDisplayObjectWhichFitsIn(unit_grid_rect); if(available==null){ trace("placeAvailableDisplayObjectIntoRectangle() No available rectangle found"); return; } available.x=unit_grid_rect.x+unit_grid_rect.width/2-available.width/2; available.y=unit_grid_rect.y+unit_grid_rect.height/2-available.height/2; _unit_grid.disableCellsUnderRect(new Rectangle(available.x,available.y,available.width,available.height)); _seed_stack.push(available); //addChild(available); _placed_display_objects.push(removeDisplayObject(available)); updateMaxAndMinRectangles(); } } private function placeDisplayObjectToTheRight(source_bounds:Rectangle):void{ //trace("placeDisplayObjectToTheRight()"); var found:Rectangle=_unit_grid.findRectangleToTheRight(source_bounds,_min_rect,_max_rect); //trace("placeDisplayObjectToTheRight() found : "+found); if(found!=null)placeAvailableDisplayObjectIntoRectangle(source_bounds,found); } private function placeDisplayObjectBelow(source_bounds:Rectangle):void{ //trace("placeDisplayObjectBelow()"); var found:Rectangle=_unit_grid.findRectangleBelow(source_bounds,_min_rect,_max_rect); //trace("placeDisplayObjectBelow() found : "+found); if(found!=null)placeAvailableDisplayObjectIntoRectangle(source_bounds,found); } private function placeDisplayObjectToTheLeft(source_bounds:Rectangle):void{ //trace("placeDisplayObjectToTheLeft()"); var found:Rectangle=_unit_grid.findRectangleToTheLeft(source_bounds,_min_rect,_max_rect); //trace("placeDisplayObjectToTheLeft() found : "+found); if(found!=null)placeAvailableDisplayObjectIntoRectangle(source_bounds,found); } private function placeDisplayObjectAbove(source_bounds:Rectangle):void{ //trace("placeDisplayObjectAbove()"); var found:Rectangle=_unit_grid.findRectangleAbove(source_bounds,_min_rect,_max_rect); //trace("placeDisplayObjectToTheAbove() found : "+found); if(found!=null)placeAvailableDisplayObjectIntoRectangle(source_bounds,found); } private function findDisplayObjectWhichFitsIn(rect:Rectangle):DisplayObject{ var candidate:DisplayObject; var max_side:uint; if(rect.widthMath.max(candidate.width,candidate.height)){ candidate=s; } } } return candidate; } //meh... maybe _display_objects should be passed as argument... private function removeDisplayObject(_disp_obj:DisplayObject):DisplayObject{ for(var i:uint=0;i<_display_objects.length;i++){ if(_display_objects[i]==_disp_obj){ return _display_objects.splice(i,1)[0]; } } trace("removeRectangle, no match found. rect:"+_disp_obj); return null; } } }