DAN ZEN EXPO - CODE EXHIBIT - OPARTICA TUNNEL

package tunnel {
	
 	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.*;
	import flash.media.Sound;
	import flash.media.SoundChannel;	
	import flash.net.URLRequest;
	import flash.display.StageScaleMode;
	import flash.display.StageAlign;
	import fl.controls.Slider;
	import flash.ui.Mouse;
	import flash.ui.Keyboard;
	import flash.display.CapsStyle;
	import flash.display.JointStyle;
	import flash.geom.Point; 
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import fl.data.DataProvider;
	import flash.filters.GlowFilter;	
	import flash.utils.Timer;
	import flash.net.SharedObject;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.system.System;
	import flash.text.Font;
	import flash.text.TextFormat;
	
	import com.adobe.serialization.json.JSON;
	import com.danzen.utilities.DynamicObject;
	import com.danzen.utilities.Ticks;
	import com.danzen.effects.HummingBird;
	import com.danzen.interfaces.Pane;	
	import com.danzen.utilities.UniqueRandom;

	public dynamic class Tunnel extends MovieClip {
		
		private var holder:Sprite;
		private var mySound:Sound;
		private var myChannel:SoundChannel;
		private var mouseDownClip:Sprite;
		private var showTimer:Timer;
		private var showSpeed:Number=0;
		private var mouseCheck:Boolean = true;
		private var pannels:Array;
		private var mySO:SharedObject;
		private var myHummingBird:HummingBird;
		private var pannelsStart:Array = [
			{name:"zoom", min:0, max:30, step:1, val:9, alpha:.6, live:true, tick:1}, // 0-6000
			{name:"pan", min:0, max:30, step:1, val:0, alpha:.6, live:true, tick:1}, // 0-6000
			
			{name:"layers", min:1, max:30, step:1, val:9, alpha:1, live:true, tick:1},
			{name:"distance", min:1, max:10, step:1, val:6, alpha:1, live:true, tick:1},
			
			{name:"tiling", min:0, max:1, step:1, val:0, alpha:.6, live:false, tick:1},
			{name:"segments", min:1, max:64, step:1, val:6, alpha:.6, live:true, tick:2},			
			{name:"twist", min:0, max:90, step:1, val:0, alpha:.6, live:true, tick:2},			
			{name:"cols", min:1, max:30, step:1, val:6, alpha:.6, live:true, tick:1},			
			{name:"rows", min:1, max:30, step:1, val:3, alpha:.6, live:true, tick:1},
			{name:"colspace", min:0, max:100, step:1, val:50, alpha:.6, live:true, tick:5},			
			{name:"rowspace", min:0, max:100, step:1, val:50, alpha:.6, live:true, tick:5},
			
			{name:"shape", min:1, max:12, step:1, val:1, alpha:1, live:true, tick:1}, // c,t,s,ct,cs,ts,cts
			{name:"shape fill", min:0, max:20, step:1, val:4, alpha:1, live:true, tick:1},
			{name:"line", min:0, max:20, step:1, val:0, alpha:1, live:true, tick:1},
			{name:"line fill", min:0, max:20, step:1, val:4, alpha:1, live:true, tick:1},		
			{name:"mod 1", min:0, max:50, step:1, val:10, alpha:1, live:true, tick:2},
			{name:"mod 2", min:0, max:50, step:1, val:0, alpha:1, live:true, tick:2},
			{name:"mod 3", min:0, max:50, step:1, val:0, alpha:1, live:true, tick:2},
			{name:"mod 4", min:0, max:50, step:1, val:0, alpha:1, live:true, tick:2},
			{name:"mod 5", min:0, max:50, step:1, val:0, alpha:1, live:true, tick:2},
			{name:"mod 6", min:0, max:50, step:1, val:0, alpha:1, live:true, tick:2},
			
			
			{name:"backing", min:1, max:14, step:1, val:0, alpha:.6, live:true, tick:1},
			{name:"blend", min:0, max:6, step:1, val:5, alpha:.6, live:true, tick:1},
			{name:"m key", min:0, max:1, step:1, val:1, alpha:.6, live:false, tick:1}
			
		];		
		
		private var controls:Object = new Object();
		private var pO:Object = new Object(); // lookup for pannels array via name as property
		private var blends:Array = ["multiply", "screen", "overlay", "hardlight", "difference", "subtract", "invert"];
		private var cities:Array = ["Hong Kong","New York City","Sao Paulo","Singapore","Moscow","Seoul","Tokyo","Rio de Janeiro","Istanbul","Toronto","Buenos Aires","Kiev","Osaka","London","Mumbai","Mexico City","Madrid","Chicago","Caracas","Santiago","Recife","Shanghai","Campinas","Beijing","St. Petersburg","Sydney","Curitiba","Minsk","Bangkok","Yekaterinburg","Paris","Milan","Porto Alegre","Sofia","Vancouver","Rosario","Macau","Kuala Lumpur","Melbourne","Dubai","Chongging","Kharkiv","Montreal","Los Angeles","Guangzhou","Wuhan","Barcelona","Honolulu","Ankara","San Francisco","Jakarta","Benidorm","Shenzhen","Houston","Berlin","Philadelphia","Valencia","Washington","Bilbao","Malaga","Novosibirsk","Tianjin","Ottawa","Frankfurt","Rotterdam","Miami","Gold Coast City","San Juan","Calgary","Dallas","Edmonton","Brisbane","Boston","Arlington","Atlanta","Seattle","Auckland","Denver","Minneapolis","Detroit","Baltimore","Miami Beach","St. Louis","San Diego","Perth","Fort Lauderdale","Adelaide","Pittsburgh","Cincinnati"];
		private var citiesTaken:UniqueRandom;
		private var stageStartH:Number = 1000;
		private var stageScaleH:Number = 1;
		private var randomA:Array = []; // holds last random angles
		private var randomD:Array = []; // holds last random distances
		private var lastSegments:Number;
		private var lastRows:Number;
		private var lastCols:Number;
		private var lastShape:Number = 0;
		private var lastLayers:Number = 0;
		private var lastSliderSetting:Number = -1;
		private var randCheck:Boolean;
		private var myPane:Pane;
		private var myFont:Font;
		private var myFormat:TextFormat;
		private var currentSelection:Number;
		private var changesMade:Boolean = false;
		
		public function Tunnel() {			
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event) {			
									
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.addEventListener(Event.RESIZE, scaleStage);			
			stage.align = StageAlign.TOP_LEFT;		
						
			mySO = SharedObject.getLocal("oparticaTunnel");
			//mySO.clear();
			if (mySO.data.pannels == null) {
				mySO.data.pannels = DynamicObject.copy(pannelsStart);
				mySO.data.randomA = [];
				mySO.data.randomD = [];
				mySO.data.record = [];
				mySO.data.city = 0;
				mySO.data.currentSelection = -1;
			}
			
			// record holds [["city", pannels, randomA, randomD], etc.]
			
			pannels = mySO.data.pannels;
			setCities();
			
			showTimer = new Timer(1000);
			showTimer.addEventListener(TimerEvent.TIMER, showChange);
			
			mouseDownClip = new Sprite();
			mouseDownClip.graphics.beginFill(0x000000,0);
			mouseDownClip.graphics.drawRect(0,0,stage.stageWidth, stage.stageHeight);
			addChildAt(mouseDownClip, 0);
			
			image.mouseEnabled = false;
			image.gotoAndStop(3);
			image.cacheAsBitmap = true;			
			//image.blendMode = "difference";
			//image.visible = false;
			holder = new Sprite();
			holder.z = 4000;
			holder.mouseEnabled = false;
			holder.mouseChildren = false;
			//holder.filters = [new GlowFilter(0xccffff, 1, 20, 20, 3, 1, false)];
			addChild(holder);		
			setChildIndex(image, numChildren-1);
			
			scaleStage(new Event(""));
									
			makePannelLookup();
			myHummingBird = new HummingBird(holder, pO.pan.val*200, 0, pO.zoom.val*400, .1, mouseDownClip);
			//myHummingBird.randomize = 0;
			myHummingBird.shiftX = pO.pan.val*200;					
			myHummingBird.shiftZ = pO.zoom.val*400;
			image.gotoAndStop(pO.backing.val);
						
			lastSegments = pO.segments.val;
			randomA = mySO.data.randomA;
			randomD = mySO.data.randomD;			
			
			createTunnel();		
			
			setChildIndex(pannel, numChildren-1);
			pannel.addEventListener(MouseEvent.MOUSE_DOWN, function(){});
			pannel.addEventListener(MouseEvent.MOUSE_UP, function(){});
			
			setChildIndex(pannel2, numChildren-1);
			pannel2.addEventListener(MouseEvent.MOUSE_DOWN, function(){});
			pannel2.addEventListener(MouseEvent.MOUSE_UP, function(){});
			pannel2.dataPane.visible = false;
		
			makePannel();	
			makePannel2();
			setChildIndex(logo, numChildren-1);
			logo.buttonMode = true;
			logo.addEventListener(MouseEvent.CLICK, togglePannel);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, doKey);
			
		}
		
		private function setCities() {
			citiesTaken = new UniqueRandom(cities);	
			for (var i:uint=0; i<mySO.data.record.length; i++) {				
				citiesTaken.removeElementTemp(mySO.data.record[i][0]);
			}			
		}
		
		private function togglePannel(e:MouseEvent) {
			pannel.visible = !pannel.visible;			
			pannel2.visible = !pannel2.visible;
		}
		
		private function makePannel2() {
			pannel2.recordBut.addEventListener(MouseEvent.CLICK, recordData);
			pannel2.updateBut.addEventListener(MouseEvent.CLICK, updateCurrent);
			pannel2.deleteBut.addEventListener(MouseEvent.CLICK, deleteCurrent);
			pannel2.importBut.addEventListener(MouseEvent.CLICK, importData);
			pannel2.exportBut.addEventListener(MouseEvent.CLICK, exportData);	
			pannel2.dataPane.closeBut.addEventListener(MouseEvent.CLICK, closeData);
			pannel2.dataPane.otherBut.addEventListener(MouseEvent.CLICK, otherData);
			
			pannel2.info.myList.addEventListener(Event.CHANGE, chooseTunnel);
			
			pannel2.dataPane.myLabel.mouseEnabled = false;
			pannel2.dataPane.myLabel.mouseChildren = false;
			pannel2.dataPane.myLabel.stop();
			setList();
			
			myFont = new Font2();
			myFormat = new TextFormat();
			myFormat.font = myFont.fontName;
			myFormat.size = 16;
			//myFormat.color = 0xaaaaaa;
			pannel2.dataPane.myText.setStyle("textFormat", myFormat);		
			pannel2.dataPane.myText.alpha = .5;
			
			pannel2.addChildAt(new Ticks(pannel2.showSlider, 1, .2, Ticks.POSITION_TOP),pannel2.getChildIndex(pannel2.showSlider)); // slider, tickInterval 
			pannel2.addChildAt(new Ticks(pannel2.zoomSlider, 1, .2, Ticks.POSITION_TOP),pannel2.getChildIndex(pannel2.zoomSlider)); // slider, tickInterval 
			pannel2.showSlider.addEventListener(Event.CHANGE, doShowSlider);
			pannel2.zoomSlider.addEventListener(Event.CHANGE, doZoomSlider);
			
		}
		
		private function doZoomSlider(e:Event) {
			myHummingBird.randomize = pannel2.zoomSlider.value;
			stage.focus = null;
		}
		
		private function doShowSlider(e:Event) {
			showSpeed = pannel2.showSlider.value;		
			if (showSpeed == 0) {
				trace ("turn off show");
				showTimer.stop();
			} else {				
				if (changesMade) {			
					myPane = new Pane(300,200,true,0xffffff,.8,true,false,true,0xffffff,.3);				
					addChild(myPane);
					var myContent:PaneContent2 = new PaneContent2();
					myPane.addChild(myContent);
					myPane.addEventListener(Pane.EXIT, removePane);
					myPane.x = stage.stageWidth-400;
					myPane.y = stage.stageHeight/2-270;			
					myContent.myText.text = "Would you like to save\nthe current tunnel before\nrunning the show?";
					myContent.cancelBut.addEventListener(MouseEvent.CLICK, removePane);
					myContent.yesBut.addEventListener(MouseEvent.CLICK, doShowUpdateCurrent);
					myContent.noBut.addEventListener(MouseEvent.CLICK, show2);
					changesMade = false;
				} else {
					show2(new MouseEvent(""));
				}				
			}
		}
		
		private function show2(e:MouseEvent) {
			showTimer.delay = Math.pow((11-showSpeed),2)*1000;
			showTimer.reset();
			showTimer.start();
			removePane(new Event(""));
		}
		
		private function showChange(e:TimerEvent) {
			changesMade = false;
			var cs:Number = pannel2.info.myList.selectedIndex;
			if (cs < 0) {return;}
			cs++; 
			if (cs >= pannel2.info.myList.length) {
				cs = 0;
			}
			pannel2.info.myList.selectedIndex = cs;	
			choose2(new MouseEvent(""));
		}
		
		private function doShowUpdateCurrent(e:MouseEvent) {
			updateCurrent(new MouseEvent(""));
			show2(new MouseEvent(""));
		}
		
		private function deleteCurrent (e:MouseEvent) {	
			myPane = new Pane(300,200,true,0xffffff,.8,true,false,true,0xffffff,.3);				
			addChild(myPane);
			var myContent:PaneContent = new PaneContent();
			myPane.addChild(myContent);
			myPane.addEventListener(Pane.EXIT, removePane);
			myPane.x = stage.stageWidth-480;
			myPane.y = stage.stageHeight/2-270;				
			myContent.myText.text = "Are you sure you want to\ndelete the current Tunnel?\nThere is no undo...";
			myContent.cancelBut.addEventListener(MouseEvent.CLICK, removePane);
			myContent.okayBut.addEventListener(MouseEvent.CLICK, doDelete);
		}
		
		private function doDelete(e:MouseEvent) {
			trace ("do delete");
			
			var cs:Number = pannel2.info.myList.selectedIndex;			
			if (cs < 0) {return;}
			
			pannel2.info.myList.removeItemAt(cs);				
			mySO.data.record.splice(cs,1);
			
			if (cs < pannel2.info.myList.length) { // deleting item other than last item
				mySO.data.currentSelection = pannel2.info.myList.selectedIndex = cs;
			} else if (pannel2.info.myList.length == 0) { // deleting last item 
				mySO.data.currentSelection = pannel2.info.myList.selectedIndex = -1;
			} else { // deleting last item but there are more		
				mySO.data.currentSelection = pannel2.info.myList.selectedIndex = cs-1;
			}			
			choose2(new MouseEvent(""));
			removePane(new MouseEvent(""));
		}
		
		private function chooseTunnel(e:Event) {			
			
			/*var diff:Boolean = false;
			trace (mySO.data.currentSelection);		
			if (!DynamicObject.compare(mySO.data.record[mySO.data.currentSelection][1], mySO.data.pannels)) {
				diff = true;			
				trace ("one");
			} else if (!DynamicObject.compare(mySO.data.record[mySO.data.currentSelection][2], mySO.data.randomA)) {
				diff = true;			
				trace ("two");
			} else if (!DynamicObject.compare(mySO.data.record[mySO.data.currentSelection][3], mySO.data.randomD)) {
				trace ("three");
				diff = true;			
			} */
									
			if (changesMade) {			
				myPane = new Pane(300,200,true,0xffffff,.8,true,false,true,0xffffff,.3);				
				addChild(myPane);
				var myContent:PaneContent2 = new PaneContent2();
				myPane.addChild(myContent);
				myPane.addEventListener(Pane.EXIT, removePane);
				myPane.x = stage.stageWidth-400;
				myPane.y = stage.stageHeight/2-270;			
				myContent.myText.text = "Would you like to save\nthe current tunnel before\nchanging tunnels?";
				myContent.cancelBut.addEventListener(MouseEvent.CLICK, removePane);
				myContent.yesBut.addEventListener(MouseEvent.CLICK, doUpdateCurrent);
				myContent.noBut.addEventListener(MouseEvent.CLICK, choose2);
				changesMade = false;
			} else {
				choose2(new MouseEvent(""));
			}	
		}
		
		private function doUpdateCurrent(e:MouseEvent) {
			updateCurrent(new MouseEvent(""));
			choose2(new MouseEvent(""));
		}
		
		private function updateCurrent(e:MouseEvent) {
					
			if (mySO.data.currentSelection < 0) {
				recordData(new MouseEvent(""));
				return;
			}
			mySO.data.record[mySO.data.currentSelection][1] = DynamicObject.copy(mySO.data.pannels);			
			mySO.data.record[mySO.data.currentSelection][2] = DynamicObject.copy(mySO.data.randomA);
			mySO.data.record[mySO.data.currentSelection][3] = DynamicObject.copy(mySO.data.randomD);
						
			changesMade = false;
		}
		
		private function choose2(e:MouseEvent) {
						
			if (mySO.data.currentSelection == -1) {
				mySO.data.pannels = DynamicObject.copy(pannelsStart);
				mySO.data.randomA = [];
				mySO.data.randomD = [];
				mySO.data.record = [];
				mySO.data.city = 0;
			} else {			
				mySO.data.pannels = DynamicObject.copy(mySO.data.record[pannel2.info.myList.selectedIndex][1]);
				mySO.data.randomA = DynamicObject.copy(mySO.data.record[pannel2.info.myList.selectedIndex][2]);
				mySO.data.randomD = DynamicObject.copy(mySO.data.record[pannel2.info.myList.selectedIndex][3]);
			}
										
			pannels = mySO.data.pannels;						
			randomA = mySO.data.randomA;
			randomD = mySO.data.randomD;			
						
			makePannelLookup();
			lastSegments = pO.segments.val;
			
			clearPannel();
			image.gotoAndStop(pO.backing.val);			
			myHummingBird.shiftX = pO.pan.val*200;					
			myHummingBird.shiftZ = pO.zoom.val*400;	
			
			mySO.data.currentSelection = pannel2.info.myList.selectedIndex;		
			
			removeTunnel();
			removePane(new Event(""));
		}
		
		private function recordData(e:MouseEvent) {

			var currentConfig:Array = [];
			var c:String = citiesTaken.getElement(); //cities[mySO.data.city]
			
			currentConfig.push(c);
			mySO.data.city++;
			mySO.data.city = mySO.data.city % cities.length;
			currentConfig.push(DynamicObject.copy(pannels));
			currentConfig.push(DynamicObject.copy(randomA));
			currentConfig.push(DynamicObject.copy(randomD));
			mySO.data.record.push(currentConfig);
			
			pannel2.info.myList.addItem({label:c});			
			pannel2.info.myList.selectedIndex = mySO.data.currentSelection = pannel2.info.myList.length-1;
			
			changesMade = false;
			
			if (mySO.data.record.length % 10 == 0) {
				var dat:String = JSON.encode(mySO.data.record);
				var len:Number = dat.length;			
				var s:String = mySO.flush(len * 1.1);				
			}
			
			
			// trying to draw the 3D images but it does not work
				/*
			var myBitmapData:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight);
			//myBitmapData.draw(holder);
			
			var p:Sprite;
			var m3:Matrix3D;
			var rawMatrixData:Vector.<Number>;
			var matrix:Matrix;
			//holder.transform.perspectiveProjection.projectionCenter = new Point(image.x, image.y); 
			for (i=0; i<holder.numChildren; i++) {
				p = Sprite(holder.getChildAt(i));
				m3 = p.transform.matrix3D;
				rawMatrixData = m3.rawData;
				
				matrix = new Matrix();
				matrix.a = rawMatrixData[0];
				trace (matrix.a);
				matrix.c = rawMatrixData[1];
				matrix.tx = p.x - 0;
				
				matrix.b = rawMatrixData[4];
				matrix.d = rawMatrixData[5];
				matrix.ty = p.y - 0;
				myBitmapData.draw(holder.getChildAt(i), holder.getChildAt(i).transform.matrix);
			}
			var myBitmap:Bitmap = new Bitmap(myBitmapData);
			addChild(myBitmap);
			*/
			
		}
		
		private function closeData(e:MouseEvent) {
			pannel2.dataPane.visible = false;
		}
		
		private function otherData(e:MouseEvent) {
			if (pannel2.dataPane.myLabel.currentFrame == 1) {
				trace ("import");
				var num:Number = parseData(pannel2.dataPane.myText.text, false);
				myPane = new Pane(300,200,true,0xffffff,.8,true,false,true,0xffffff,.3);				
				addChild(myPane);
				var myContent:PaneContent = new PaneContent();
				myPane.addChild(myContent);
				myPane.addEventListener(Pane.EXIT, removePane);
				myPane.x = stage.stageWidth-600;
				myPane.y = stage.stageHeight/2-270;
				var added:String = " entries";
				if (num == 1) {added = " entry";}
				myContent.myText.text = "Would you like to import\n"+num+added+".  Warning: this will\nreplace your saved data";
				myContent.cancelBut.addEventListener(MouseEvent.CLICK, removePane);
				myContent.okayBut.addEventListener(MouseEvent.CLICK, doImport);
			} else {
				trace ("export");
				stage.focus = pannel2.dataPane.myText;
				pannel2.dataPane.myText.setSelection(0,pannel2.dataPane.myText.length)
				System.setClipboard(pannel2.dataPane.myText.text);
			}
		}
		
		private function doImport(e:MouseEvent) {
			parseData(pannel2.dataPane.myText.text, true);
			
			var dat:String = JSON.encode(mySO.data.record);
			var len:Number = dat.length;			
			var s:String = mySO.flush(len * 1.1);				
			
			removePane(new Event(""));
			closeData(new MouseEvent(""));
			setCities();
		}
		
		private function removePane(e:Event) {
			if (!myPane || !contains(myPane)) {return;}
			removeChild(myPane);
			myPane.dispose();
			pannel2.info.myList.selectedIndex = mySO.data.currentSelection;
		}
		
		private function parseData(d:String, live:Boolean):Number {
			//d = d.replace(/\r/g, "\n");
			var list:Array = d.split("title^");
			var lines:Array;
			if (live) {mySO.data.record = [];}
			var t:String;
			var p:Array;
			var ra:Array;
			var rd:Array;
			var count:Number = 0;
			var j:uint;
			var temp:Array;
			for (var i:uint=0; i<list.length; i++) {	
				lines = list[i].split(/\r|\n/g);
				if (lines.length < 4) {continue;}
				t = "";
				temp = [];
				while (lines.length > 0) { 
					if (lines[0] == "") {lines.shift(); continue;}
					if (t == "") {t = lines.shift(); continue;}
					if (lines[0].split("^").length > 1) {
						temp.push(lines.shift().split("^")[1]);
					}
				}
				if (temp.length < 3) {continue;}
				
				p = JSON.decode(temp[0]);
				ra = JSON.decode(temp[1]);
				rd = JSON.decode(temp[2]);				
				if (live) {mySO.data.record.push([t,p,ra,rd]);} 
				count++;				
			}
						
			setList();
			return count;
		}
		
		private function importData(e:MouseEvent) {
			pannel2.dataPane.visible = true;
			pannel2.dataPane.myLabel.gotoAndStop(1);
			pannel2.dataPane.myText.text = "";
		}
		
		private function exportData(e:MouseEvent) {	
			pannel2.dataPane.visible = true;
			pannel2.dataPane.myLabel.gotoAndStop(2);
			pannel2.dataPane.myText.text = "";
			for (var i:uint=0; i<mySO.data.record.length; i++) {			
				pannel2.dataPane.myText.appendText("title^"+mySO.data.record[i][0]);
				pannel2.dataPane.myText.appendText("\npannels^"+JSON.encode(mySO.data.record[i][1]));
				pannel2.dataPane.myText.appendText("\nrandomA^"+JSON.encode(mySO.data.record[i][2]));
				pannel2.dataPane.myText.appendText("\nrandomD^"+JSON.encode(mySO.data.record[i][3])+"\n\n");
			}
			pannel2.dataPane.myText.setStyle("textFormat", myFormat);
		}
		
		private function makePannel() {
			var n:MovieClip;
			var startSpacing:Number = 50;
			var spacing:Number = 3;
			var tileCheck:Boolean = false;
			var counter:Number = 0;
			for (var i:uint=0; i<pannels.length; i++) {
				if (pannels[i].name == "tiling") {
					if (pannels[i].val != 0) {
						tileCheck = true;
					}
				}
				//trace (tileCheck + "-----------")
				if (tileCheck) {
					if (pannels[i].name == "segments") {continue;}
					if (pannels[i].name == "twist") {continue;}	
					pannel.backing.height = 960;
				} else {
					if (pannels[i].name == "cols") {continue;}
					if (pannels[i].name == "rows") {continue;}		
					if (pannels[i].name == "colspace") {continue;}
					if (pannels[i].name == "rowspace") {continue;}	
					pannel.backing.height = 878;
				}				
				n = controls[pannels[i].name.replace(" ","")] = new ControlStrip();				
				n.o = pannels[i];
				pannels[i].control = n;
				pannel.addChild(n);
				n.y = startSpacing + (spacing + n.height) * counter;
				n.t.text = n.o.name.toUpperCase();
				n.b.alpha = n.o.alpha;
				n.s.inner.minimum = n.o.min;
				n.s.inner.maximum = n.o.max
				n.s.inner.snapInterval = n.o.step;
				//n.s.inner.tickInterval = 1;				
				//n.s.inner.setChildIndex(n.s.inner.getChildAt(1),n.s.inner.numChildren-1);
				n.s.inner.value = n.o.val;				
				n.s.inner.liveDragging = n.o.live;	
				n.s.inner.addEventListener(Event.CHANGE, doSlider);
				counter++;
				//trace (pannels[i].name, n.o.min, n.o.max, n.o.val);
				//holder.addChildAt(new Ticks(holder.slider, 1), holder.getChildIndex(holder.slider));
				n.s.addChildAt(new Ticks(n.s.inner, n.o.tick, .2, Ticks.POSITION_TOP), n.s.getChildIndex(n.s.inner)); // slider, tickInterval 
				
			}						
		}
		
		private function makePannelLookup() {
			pO = {};
			for (var i:uint=0; i<pannels.length; i++) {
				pO[pannels[i].name.replace(" ","")] = pannels[i]; 
			}
		}
		
		private function clearPannel() {
			for (var i:uint=pannel.numChildren-1; i>0; i--) {
				pannel.removeChildAt(i);
			}
			makePannel();
		}
								
		private function doSlider(e:Event) {
			var s:Slider = Slider(e.target);			
			var o:Object = MovieClip(s.parent.parent).o;
			var n:String = o.name;
			o.val = s.value;
			changesMade = true;
			stage.focus = null;

			switch (n) {				
				case "backing":					
					image.gotoAndStop(o.val);
					break;		
				case "shape":					
					if (lastShape != o.val) {
						randCheck = false;
						lastSegments = 0; // force redraw
						lastRows = 0; 
						lastCols = 0;
						lastShape = o.val;
					} else {
						return;
					}
					break;								
				case "layers":					
					if (lastLayers != o.val) {
						randCheck = false;
						lastSegments = 0; // force redraw
						lastRows = 0; 
						lastCols = 0;
						lastLayers = o.val;
					} else {
						return;
					}					
					break;							
				case "pan":
					myHummingBird.shiftX = o.val*200;
					break;
				case "zoom":
					myHummingBird.shiftZ = o.val*400;					
					break;
				case "tiling":						
					clearPannel();					
					break;
				case "m key":
					if (mouseCheck) {
						Mouse.hide();
					} else {
						Mouse.show();
					}
					mouseCheck = !mouseCheck;
					break;	
				case "blend":
					image.cacheAsBitmap = false;
					break;
			}
			if (lastSliderSetting!=o.val) {
				removeTunnel();
				lastSliderSetting = o.val;
			}
		}
		
				
		private function doKey(e:KeyboardEvent) {
			//trace (e.keyCode);
			var cs:Number;
			if (e.keyCode == 77) {
				if (mouseCheck) {
					Mouse.hide();
					controls.mkey.s.inner.value = 0;
					pO.mkey.val = 0;
				} else {
					Mouse.show();
					controls.mkey.s.inner.value = 1;
					pO.mkey.val = 1;
				}
				mouseCheck = !mouseCheck;
			} else if (e.keyCode >= 48 && e.keyCode <= 57) { // numbers
				pannel2.zoomSlider.value = e.keyCode-48;
				if (pannel2.zoomSlider.value > 2) {
					pannel2.zoomSlider.value++; // handle 0-9 really doing 0-2,4-10
				}
				doZoomSlider(new Event(""));
			} else if (e.keyCode == 37) {
				pannel2.showSlider.value--;
				doShowSlider(new Event(""));
			} else if (e.keyCode == 39) {
				pannel2.showSlider.value++;
				doShowSlider(new Event(""));
			} else if (e.keyCode == 38) {
				cs = pannel2.info.myList.selectedIndex;				
				if (cs < 0) {return;}
				cs--; 
				if (cs < 0) {
					cs = pannel2.info.myList.length-1;
				}
				pannel2.info.myList.selectedIndex = cs;
				chooseTunnel(new Event(""));
			} else if (e.keyCode == 40) {
				cs = pannel2.info.myList.selectedIndex;
				if (cs < 0) {return;}
				cs++; 
				if (cs >= pannel2.info.myList.length) {
					cs = 0;
				}
				pannel2.info.myList.selectedIndex = cs;
				chooseTunnel(new Event(""));				
			}
			//if (stage.focus != pannel2.dataPane.myText) {
				//stage.focus = null;
			//}
		}
		
		private function scaleStage(e:Event) {
			image.x = stage.stageWidth/2;
			image.y = stage.stageHeight/2;
			stageScaleH = stage.stageHeight / stageStartH;
			mouseDownClip.width = stage.stageWidth;
			mouseDownClip.height = stage.stageHeight;
			pannel.scaleX = pannel.scaleY = pannel2.scaleX = pannel2.scaleY = logo.scaleX = logo.scaleY = stageScaleH;
			pannel2.x = stage.stageWidth - pannel2.backing.width - 24;
			root.transform.perspectiveProjection.projectionCenter = new Point(image.x, image.y); 
			removeTunnel();
		}
		
		private function removeTunnel() {
			if (holder.numChildren <= 0) {return;}
			for (var i:uint=holder.numChildren-1; i>0; i--) {
				Sprite(holder.getChildAt(i)).graphics.clear();
				holder.removeChildAt(i);
			}
			if (holder.numChildren == 1) {holder.removeChildAt(0);}
			createTunnel();			
		}
		
		private function roundTo(n:Number, d:Number):Number {
			if (d <= 1) {return Math.round(n);}
			return Math.round(n*10*d)/10/d;
		}
		
		
		private function createTunnel() {
			var layers:Number = pO.layers.val;
			var distance:Number = pO.distance.val*100;
			var radius:Number = 300; //180;
			var pattern:Sprite;
			var startX:Number = stage.stageWidth/2;			
			var startY:Number = stage.stageHeight/2;						
			var smallRadius:Number = radius/30;
			var color:Number = 0x000;
			var shapefill:Number = pO.shapefill.val/pO.shapefill.max;
			var linefill:Number = pO.linefill.val/ pO.linefill.max;
			var w:Number; var a:Number; var r:Number; var h:Number;
			var dX:Number; var dY:Number;
			var rect:Sprite;
			var centerX:Number; var centerY:Number;						
			var i:uint; var j:Number; var k:uint; var m:uint;
			
			// -------------- rays ------------//
			
			var sW:Number = stage.stageWidth;
			var sH:Number = stage.stageHeight;
			
			//cl.x = sW/2;
			//cl.y = sH/2;					
			//cl.graphics.lineStyle(1,0x000,1);	
			//cl.graphics.beginFill(0x000,1);
			
			//var a:Number; 
			var b:Number; var c:Number; var d:Number; var e:Number; var f:Number;
			var e1:Number; var e1W:Number;
			var ang:Number; 
			var point1:Point; var point2:Point; var point3:Point; var point4:Point; var pointRem:Point; 
			var e1s:Number; var e1b:Number;	var e2s:Number; var e2b:Number;
			var intX:Number; var intY:Number;
			
			var numRays:Number = 30;
			//var i:uint;
			var dir:Number=1;
			var flip:Boolean = true;
			var alternate:Boolean = false;
			var widest:Number;
			var tallest:Number;
			
			//-----------------
						
			image.blendMode = blends[pO.blend.val];
			image.cacheAsBitmap = true;
			
			if (pO.tiling.val == 1) { // tiling				
				var cols:Number = pO.cols.val;
				var rows:Number = pO.rows.val;				
				var spacingX:Number = pO.colspace.val*6;
				var spacingY:Number = pO.rowspace.val*6;				
			} else {
				var twist:Number = pO.twist.val;
			}
			
			if (pO.tiling.val == 1) { // tiles
				randCheck = true;
				if (lastCols != pO.cols.val || lastRows != pO.rows.val) {
					randCheck = false;
					randomA = [];
					randomD = [];
					lastRows = pO.rows.val;
					lastCols = pO.cols.val;
					trace ("row / col change");
				}
			} else { //tunnel	
				randCheck = true;
				if (lastSegments != pO.segments.val) {
					randCheck = false;
					randomA = [];
					randomD = [];
					lastSegments = pO.segments.val;
					trace ("rand change");
				}
			}
					
			var toggleDir:Number = -1;			
			var count:Number;
			var tempLineFill:Number;
			
			var shifters:Array = [[1,2],[1,3],[2,3],[1,2,3]];
			//var shifters:Array = [[6,1],[7,1],[6,2],[7,2],[1,7],[1,8]];
			var shifter:Array = [];
			var cS:Number = 0;
			var shifterCount:Number;		
			if (pO.shape.val >= 9 && pO.shape.val <= 12) { // combinations			
				shifter = shifters[pO.shape.val-9];			
				shifterCount = -1;				
			}
			
			for (i=0; i<layers; i++) { // layers		
				if (shifter.length > 0) {
					shifterCount++;
					cS = shifter[shifterCount%shifter.length];
					//trace ("shifter = "+cS);
				}
				toggleDir *= -1;				
				pattern = new Sprite();
				pattern.cacheAsBitmap = true;				
				pattern.graphics.beginFill(0x000000, shapefill);
				if (pO.line.val > 0) {
					tempLineFill = linefill;
				} else {
					tempLineFill = 0;
				}
				pattern.graphics.lineStyle(pO.line.val, color, tempLineFill, true,"normal",CapsStyle.SQUARE,JointStyle.MITER);	
								
				if (!randCheck) {randomA.push([]); randomD.push([]);}
				count = -1;
				if (pO.tiling.val == 1) { // tiling
					for (j=0; j<rows; j++) {
						for (k=0; k<cols; k++) {
							count++;
							centerX = startX - (cols-1)*spacingX/2 + k*spacingX;
							centerY = startY - (rows-1)*spacingY/2 + j*spacingY;
							if ((pO.shape.val == 1 && cS <= 0) || cS == 1) { // circle			
								for (m=1; m<=6; m++) {
									pattern.graphics.drawCircle(centerX, centerY, smallRadius*pO["mod"+m].val);
								}
							} else if ((pO.shape.val == 2 && cS <= 0) || cS == 2) { // square					
								for (m=1; m<=6; m++) {
									w = smallRadius*pO["mod"+m].val;
									pattern.graphics.drawRect(centerX-w, centerY-w, w*2, w*2);
								}							
							} else if ((pO.shape.val == 3 && cS <= 0) || cS == 3) { // Diamonds					
								for (m=1; m<=6; m++) {
									w = smallRadius*pO["mod"+m].val;																
									r = Math.sqrt(Math.pow(w,2) + Math.pow(w,2));																		
									pattern.graphics.moveTo(centerX,centerY-r);
									pattern.graphics.lineTo(centerX+r,centerY);
									pattern.graphics.lineTo(centerX,centerY+r);
									pattern.graphics.lineTo(centerX-r,centerY);
									pattern.graphics.lineTo(centerX,centerY-r);												
								}
							} else if (pO.shape.val == 4 || pO.shape.val == 5) { // Random					
								for (m=1; m<=6; m++) {
									w = smallRadius*pO["mod"+m].val;
									r = Math.sqrt(Math.pow(w,2) + Math.pow(w,2));
									if (pO.shape.val == 4) {
										if (!randCheck) {										
											if (m==1) {
												a = Math.floor(Math.random()*12)*30;
												randomA[0].push(a);
											} else {
												a = randomA[0][count];
											}
										} else {
											a = randomA[0][count];
										}
									} else if (pO.shape.val == 5) {
										if (!randCheck) {
											if (m==1) {
												a = Math.floor(Math.random()*12)*30;
												randomA[i][count] = a;
											} else {
												a = randomA[i][count];
											}	
										} else {
											a = randomA[i][count];
										}
									}
									dX = Math.sin(a)*r;
									dY = Math.cos(a)*r;
									
									if (pO.shape.val == 5) {
										if (!randCheck) {
											if (m==1) {
												randomD[i][count]=[];										
											}
											if (w>0) {
												dX = Math.round(Math.random()*100);										
												randomD[i][count][m-1]=dX;
											}
										} else {
											if (w>0) {
												if (!randomD[i][count][m-1]) { // catch if no segment change and adding mods
													dX = Math.round(Math.random()*100);
													randomD[i][count][m-1]=dX;
												} else {
													dX = randomD[i][count][m-1];											
												}
											} else {
												randomD[i][count][m-1]=null; // catch if removing mods without segment change
											}
										}
									}									
									pattern.graphics.moveTo(centerX+dY,centerY-dX);
									pattern.graphics.lineTo(centerX+dX,centerY+dY);
									pattern.graphics.lineTo(centerX-dY,centerY+dX);
									pattern.graphics.lineTo(centerX-dX,centerY-dY);
									pattern.graphics.lineTo(centerX+dY,centerY-dX);
								}
							} else if (pO.shape.val == 6) { // elipse			
								for (m=1; m<=3; m++) {											
									pattern.graphics.drawEllipse(centerX-smallRadius*pO["mod"+(m*2-1)].val, centerY-smallRadius*pO["mod"+(m*2)].val, smallRadius*pO["mod"+(m*2-1)].val*2, smallRadius*pO["mod"+(m*2)].val*2);
								}
							} else if (pO.shape.val == 7) { // rectangle					
								for (m=1; m<=3; m++) {											
									pattern.graphics.drawRect(centerX-smallRadius*pO["mod"+(m*2-1)].val, centerY-smallRadius*pO["mod"+(m*2)].val, smallRadius*pO["mod"+(m*2-1)].val*2, smallRadius*pO["mod"+(m*2)].val*2);
								}	
							} else if (pO.shape.val == 8) { // elipse and rectangle					
								for (m=1; m<=3; m++) {
									dir = dir*-1;
									if (dir == 1) {
										pattern.graphics.drawEllipse(centerX-smallRadius*pO["mod"+(m*2-1)].val, centerY-smallRadius*pO["mod"+(m*2)].val, smallRadius*pO["mod"+(m*2-1)].val*2, smallRadius*pO["mod"+(m*2)].val*2);
									} else {
										pattern.graphics.drawRect(centerX-smallRadius*pO["mod"+(m*2-1)].val, centerY-smallRadius*pO["mod"+(m*2)].val, smallRadius*pO["mod"+(m*2-1)].val*2, smallRadius*pO["mod"+(m*2)].val*2);
									}
								}	
							}
						}
					}				
				} else { // tunnel					
					for (j=0; j<360; j+=360/pO.segments.val){			
						count++;
						if ((pO.shape.val == 1 && cS <= 0) || cS == 1) { // circle			
							for (k=1; k<=6; k++) {
								pattern.graphics.drawCircle(startX+Math.sin((j+i*twist)*Math.PI/180)*radius, startY+Math.cos((j+i*twist)*Math.PI/180)*radius, smallRadius*pO["mod"+k].val);
							}
						} else if ((pO.shape.val == 2 && cS <= 0) || cS == 2) { // square					
							for (k=1; k<=6; k++) {
								w = smallRadius*pO["mod"+k].val;
								pattern.graphics.drawRect(startX+Math.sin((j+i*twist)*Math.PI/180)*radius-w, startY+Math.cos((j+i*twist)*Math.PI/180)*radius-w, w*2, w*2);
							}
						} else if (((pO.shape.val == 3 && cS <= 0) || cS == 3) || pO.shape.val == 4 || pO.shape.val == 5) { // rotated square					
							for (k=1; k<=6; k++) {
								w = smallRadius*pO["mod"+k].val;								
								if ((pO.shape.val == 3 && cS <= 0) || cS == 3) {
									a = 90-(j+i*twist);									
								} else if (pO.shape.val == 4) { // repeat random rotation on layers							
									if (!randCheck) {										
										if (k==1) {
											a = Math.floor(Math.random()*12)*30;											
											randomA[0].push(a);
										} else {
											a = randomA[0][count];
										}
									} else {
										a = randomA[0][count];
									}
								} else if (pO.shape.val == 5) { // new random locations on layers	
									if (!randCheck) {
										if (k==1) {
											a = Math.floor(Math.random()*12)*30;
											randomA[i][count] = a;
										} else {
											a = randomA[i][count];
										}	
									} else {
										a = randomA[i][count];
									}
								}
								r = Math.sqrt(Math.pow(w,2) + Math.pow(w,2));
								centerX = startX+Math.sin((j+i*twist)*Math.PI/180)*radius;
								centerY = startY+Math.cos((j+i*twist)*Math.PI/180)*radius;								
								dX = Math.sin((45-a)*Math.PI/180)*r;
								dY = Math.cos(Math.abs((45-a))*Math.PI/180)*r;
								
								if (pO.shape.val == 5) {
									if (!randCheck) {
										if (k==1) {
											randomD[i][count]=[];										
										}
										if (w>0) {
											dX = Math.round(Math.random()*100);										
											randomD[i][count][k-1]=dX;
										}
									} else {
										if (w>0) {
											if (!randomD[i][count][k-1]) { // catch if no segment change and adding mods
												dX = Math.round(Math.random()*100);
												randomD[i][count][k-1]=dX;
											} else {
												dX = randomD[i][count][k-1];											
											}
										} else {
											randomD[i][count][k-1]=null; // catch if removing mods without segment change
										}
									}
								}
								
								
								pattern.graphics.moveTo(centerX+dY,centerY-dX);
								pattern.graphics.lineTo(centerX+dX,centerY+dY);
								pattern.graphics.lineTo(centerX-dY,centerY+dX);
								pattern.graphics.lineTo(centerX-dX,centerY-dY);
								pattern.graphics.lineTo(centerX+dY,centerY-dX);
								
								/*rect = new Sprite();
								rect.cacheAsBitmap = true;
								pattern.addChild(rect);
								rect.graphics.beginFill(0x000000, shapefill);
								//rect.graphics.lineStyle(pO.line.val, color, linefill, true,"normal",CapsStyle.SQUARE,JointStyle.MITER);	
								rect.graphics.drawRect(-w,-w,2*w,2*w);
								rect.x = startX+Math.sin((j+i*twist)*Math.PI/180)*radius;
								rect.y = startY+Math.cos((j+i*twist)*Math.PI/180)*radius;
								trace (j);
								rect.rotation = 90-(j+i*twist);*/
							}								
						} else if (pO.shape.val == 6 || pO.shape.val == 7 || pO.shape.val == 8) { // rays
							
							flip = (pO.shape.val == 7);							
							if (flip) {dir = dir*-1;}			
							if (pO.shape.val == 8) {
								dir = toggleDir;
							}
							ang = j+i*twist;
							
							var amp:Number = radius*2 / pO.mod1.max;
							a = amp*(pO.mod1.val-pO.mod1.max/2)*dir; //30*dir; // x of first control
							b = amp*pO.mod2.val; //60;	// y of first control
							c = amp*(pO.mod3.val-pO.mod3.max/2)*dir; //-60*dir; // x of second control
							d = amp*pO.mod4.val; //100; // y of second control	
							e = .5+pO.mod5.val; // angle between lines
							f = 0; // height of end cap
										
							e1 = radius*2; // radius
							e1W = 2*e1*Math.sin(e/2*Math.PI/180); // chord			
										
							point1 = rotatePoint(new Point(a,b),ang);			
							point2 = rotatePoint(new Point(c,d),ang);
							point3 = rotatePoint(new Point(e1W/2,e1),ang);		
							
							// these smoothen the curve by averaging control points
							// and setting a modified anchor point
							// basically gets the anchor point = intersection of line
							// between control points and radial to ending anchor point
							// and uses this as the mid anchor point
							// works well with enough curve 
							
							e1s = getSlope(point1, point2); // slope of first line
							e1b = point1.y-e1s*(point1.x); // y intercept
							e2s = getSlope(new Point(0,0), point3);
							e2b = point3.y-e2s*point3.x;
							
							intX = (e2b-e1b)/(e1s-e2s); // solve for intersection
							intY = e1s*intX + e1b;
							
							// draw first part of line
							pattern.graphics.moveTo(startX, startY);
							pattern.graphics.curveTo(startX+point1.x,startY+point1.y,startX+intX,startY+intY);
							pattern.graphics.curveTo(startX+point2.x,startY+point2.y,startX+point3.x,startY+point3.y);
							
							pointRem = point3;
							
							// redo for line coming back spaced over by angle
							ang = ang + e;
							point1 = rotatePoint(new Point(a,b),ang);			
							point2 = rotatePoint(new Point(c,d),ang);
							point3 = rotatePoint(new Point(e1W/2,e1),ang);		
							
							point4 = rotatePoint(new Point(0, e1+f), ang+e);
							
							e1s = getSlope(point1, point2);
							e1b = point1.y-e1s*(point1.x);				
							e2s = getSlope(new Point(0,0), point3);
							e2b = point3.y-e2s*point3.x;
							
							intX = (e2b-e1b)/(e1s-e2s);
							intY = e1s*intX + e1b;
							
							pattern.graphics.curveTo(startX+point3.x,startY+point3.y,startX+point4.x,startY+point4.y);			
							pattern.graphics.curveTo(startX+point2.x,startY+point2.y,startX+intX,startY+intY);
							pattern.graphics.curveTo(startX+point1.x,startY+point1.y,startX+0,startY+0);
						}
						
					}				
					if (pO.shape.val == 4) {randCheck = true;}
					if (pO.shape.val == 6 || pO.shape.val == 7 || pO.shape.val == 8) {
						pattern.graphics.endFill();
						if (pO.mod6.val > 0) {
							tempLineFill = shapefill+linefill;
						} else {
							tempLineFill = 0;
						}
						pattern.graphics.lineStyle(pO.mod6.val/2,0x000,tempLineFill);	
						pattern.graphics.drawCircle(startX+0,startY+0,e1);
					}
				}
				pattern.z = -3000 + i * distance;		
				holder.addChild(pattern);				
			}			
			if (pO.shape.val == 4 || pO.shape.val == 5) {
				mySO.data.randomA = randomA;
				mySO.data.randomD = randomD;
			} else {
				mySO.data.randomA = randomA = [];
				mySO.data.randomD = randomD = [];
			}
		}
	
		private function rotatePoint(p:Point,a:Number) {			
			var oldA:Number = Math.PI/2 - Math.atan2(p.y, p.x);			
			var r:Number = Math.sqrt(Math.pow(p.x,2) + Math.pow(p.y,2));
			var newX:Number = Math.sin(oldA+a*Math.PI/180)*r;
			var newY:Number = Math.cos(oldA+a*Math.PI/180)*r;
			return new Point(newX,newY);
		}
			
		private function getSlope(p1:Point, p2:Point) {
			return (p2.y - p1.y) / (p2.x - p1.x);
		}		
		
		private function setList() {	
			pannel2.info.myList.dataProvider = new DataProvider();
			for (var i:uint=0; i<mySO.data.record.length; i++) {
				pannel2.info.myList.addItem({label:mySO.data.record[i][0]});
			}
			pannel2.info.myList.selectedIndex = mySO.data.currentSelection;
		}				
	}
}

package com.danzen.utilities {
	
	// Ticks - by Dan Zen - http://www.danzen.com
	// puts ticks behind the slider so behind the slider knob
	// lets you place ticks above or below slider in y
	// apply like so if a holder MovieClip holds the slider
	// holder.addChildAt(new Ticks(holder.slider, 1, .5, Ticks.POSITION_TOP), holder.getChildIndex(holder.slider));
	
	// to use the class, place the com folder with all its subfolders and files
	// in a folder that is in your class path (Edit > Preferences > ActionScript 3 > Source Path)
	// note: do not add the com folder to the source path
	// but rather, add the folder the com folder is in to your Source Path
	
	import flash.display.Sprite;
	import fl.controls.Slider;	

	public class Ticks extends Sprite {
		
		// s is the slider instance
		// t is the tick interval (default 1)
		// a is the alpha of the tick (default 1)
		// p is the tick placement above or below the slider
		
		public static const POSITION_TOP:String = "position_top";
		public static const POSITION_BOTTOM:String = "position_bottom";
		
		public function Ticks(s:Slider, t:Number=1, a:Number=1, p:String=Ticks.POSITION_TOP) {
			graphics.lineStyle(1, 1, a, true, "normal", "none");
			var sY:Number;
			if (p == Ticks.POSITION_TOP) {
				sY = -4;
			} else {
				sY = 6;
			}
			var h:Number = 2;			
			var min:Number = s.minimum;
			var max:Number = s.maximum;
			var w:Number = s.width;
			var num:Number = Math.floor((max - min) / t);
			var spacing:Number = s.width / num;			
			for (var i:uint=0; i<=num; i++) {
				graphics.moveTo(s.x+spacing*i,s.y+sY);
				graphics.lineTo(s.x+spacing*i,s.y+sY+h);		
			}			
		}
	}	
}


package com.danzen.interfaces {
    
    import flash.display.Sprite;
    import flash.events.*;
	import flash.filters.DropShadowFilter;
	import flash.filters.BitmapFilterQuality
	
	import com.danzen.interfaces.ExitButton;
    
    public class Pane extends Sprite {
		
		public static const EXIT:String = "exit";
		
		private var myW:Number;
		private var myH:Number;
		private var myDrag:Boolean;
		private var myColor:Number;
		private var myAlpha:Number;
		private var myCurve:Boolean;
		private var myBar:Boolean;
		private var myModal:Boolean;
		private var myModalColor:Number;
		private var myModalAlpha:Number;
		
		private var myBack:Sprite;
		private var myFront:Sprite;
		public var myExit:ExitButton;
		
		public var bar:Sprite;
		public var backing:Sprite;
		
	
		public function Pane (
					theW:Number=300,
					theH:Number=200,
					theDrag:Boolean=true,
					theColor:Number=0xFFFFFF,
					theAlpha:Number=1,
					theCurve:Boolean=false,
					theBar:Boolean=false,
					theModal:Boolean=false,
					theModalColor:Number=0xffffff,
					theModalAlpha:Number=.6) {
	
			myW = theW;
			myH = theH;
			myDrag = theDrag;
			myColor = theColor;
			myAlpha = theAlpha;
			myCurve = theCurve;
			myBar = theBar;
			myModal = theModal;
			myModalColor = theModalColor;
			myModalAlpha = theModalAlpha;
			
			trace ("hi from Pane");
			
			myBack = new Sprite();
			myFront = new Sprite();
			
			if (myModal) {
				backing = new Sprite();			
				with (backing.graphics) {
					beginFill(myModalColor, myModalAlpha);				
					drawRect(-2000,-2000,4000,4000);				
				}
				addChild(backing);
			}
			
			var myShapes:Array = [myBack, myFront];
			var temp:Sprite;
			for (var i:uint=0; i < myShapes.length; i++) {
				temp = myShapes[i];
				with (temp.graphics) {
					lineStyle(2, 0x000000, .04);
					if (i==0) {
						beginFill(this.myColor);
					} else {
						beginFill(this.myColor, this.myAlpha);
					}
					var miter:Number = 12;
					if (this.myCurve) {
						moveTo(0,theH);
						lineTo(0,miter);
						curveTo(0,0,miter,0);
						lineTo(this.myW-miter,0);
						curveTo(this.myW,0,this.myW,miter);
						lineTo(this.myW,this.myH);						
					} else {					
						drawRect(0,0,this.myW,this.myH);
					}
				}
				addChild(temp);
			}
			myBack.filters = [new DropShadowFilter(10, 45, 0x666666, 1, 17, 17, .7, BitmapFilterQuality.HIGH, false, true, false)];		
			
			
			bar = new Sprite();
			var barHeight = 34;
			with (bar.graphics) {
				beginFill(0, .2);
				if (this.myCurve) {
					moveTo(0,barHeight);
					lineTo(0,miter);
					curveTo(0,0,miter,0);
					lineTo(this.myW-miter,0);
					curveTo(this.myW,0,this.myW,miter);
					lineTo(this.myW,barHeight);						
				} else {					
					drawRect(0,0,this.myW,barHeight);
				}
			}
			addChild(bar);

			if (myDrag) {
				bar.buttonMode = true;
				bar.addEventListener(MouseEvent.MOUSE_DOWN, dragWindow);	
			}

			if (myBar) {bar.alpha = 1;} else {bar.alpha = 0;}
			
			myExit = new ExitButton(16);
			var spacing:Number = 10;
			myExit.x = myW - spacing - myExit.width;
			myExit.y = spacing;
			myExit.alpha = .6;
			addChild(myExit);
			myExit.addEventListener(MouseEvent.CLICK, exitClick);			
			
						
			
		}	

		private function dragWindow(e:MouseEvent) {
			this.startDrag()
			stage.addEventListener(MouseEvent.MOUSE_UP, dropWindow);
		}
		
		private function dropWindow(e:MouseEvent) {
			this.stopDrag()
			stage.removeEventListener(MouseEvent.MOUSE_UP, dropWindow);
		}				

		private function exitClick(e:MouseEvent) {
			dispatchEvent(new Event(Pane.EXIT));
		}

		public function dispose() {
			if (myDrag) {
				bar.removeEventListener(MouseEvent.MOUSE_DOWN, dragWindow);	
			}
			myExit.removeEventListener(MouseEvent.CLICK, exitClick);
			myExit.dispose();
		}
        
    }
    
}