flash on 2013-7-26

by CatHobo
♥0 | Line 1204 | Modified 2013-09-16 21:02:37 | MIT License
play

ActionScript3 source code

/**
 * Copyright CatHobo ( http://wonderfl.net/user/CatHobo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hwez
 */

package {
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.system.System;
    import net.hires.debug.Stats;
    import org.si.sion.SiONDriver;
    import org.si.sion.SiONVoice;
    import org.si.sion.utils.SiONPresetVoice;
    public class Main extends Sprite{
        /*private static var stage:Stage;
        public static function get GetStage():Stage{
            return Main.stage;
        }*/
        
        
        
        
        
        
        
        
        
        
        
        
        
        public function Main():void {
            //Main.stage=this.stage;
            this.addChild(new Stats());
            //C.INIT();
            //Console.ClearAndPrint=true;
            Console.ScrollToEnd=true;
            //Console.HideConsole=true;
            //this.stage.frameRate=30;
            this.stage.quality="low";
            var i:int;
            for(i=0;i<Keyboard.NUM_KEYS;i++){
                if(!Keyboard.IsBlackKey(i)){
                    this.addChild(new PianoKey(i));
                }
            }
            for(i=0;i<Keyboard.NUM_KEYS;i++){
                if(Keyboard.IsBlackKey(i)){
                    this.addChild(new PianoKey(i));
                }
            } //White keys first, then black keys over white keys.
            this.addEventListener(Event.ENTER_FRAME,ContinuousPrint);
            this.stage.addEventListener(
            MouseEvent.MOUSE_DOWN,AddPianoKeyHandlers);
            this.stage.addEventListener(
            MouseEvent.MOUSE_UP,RemovePianoKeyHandlers);
            s_driver.play();
            this.addChild(scroll_gui
            =new CustomScrollGUI(0,200+Keyboard.KEY_HEIGHT
            ,this.stage.stageWidth
            ,this.stage.stageHeight-Keyboard.KEY_HEIGHT-200-10));
            some_sprite=new Sprite();
            some_sprite.graphics.lineStyle(2,0x000000);
            some_sprite.graphics.beginFill(0xFFFFFF);
            some_sprite.graphics.drawRect(
            0,0,Keyboard.WHITE_WIDTH,400);
            scroll_gui.AddDisplayObject(
            some_sprite,100,scroll_gui.height+200);
            note_detector.y=scroll_gui.y+3;
            this.addChild(note_detector);
            Console.TraceVariable(null
            ,function():Boolean{
                return note_detector.hitTestObject(some_sprite);
            },"touching");
            //Console.Print(some_sprite.getBounds(scroll_gui.ContentsToSee));
            //Console.Print(scroll_gui.GetContentScrollRect());
            new NoteLength(1,8);
            new NoteOctave(1,6);
            new NoteOctaveDown(1);
            new MusicalNote(1,"c");
            new MusicalNote(1,"g");
            new MusicalNote(1,"f+");
            new MusicalNote(1,"g");
            new MusicalNote(1,"d");
            new MusicalNote(1,"b-");
            new MusicalNote(1,"a");
            new MusicalNote(1,"b-");
            new MusicalNote(1,"e");
            new MusicalNote(1,"g");
            new MusicalNote(1,"f+");
            new MusicalNote(1,"g");
            Console.Print(MMLProperty.GetMMLString(1));
            note_detector.addEventListener(Event.EXIT_FRAME,DetectNotes);
            Console.INIT(this);
            
            this.stage.addEventListener(
            MouseEvent.CLICK,ClickGUI);
        } 
        
        private function ClickGUI(e:MouseEvent):void{
            Console.Print(e.target);
        }

        private function DetectNotes(e:Event):void{
            for(var i:int=0;i<scroll_gui.ContentsToSee.numChildren;i++){
                var musical_note_obj:MusicalNote
                =(scroll_gui.ContentsToSee.getChildAt(i) as MusicalNote);
                if(musical_note_obj){
                    if(note_detector.hitTestObject(musical_note_obj)){
                        if(!musical_note_obj.TouchingNote){
                            s_driver.noteOn(musical_note_obj.NoteID,s_voice)
                            musical_note_obj.TouchingNote=true;
                        } //Driver note on once when touched.
                    }else{
                        if(musical_note_obj.TouchingNote){
                            s_driver.noteOff(musical_note_obj.NoteID);
                            musical_note_obj.TouchingNote=false;
                        } //Also turn note off once.
                    }
                }
            }
        }
        
        private var some_sprite:Sprite;
        private var note_detector:Sprite=(function():Sprite{
            var spr:Sprite=new Sprite();
            spr.graphics.lineStyle(2,0xFFFFFF);
            spr.graphics.drawRect(0,0,Keyboard.STAGE_WIDTH,0);
            return spr;
        })();
        public static var scroll_gui:CustomScrollGUI;
        private var s_driver:SiONDriver=new SiONDriver();
        private var s_preset_voice:SiONPresetVoice=new SiONPresetVoice();
        private var s_voice:SiONVoice=s_preset_voice["valsound.piano1"];
        private function AddPianoKeyHandlers(e:MouseEvent):void{
            this.stage.addEventListener(
            MouseEvent.MOUSE_OVER,PianoKeyON);
            this.stage.addEventListener(
            MouseEvent.MOUSE_OUT,PianoKeyOFF);
            PianoKeyON(e); //If initially clicked a note...
        }
        private function RemovePianoKeyHandlers(e:MouseEvent):void{
            this.stage.removeEventListener(
            MouseEvent.MOUSE_OVER,PianoKeyON);
            this.stage.removeEventListener(
            MouseEvent.MOUSE_OUT,PianoKeyOFF);
            PianoKeyOFF(e); //If letting go a note...
        }
        public function PianoKeyON(e:Event):void{
            if(e.target is PianoKey){
                s_driver.noteOn(e.target.NoteID,s_voice);
                e.target.IsBlackKey
                ?e.target.MakeBlackKeyPressed()
                :e.target.MakeWhiteKeyPressed();
                Console.Print("Key ON.","NoteID: "+e.target.NoteID);
                Console.Print("Octave: "+e.target.OctaveNum," ");
                //new MusicalNote(e.target.NoteID,1);
            }
        }
        public function PianoKeyOFF(e:Event):void{
            if(e.target is PianoKey){
                s_driver.noteOff(e.target.NoteID);
                e.target.IsBlackKey
                ?e.target.MakeBlackKeyReleased()
                :e.target.MakeWhiteKeyReleased();
                Console.Print("Key OFF.","NoteID: "+e.target.NoteID);
                Console.Print("Octave: "+e.target.OctaveNum," ");
            }
        } 
        private function ContinuousPrint(e:Event):void{
            Console.PrintTracedVariables();
        }
    }
}


import flash.display.Sprite;
import flash.display.Stage;
import flash.display.DisplayObject;
import flash.geom.Rectangle;
import flash.events.Event;
import flash.events.MouseEvent;
final class CustomScrollGUI extends Sprite{
    private var V_ScrollInner:Sprite=new Sprite();
    private var V_ScrollOuter:Sprite=new Sprite();
    public var ContentsToSee:Sprite=new Sprite();
    private var ContentsRect:Rectangle=new Rectangle();
    private var ContentScrollRect:Rectangle=new Rectangle();
    public static const BAR_LENGTH:int=20;
    private static const SCROLL_TO_END_IF_UPDATED:Boolean=false;
    public function AddDisplayObject(obj:DisplayObject
    ,to_x:Number=0,to_y:Number=0):void{
        obj.x=to_x;
        obj.y=to_y;
        ContentsToSee.addChild(obj);
        Update();
    }//Custom "addChild" for the scrollbar.
    public function GetContentScrollRect():Rectangle{
        return ContentScrollRect.clone();
    }
    private function GetContentBounds():Rectangle{
        var init_rectangle:Rectangle=new Rectangle();
        for(var i:int=0;i<ContentsToSee.numChildren;i++){
            init_rectangle=init_rectangle.union(
                ContentsToSee.getChildAt(i).getRect(ContentsToSee)
            ); //Get the largest rectangle for all children
            //in the contents of the scrollbar.
        }
        init_rectangle=init_rectangle.union(
        new Rectangle(0,0,init_rectangle.width,init_rectangle.height));
        //Also get rectangle bounds from point (0,0) of the rectangle.
        return init_rectangle;
    }
    public function Update():void{
        var LargestRectangle:Rectangle=GetContentBounds();
        ContentsRect.height=LargestRectangle.height;
        ContentsRect.width=LargestRectangle.width; 
        //Update ScrollRect for the scrollbar to work properly.
        if(LargestRectangle.height>ContentScrollRect.height){
            with(V_ScrollOuter.graphics){
                clear(); //Clear to redraw properly.
                lineStyle(2,0x000000);
                beginFill(0xFFFFFF);
                drawRoundRect(0,0
                ,BAR_LENGTH,
                V_ScrollInner.height
                *ContentScrollRect.height/LargestRectangle.height
                ,20,20);
            }
            V_ScrollInner.visible=true;
        }else{
            V_ScrollInner.visible=false;
        } //Show scrollbar if content height is bigger than mask.
        //by redrawing with the ratio of mask height to content height.
        CheckV_ScrollOutOfBounds();
    }
    private function CheckV_ScrollOutOfBounds():void{
        /*Console.Print(GetContentBounds(),ContentScrollRect,
        GetContentBounds().height-ContentScrollRect.height,
        GetContentBounds().height>ContentScrollRect.height,
        GetContentBounds().height-ContentScrollRect.height
        <ContentScrollRect.y+0.2," ");*/
        if(GetContentBounds().height>ContentScrollRect.height){
            if(GetContentBounds().height-ContentScrollRect.height
            <ContentScrollRect.y+0.2){
                V_ScrollTo(GetScrollVSpace);
                //Automatically change scrollbar and
                //contents positions if using backspace.
            }else{
                if(SCROLL_TO_END_IF_UPDATED){
                    V_ScrollTo(GetScrollVSpace); 
                }
            }
        }else{
            V_ScrollTo(0);
            //If cutting a whole textfield, 
            //scroll back up to 0.
        } 
        ContentScrollV();
    }
    public function CustomScrollGUI(init_x:Number,init_y:Number,
    init_width:Number,init_height:Number):void{
        x=init_x;
        y=init_y;
        with(graphics){
            lineStyle(2,0x000000);
            beginFill(0x9F9FFF);
            drawRect(0,0,init_width,init_height);
        }
        with(V_ScrollInner){
            x=init_width-BAR_LENGTH-2;
            y=2;
            with(graphics){
                lineStyle(2,0x000000);
                beginFill(0xBFBFBF);
                drawRoundRect(0,0,BAR_LENGTH,init_height-4,20,20);
            }
        }
        V_ScrollInnerHeight=V_ScrollInner.height;
        V_ScrollInner.visible=false;
        this.addChild(V_ScrollInner);
        with(V_ScrollOuter){
            buttonMode=true;
            with(graphics){
                lineStyle(2,0x000000);
                beginFill(0xFFFFFF);
                drawRoundRect(0,0,BAR_LENGTH,init_height-BAR_LENGTH,20,20);
            }
        }
        V_ScrollInner.addChild(V_ScrollOuter);
        with(ContentScrollRect){
            width=this.width-4;
            height=this.height-4;
        }
        ContentsToSee.scrollRect=ContentScrollRect;
        //Used to scroll the contents with the scrollbars.
        ContentsToSee.cacheAsBitmap=true;
        this.addChild(ContentsToSee);
        this.addEventListener(Event.ADDED_TO_STAGE,AddEventListeners);
        //After "this" is added by addChild, this.root.stage is accessible.
    }
    private function AddEventListeners(e:Event):void{
        V_ScrollInner.addEventListener(MouseEvent.MOUSE_DOWN,V_ScrollByInner);
        this.root.stage.addEventListener(
        MouseEvent.MOUSE_UP,V_ScrollByOuterRemove);
        //Remove scrolling anywhere when mouse is up in the stage.       
    }
    private var V_ScrollInnerHeight:Number;
    //Since V_ScrollOuter is a child, of V_ScrollInner
    //would change the height. This is to preserve that.
    private function get GetScrollVSpace():Number{
        return V_ScrollInnerHeight-V_ScrollOuter.height;
    } //Magic number to get the number by the difference of V_Scroll bars.
    private function V_ScrollTo(to_y:Number):void{
        var GetScrollVSpace:Number=this.GetScrollVSpace;
        if(to_y<=GetScrollVSpace&&to_y>=0){
            V_ScrollOuter.y=to_y;
        }else if(to_y>GetScrollVSpace){
            V_ScrollOuter.y=GetScrollVSpace;
        }else if(to_y<0){
            V_ScrollOuter.y=0;
        }//Scroll inside the boundaries of ScrollBarInner.
    }
    private function ContentScrollV():void{
        /*ContentScrollRect.y=(GetScrollVSpace!=0)
        ?(ContentsRect.height-ContentScrollRect.height)
        *V_ScrollOuter.y/GetScrollVSpace
        :(0); //No 0 division.*/
        ContentScrollRect.y=(GetScrollVSpace!=0)
        ?(ContentsRect.height+20)
        *V_ScrollOuter.y/GetScrollVSpace
        :(0);
         //Make content "not appear" at end of scroll
         //using only ContentsRect.height.
        ContentsToSee.scrollRect=ContentScrollRect;
        //Change scrolling positions using maths.
    }
    private function V_ScrollByInner(e:MouseEvent):void{
        var GetDisp:DisplayObject=V_ScrollOuter;
        var GetLocal_y:Number=0;
        while(!(GetDisp is Stage)){
            GetDisp=GetDisp.parent;
            GetLocal_y+=GetDisp.y;            
        }//If GUI is nested inside display objects,
        //add all of the y-offsets for the scroll
        //to properly get the local y with respect to V_ScrollInner
        //using e.stageY-GetLocal_y.
//Console.Print(V_ScrollInner.globalToLocal(new Point(0,e.stageY)).y);
        V_ScrollTo(e.stageY-GetLocal_y-V_ScrollOuter.height/2);
        //Scroll in the middle of the mouse y position.
        ContentScrollV(); //Scroll the content vertically.
        this.root.stage.addEventListener(
        MouseEvent.MOUSE_MOVE,V_ScrollByInner);
    }
    private function V_ScrollByOuterRemove(e:MouseEvent):void{
        this.root.stage.removeEventListener(
        MouseEvent.MOUSE_MOVE,V_ScrollByInner);
    }    
}
final class Keyboard{
    //Static class for constants/functions.
    public static const STAGE_WIDTH:int=465-CustomScrollGUI.BAR_LENGTH;
    public static const STAGE_HEIGHT:int=465;
    //Not sure how to access stage without explicitly making it.
    public static const NUM_OCTAVES:int=8;
    public static const KEY_HEIGHT:Number=50;
    
    //Constants created using constants above.
    public static const NUM_KEYS:int=12*NUM_OCTAVES;
    public static const NUM_WHITE_KEYS:int=(function():int{
        var num_white_keys:int=0;
        for(var key:int=0;key<NUM_KEYS;key++){
            switch(key%12){
                case 1:
                case 3:
                case 6:
                case 8:
                case 10:
                    break;
                default:
                    num_white_keys++;
            }
        }
        return num_white_keys;
    })(); //Initialize NUM_WHITE_KEYS constant in anonymous function.
    public static const WHITE_WIDTH:Number
    =STAGE_WIDTH/NUM_WHITE_KEYS;
    public static const BLACK_WIDTH:Number
    =STAGE_WIDTH/NUM_WHITE_KEYS/1.9;
    public static const TWELVE_KEY_LENGTH:Number
    =STAGE_WIDTH/int(NUM_WHITE_KEYS/7);
    public static function ToKeyPosition(p:PianoInterface):void{
        p.x=0; //Reset when called again.
        p.x+=TWELVE_KEY_LENGTH*(p.OctaveNum-1);
        if(IsBlackKey(p.NoteID)){
            p.x+=3*WHITE_WIDTH/4; //If black key, move.
        }
        switch(p.NoteID%12){
            case 11:
                p.x+=WHITE_WIDTH;
            case 10:
            case 9:
                p.x+=WHITE_WIDTH;
            case 8:
            case 7:
                p.x+=WHITE_WIDTH;
            case 6:
            case 5:
                p.x+=WHITE_WIDTH;
            case 4:
                p.x+=WHITE_WIDTH;
            case 3:
            case 2:
                p.x+=WHITE_WIDTH;
        } //Increase x depending upon octave (except "C" notes).
    }
    public static function IsBlackKey(note_id:int):Boolean{
        switch(note_id%12){
            case 1:
            case 3:
            case 6:
            case 8:
            case 10:
                return true;
        }
        return false;
    }
    public static function PianoKeyToNoteID(
    key:String,octave:int):int{
        octave--;
        if(key.search(/[A-Ga-g][\+\-]?/)==0 && key.length<=2
        && octave>=0 && octave<NUM_OCTAVES){
            var key_number:int;
            switch(key.charAt(0)){
                case "C": case "c": key_number=0; break;
                case "D": case "d": key_number=2; break;
                case "E": case "e": key_number=4; break;
                case "F": case "f": key_number=5; break;
                case "G": case "g": key_number=7; break;
                case "A": case "a": key_number=9; break;
                case "B": case "b": key_number=11;
            }
            switch(key.charAt(1)){
                case "+":
                    key_number++;
                    break;
                case "-":
                    key_number--;
            }
            key_number+=octave*12;
            if(key_number<0||key_number>=NUM_KEYS){
                throw new Error("Key "+key+" at octave "
                +String(octave+1)+" out of range.");
            }
        }else{
            throw new Error("Invalid piano key string or octave out of range.");
        }
        return key_number;
    }
}
interface PianoInterface{
    function get x():Number;
    function set x(to_this_x:Number):void;
    function get NoteID():int;
    function get OctaveNum():int;
}
import flash.display.Sprite;
final class PianoKey extends Sprite implements PianoInterface{
    private var _NoteID:int;
    public function get NoteID():int{
        return _NoteID;
    }
    public function get OctaveNum():int{
        return int(_NoteID/12)+1;
    }
    private var _IsBlackKey:Boolean;
    public function get IsBlackKey():Boolean{
        return _IsBlackKey;
    }
    public function PianoKey(note_id:int){
        this.y=200;
        this.buttonMode=true;
        _NoteID=note_id;
        _IsBlackKey=Keyboard.IsBlackKey(note_id);
        if(_IsBlackKey){
            MakeBlackKeyReleased();
        }else{
            MakeWhiteKeyReleased();
        }
        Keyboard.ToKeyPosition(this);
    }
    //Graphic changes below used in Events.
    public function MakeWhiteKeyReleased():void{
        this.graphics.lineStyle(1,0x000000);
        this.graphics.beginFill(0xFFFFFF);
        this.graphics.drawRect(
        0,0,Keyboard.WHITE_WIDTH,Keyboard.KEY_HEIGHT);
    }
    public function MakeWhiteKeyPressed():void{
        this.graphics.lineStyle(1,0x000000);
        this.graphics.beginFill(0xBFBFBF);
        this.graphics.drawRect(
        0,0,Keyboard.WHITE_WIDTH,Keyboard.KEY_HEIGHT);
    }
    public function MakeBlackKeyReleased():void{
        this.graphics.lineStyle(1,0x000000);
        this.graphics.beginFill(0x000000);
        this.graphics.drawRect(
        0,0,Keyboard.BLACK_WIDTH,Keyboard.KEY_HEIGHT/2);
    }
    public function MakeBlackKeyPressed():void{
        this.graphics.lineStyle(1,0x000000);
        this.graphics.beginFill(0x7F7F7F);
        this.graphics.drawRect(
        0,0,Keyboard.BLACK_WIDTH,Keyboard.KEY_HEIGHT/2);
    }
}
import flash.display.Sprite;
class MMLProperty extends Sprite{
    private static var TotalCreated:int=0;
    protected var _ID:int;
    public function get ID():int{
        return _ID;
    }
    
    public function MMLProperty(channel:int):void{
        _ID=++TotalCreated;
        this.name=String(_ID); //To search with ID name.
        _AtChannel=channel;
        try{
            MMLProperty["Channel_"+channel+"_Notes"].push(_ID);
        }catch(e:Error){
            Console.Print("Channel error.");
        }
        Main.scroll_gui.ContentsToSee.addChild(this);
        this.buttonMode=true;
    }
    public static const WHOLE_NOTE_LENGTH:int=400;
    public static function get INIT_POSITION():Number{
        return Main.scroll_gui.GetContentScrollRect().height;
    }
    public static const INIT_MML_LENGTH:int=4;
    public static const INIT_OCTAVE:int=4;
    
    
    protected static var NoteColor:uint;
    //Temporary storage color as protected static.
    protected static var Channel_1_Notes:Vector.<int>
    =new Vector.<int>();
    protected static var Channel_2_Notes:Vector.<int>
    =new Vector.<int>();
    protected static var Channel_3_Notes:Vector.<int>
    =new Vector.<int>();
    protected static var Channel_4_Notes:Vector.<int>
    =new Vector.<int>();
    protected static var Channel_5_Notes:Vector.<int>
    =new Vector.<int>();
    protected static var Channel_6_Notes:Vector.<int>
    =new Vector.<int>();
    
    protected var _MML_Length:uint;
    public function get MML_Length():uint{
        return _MML_Length;
    }
    public function set MML_Length(to_this:uint):void{
        _MML_Length=(to_this!=0?to_this:1);
    } //_MML_Length getter/setter used for polymorphism.
    protected var _AtChannel:int;
    public function get AtChannel():int{
        return _AtChannel;
    }
    protected static function SetNoteLengthByPreviousNoteLength(
    self:MMLProperty):void{
        var UseArray:Vector.<int>
        =MMLProperty["Channel_"+self._AtChannel+"_Notes"];
        var self_i:int=UseArray.indexOf(self._ID);
        for(var i:int=self_i-1;i>=0;i--){
            /*Console.Print(Main.scroll_gui.ContentsToSee
            .getChildByName(String(UseArray[i])));*/
            if(
            Main.scroll_gui.ContentsToSee
            .getChildByName(String(UseArray[i])) is NoteLength){
                self._MML_Length
                =(Main.scroll_gui.ContentsToSee
                .getChildByName(String(UseArray[i]))
                as MMLProperty)._MML_Length;
                return;
            }
        }
        self._MML_Length=INIT_MML_LENGTH;
        //If detecting a NoteLength object, set MML_Length
        //to that length, otherwise, set it to 1/4.
    }
    protected static function SetYPosition(
    self:MMLProperty):void{
        var UseArray:Vector.<int>
        =MMLProperty["Channel_"+self._AtChannel+"_Notes"];
        var self_i:int=UseArray.indexOf(self._ID);
        self.y=MMLProperty.INIT_POSITION;
        for(var i:int=self_i-1;i>=0;i--){
            try{
                self.y+=(Main.scroll_gui.ContentsToSee
                .getChildByName(String(UseArray[i]))
                as MeasurableInterface).height;
                /*Console.Print((Main.scroll_gui.ContentsToSee
                .getChildByName(String(UseArray[i]))
                as MeasurableInterface).height);*/
            }catch(E:Error){
            }
        } //Add previous MusicProperty object with
        //MeasurableInterface's heights.
        /*Console.Print(" ");*/
    }
    protected static function SetPreviousOctave(
    self:OctaveInterface):int{
        var UseArray:Vector.<int>
        =MMLProperty["Channel_"+self.AtChannel+"_Notes"];
        var self_i:int=UseArray.indexOf(self.ID);
        for(var i:int=self_i-1;i>=0;i--){
            try{
                self.OctaveNum=(Main.scroll_gui.ContentsToSee
                .getChildByName(String(UseArray[i]))
                as OctaveInterface).OctaveNum;
                return self.OctaveNum;
            }catch(E:Error){
            }
        }
        self.OctaveNum=INIT_OCTAVE;
        return self.OctaveNum;
        //Set to previous octave, or set to initial octave (4).
    }
    public function get Value():String{
        throw new Error("Abstract method.");
        return "";
    } //Polymorphic method will be overridden below creating mml syntax
    //such as o2,>,<,l8,a+2...
    public static function GetMMLString(channel:int):String{
        var mml_string:String="";
        var UseArray:Vector.<int>
        =MMLProperty["Channel_"+channel+"_Notes"];
        for(var i:int=0;i<UseArray.length;i++){
            try{
                mml_string+=(Main.scroll_gui.ContentsToSee
                .getChildByName(String(UseArray[i]))
                as MMLProperty).Value;
            }catch(E:Error){
                Console.Print(i);
            }
        }
        return mml_string;
    }
}
interface MeasurableInterface{
    function get height():Number;
}
interface OctaveInterface{
    function get ID():int;
    function get AtChannel():int;
    function get OctaveNum():int;
    function set OctaveNum(o:int):void;
}
import flash.display.Sprite;
final class MusicalNote extends MMLProperty
implements PianoInterface,MeasurableInterface,OctaveInterface{
    /*
    public function MusicalNote(
    note_id:int,channel:int,mml_length:uint=0):void{
        super(channel);
        Main.scroll_gui.ContentsToSee.addChild(this);
        //this.y=MusicProperty.INIT_POSITION;
        SetYPosition(this);
        MML_Length=mml_length;
        SetNoteID(note_id);
    }
    */
    public function MusicalNote(
    channel:int,key:String,mml_length:int=0,is_dotted:Boolean=false):void{
        super(channel);
        _Key=key;
        SetYPosition(this);
        SetPreviousOctave(this);
        MML_Length=mml_length;
    }
    override public function get Value():String{
        return _Key+(!UsingPreviousLength?String(_MML_Length):"");
    }
    private var _Key:String;
    public function set Key(key:String):void{
        SetNoteID(Keyboard.PianoKeyToNoteID(key,OctaveNum));
        _Key=key;
    }
    public function get Key():String{
        return _Key;
    }
    private var _NoteID:int;
    public function get NoteID():int{
        return _NoteID;
    }
    public function set OctaveNum(o:int):void{
        SetNoteID(Keyboard.PianoKeyToNoteID(_Key,o));
    }
    public function get OctaveNum():int{
        return int(_NoteID/12)+1;
    }
    public function SetNoteID(note_id:int):void{
        _NoteID=note_id;
        NoteColor=Keyboard.IsBlackKey(note_id)
        ?0x000000:0xFFFFFF;
        DrawGraphics(); //Draw/redraw.
    } 
    private function DrawGraphics():void{
        this.graphics.clear();
        if(Keyboard.IsBlackKey(_NoteID)){
            MakeBlackNote();
        }else{
            MakeWhiteNote();
        }
        Keyboard.ToKeyPosition(this);
        Main.scroll_gui.Update();
    }
    public var TouchingNote:Boolean=false;
    //To turn SiON driver on/off once.
    private var UsingPreviousLength:Boolean=false;
    //To print out the proper string, such as "a+5" or just "a+".
    override public function set MML_Length(to_this:uint):void{
        if(to_this!=0){
            _MML_Length=to_this;
            UsingPreviousLength=false;
        }else{
            SetNoteLengthByPreviousNoteLength(this);
            UsingPreviousLength=true;
        } 
        DrawGraphics(); //Draw/redraw.
    }  
    private function MakeWhiteNote():void{
        this.graphics.beginFill(NoteColor);
        this.graphics.drawRoundRect(
        0,0,Keyboard.WHITE_WIDTH
        ,WHOLE_NOTE_LENGTH/_MML_Length,20,20);
    }
    private function MakeBlackNote():void{
        this.graphics.beginFill(NoteColor);
        this.graphics.drawRoundRect(
        0,0,Keyboard.BLACK_WIDTH
        ,WHOLE_NOTE_LENGTH/_MML_Length,20,20);
    }
}
import flash.display.Sprite;
final class RestNote extends MMLProperty
implements MeasurableInterface{
    public function RestNote(channel:int,mml_length:uint=0):void{
        super(channel);
        MML_Length=mml_length;
    } 
    override public function get Value():String{
        return "r"+(!UsingPreviousLength?String(_MML_Length):"");
    }
    private var UsingPreviousLength:Boolean=false;
    override public function set MML_Length(to_this:uint):void{
        if(to_this!=0){
            _MML_Length=to_this;
            UsingPreviousLength=false;
        }else{
            SetNoteLengthByPreviousNoteLength(this);
            UsingPreviousLength=true;
        }
    }
    override public function get height():Number{
        return WHOLE_NOTE_LENGTH/_MML_Length;
    } //Get "rest height" without drawing graphics.
}  
import flash.display.Sprite;
final class NoteLength extends MMLProperty{
    public function NoteLength(channel:int,mml_length:uint):void{
        super(channel);
        MML_Length=mml_length; //Call setter function for boundaries.
    }
    override public function get Value():String{
        return "l"+String(_MML_Length);
    }
    override public function set MML_Length(to_this:uint):void{
        if(to_this==0){
            throw new Error("Length error.")
        }
        _MML_Length=to_this;
    }
}
import flash.display.Sprite;
class NoteOctave extends MMLProperty
implements OctaveInterface{
    public function NoteOctave(channel:int,octave:int=1):void{
        super(channel);
        _OctaveNum=octave;
    }
    override public function get Value():String{
        return "o"+String(_OctaveNum);
    }
    protected var _OctaveNum:int;
    public function set OctaveNum(o:int):void{
        if(o>0 && o<=Keyboard.NUM_OCTAVES){
            _OctaveNum=o;
        }else{
            throw new Error("Invalid octave number.");
        }
    }
    public function get OctaveNum():int{
        return _OctaveNum;
    }
}
import flash.display.Sprite;
final class NoteOctaveUp extends NoteOctave
implements OctaveInterface{
    public function NoteOctaveUp(channel:int):void{
        super(channel);
        SetPreviousOctave(this);
    }
    override public function get Value():String{
        return ">";
    }
    override public function get OctaveNum():int{
        return _OctaveNum+1;
    }
}
import flash.display.Sprite;
final class NoteOctaveDown extends NoteOctave
implements OctaveInterface{
    public function NoteOctaveDown(channel:int):void{
        super(channel);
        SetPreviousOctave(this);
    }
    override public function get Value():String{
        return "<";
    }
    override public function get OctaveNum():int{
        return _OctaveNum-1;
    }
}



















import flash.utils.Dictionary;
final class WeakRefCalls{
    private var WeakDict:Dictionary=new Dictionary(true);
        //Weak keys will be deleted by garbage collection.
    public function AddFunction(obj_ref:Object,
    getter_function:Function,var_name:String="Name N/A"):void{
        if(!WeakDict[obj_ref]){
            WeakDict[obj_ref]=new Dictionary(); //No weak keys.
            
        }
        WeakDict[obj_ref][getter_function]=var_name;
    }
    
    /*public function DeleteFunction(obj_ref:Object,
    getter_function:Function):Boolean{
        //Anonymous functions can't be deleted however.
        for(var obj_item:Object in WeakDict){
            if(obj_ref==obj_item){
                for(var func_obj:Object in WeakDict[obj_ref]){
                  
                    if(getter_function==func_obj){
                       delete WeakDict[obj_ref][getter_function];
                       return true;
                    }
                }
            }
        }
        return false;
    }*/
    public function get GetLog():String{
        var StringOutput:String="";
        for(var obj_ref:Object in WeakDict){
            StringOutput+=
            "Tracing object toString()=\""+obj_ref+"\"\n";
            for(var setter_func:Object in WeakDict[obj_ref]){
                try{
                StringOutput+="\t\t"
                +WeakDict[obj_ref][setter_func]+" = "
                +setter_func()+"\n"
                
                }catch(E:Error){
                    delete WeakDict[obj_ref];
                        //Delete if object is set to null.
                }
            }
        }
        return StringOutput;
        
    }
    /*public function get GetDictionary():Dictionary{
        var Clone:Dictionary=new Dictionary(true);
        for(var obj_ref:Object in WeakDict){
            Clone[obj_ref]=WeakDict[obj_ref];
        }
        return Clone;
    }*/ //Clones dictionary to pass by value.
}


import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.display.Sprite;
import flash.events.MouseEvent;
final class WordBalloon extends Sprite{
    //For the Console static class that can make it "talk".
    private var T:TextField=new TextField();
    private var T_Format:TextFormat=new TextFormat();
    
    public function WordBalloon(
    Message:String,
    init_x:Number=200,init_y:Number=200,
    max_width:Number=250):void{
        x=init_x;
        y=init_y;
        T.autoSize=TextFieldAutoSize.RIGHT;
        T.wordWrap=true;
        T.multiline=true;
        T.text=Message;
        T.width=max_width;
        T.width=T.textWidth+5;
            //Using these two T.width assignments,
            //the word balloon can resize "appropriately".
        addChild(T); //Word balloon container for T.
        cacheAsBitmap=true;
        with(this.graphics){
            lineStyle(1.5,0x000000,0.5);
            beginFill(0xFFFFFF,0.7);
            drawEllipse(-T.textWidth/2/4,-T.textHeight/2/2
            ,T.width+T.textWidth/4,T.height+T.textHeight/2);
        }
        this.addEventListener(MouseEvent.MOUSE_OVER,MakeInvisible);
        //Roll over balloon to make it disappear.
    }
    private function MakeInvisible(e:MouseEvent):void{
        T.visible=false;
        this.visible=false;
        this.removeEventListener(MouseEvent.MOUSE_OVER,MakeInvisible);
    }
}

import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.geom.Point;
import flash.geom.ColorTransform;
final class Console{
/////////////////////All public/shared static methods/////////////////////
    public static function ClearText():void{
        T.text="";
            //Probably might implement something whether
            //the T textfield might get too big.
        ResizeScrollBar();
    }
    public static function Print(...Objects):void{
        if(_ClearAndPrint){return;}
            //Disable Clear and Print first.
        if(T.numLines>=MaxNumLines){ClearText();}
        T.appendText(Objects.join("\n")+"\n");
        ResizeScrollBar();
        if(_ScrollToEnd){
            SetScrollBarAndScrollV(GetMaxScroll_y);
            //When console is printing, this button can 
            //automatically scroll to the end to see the last line.
        }else{
            SetScrollBarOffset();
            //To make sure scrollbar can scroll
            //not at the beginning using T.scrollV
        }
        UpdateTextLineMeter();
    }
    public static function PrintTracedVariables():void{
        if(!_ClearAndPrint){return;}
            //Enable Clear and Print first.
        T.text=TraceDictionary.GetLog;
        ResizeScrollBar();
        SetScrollBarOffset();
        UpdateTextLineMeter();
    }
    private static function UpdateTextLineMeter():void{
        //Fills the meter.
        TextLineProgress.scaleY=T.numLines/MaxNumLines;
        TextLineProgress.y=
        TextLineMeter.y+TextLineMeter.height-TextLineProgress.height-1;
    }
    public static function set ScrollToEnd(b:Boolean):void{
        _ScrollToEnd=b;
        ScrollToEndButton.transform.colorTransform=
        GetColorTransformByBoolean(b);
        //Change button color by ColorTransform object.
    }
    public static function get ScrollToEnd():Boolean{
        return _ScrollToEnd;
    }
    private static var _ScrollToEnd:Boolean=false;
    public static function set ClearAndPrint(b:Boolean):void{
        _ClearAndPrint=b;
        ClearAndPrintButton.transform.colorTransform=
        GetColorTransformByBoolean(b);
    }
    public static function get ClearAndPrint():Boolean{
        return _ClearAndPrint;
    }
    private static var _ClearAndPrint:Boolean=false;
    
    public static function get HideConsole():Boolean{
        return _HideConsole;
    }
    public static function set HideConsole(b:Boolean):void{
        ConsoleBody.visible=!b;
        _HideConsole=b;
    }
    private static var _HideConsole:Boolean=false;
    public static function TraceVariable(ObjRef:Object
    ,UseSetterFunction:Function
    ,VariableName:String="Name N/A"):void{
        TraceDictionary.AddFunction(ObjRef
        ,UseSetterFunction,VariableName);
        
    }
    
    
    private static var TraceDictionary:WeakRefCalls
    =new WeakRefCalls();

/////////////////////////////////////////////////////////////////////////
    //getters/constants used when "resizing" objects
    //so that there are less "Magic Numbers"
    //in order to change the GUI size of all objects.
    private static const init_width:Number=390;
    private static const init_height:Number=200;
    private static const init_x:Number=75;
    private static const init_y:Number=0;
    private static const MaxNumLines:int=1234;
    private static const ScrollBar_width:Number=30;
    private static const TextBody_y:Number=40;
        //TextBody.y With respect to the ConsoleBody "container".
    private static function get TextBodyWidth():Number{
        return ConsoleBody.width-125;
    }
    private static function get TextBodyHeight():Number{
        return ConsoleBody.height-15-TextBody_y;
    }
//Everything else below is internal/private/GUI-related/////    
////////////////////////////////////////////////////////////    
    private static var AlreadyInit:Boolean=false;
    private static var ConsoleBody:Sprite=new Sprite();
        //As "container" for all of the DisplayObjects.
    private static var TextBody:Sprite=new Sprite();
        //As "container" for the TextField object.
    private static var T:TextField=new TextField();
        //This.
    private static var TitleT:TextField=new TextField();
    
    private static var UpButton:Sprite=new Sprite();
    private static var DownButton:Sprite=new Sprite();
        //Move text up/down respectively.
    private static var ScrollBarOuter:Sprite=new Sprite();
    private static var ScrollBarInner:Sprite=new Sprite();
        //As vertical scrollbar.
    private static var DraggableBar:Sprite=new Sprite();
    
    private static var ScrollToEndButton:Sprite=new Sprite();
    private static var ScrollToEndButtonOutline:Shape=new Shape();
        //Force Scrolling to the end of the line when printing.
    private static var ClearAndPrintButton:Sprite=new Sprite();
    private static var ClearAndPrintButtonOutline:Shape=new Shape();
        //Can print traced variables as getter functions
        /*
        Example: Console.TraceVariable(function():String{
            return VariableOfDataTypeString;
        },"YourSpecialNameForThisVariable");*/
    private static var ClearTextButton:Sprite=new Sprite();
    
    private static var TextLineMeter:Shape=new Shape();
    private static var TextLineProgress:Shape=new Shape();
    
    private static var HideConsoleButton:Sprite=new Sprite();
    
    public static function INIT(StageObj:Main):void{
            //Ignore that it says StageObj.
        if(AlreadyInit){return;}
            //Just call the function only once.
        DoShapeGraphics(
        ConsoleBody,init_x,init_y,0xBFBFBF,
        init_width-1,init_height-1);
        StageObj.addChild(ConsoleBody);
        
        DoShapeGraphics(
        TextBody,15,TextBody_y,0xFFFFFF,TextBodyWidth,TextBodyHeight);
        ConsoleBody.addChild(TextBody);
        
        DoShapeGraphics(ScrollBarInner,TextBodyWidth+30,TextBody_y+15
        ,0x3F3F3F,ScrollBar_width,TextBodyHeight-30);
        ScrollBarInner.addEventListener(MouseEvent.CLICK,ScrollBarRoutine);
            //When ScrollBarInner is clicked,
            //the ScrollBarOuter will scroll as well.

        ConsoleBody.addChild(ScrollBarInner);
        
        DoShapeGraphics(UpButton,
        TextBodyWidth+30,TextBody_y,0xFFFFFF,ScrollBar_width,15);
        UpButton.addEventListener(MouseEvent.MOUSE_DOWN,
        function(e:MouseEvent):void
            {
                //T.scrollV--; //Scroll the text up by line.
                //SetScrollBarOffset();
                SetScrollBarAndScrollV(
                ScrollBarOuter.y-
                ScrollBarOuter.height/2
                );
                //New code that scrolls ScrollBar and T.scrollV.
            }
        );
        
        UpButton.buttonMode=true;
        UpButton.graphics.lineStyle(1,0x000000);
        UpButton.graphics.drawPath(Vector.<int>(
            [1,2,2,2]),
            Vector.<Number>(
            [0,UpButton.height-3
            ,UpButton.width-2,UpButton.height-3
            ,(UpButton.width-2)/2,0
            ,0,UpButton.height-3]));
            //UpButton graphic.
        ConsoleBody.addChild(UpButton);
        
        DoShapeGraphics(DownButton,TextBodyWidth+30,TextBodyHeight+
        TextBody_y-15
        ,0xFFFFFF,ScrollBar_width,15);
        DownButton.addEventListener(MouseEvent.MOUSE_DOWN,function(e:MouseEvent):void
            {
                //T.scrollV++; //Scroll the text down by line.
                //SetScrollBarOffset();
                SetScrollBarAndScrollV(
                ScrollBarOuter.y+
                ScrollBarOuter.height/2
                );
            }
        );
        DownButton.buttonMode=true;
        DownButton.graphics.lineStyle(1,0x000000);
        DownButton.graphics.drawPath(Vector.<int>(
            [1,2,2,2]),
            Vector.<Number>(
            [0,1
            ,DownButton.width/2-2,DownButton.height-2
            ,DownButton.width-2,1
            ,0,1]));
            //DownButton graphic.
        ConsoleBody.addChild(DownButton);

        T.width=TextBodyWidth;
        T.height=TextBodyHeight+4;
        T.wordWrap=true;
            //Wrap so scrolling horizontally isn't needed.
        T.addEventListener(Event.SCROLL,SetScrollBarOffset);
            //Allow scrolling the scrollbar by highlighting text.
        TextBody.addChild(T);
        
        ResizeScrollBar();
        ScrollBarOuter.buttonMode=true;
        ScrollBarOuter.addEventListener(MouseEvent.MOUSE_DOWN,
        function(e:MouseEvent):void
            {
                StageObj.addEventListener(MouseEvent.MOUSE_MOVE,ScrollBarRoutine);
                e.updateAfterEvent();
            }
        );
        StageObj.addEventListener(MouseEvent.MOUSE_UP,
        function(e:MouseEvent):void
            {
                StageObj.removeEventListener(MouseEvent.MOUSE_MOVE,ScrollBarRoutine);
            }
        );
        ConsoleBody.addChild(ScrollBarOuter);
        
        DoShapeGraphics(DraggableBar,0,0
        ,0xFFFF00,ConsoleBody.width-32,TextBody_y-15);
        
        var IsDragged:Boolean=false;
        DraggableBar.addEventListener(MouseEvent.CLICK,
        function(e:MouseEvent):void{
            StageObj.addChild(ConsoleBody);
                //Make ConsoleBody the top layer whenever possible.
            StageObj.addChild(HideConsoleButton);
                //Make HideConsoleButtop as well.
            if(!IsDragged){
                ConsoleBody.startDrag();
                IsDragged=true;
            }else{
                ConsoleBody.stopDrag();
                IsDragged=false;
            }
            //Click to drag, click again to not drag.
        });
        DraggableBar.addEventListener(MouseEvent.MOUSE_MOVE,
        function(e:MouseEvent):void{
            HideConsoleButton.x=ConsoleBody.x+DraggableBar.x+DraggableBar.width;
            HideConsoleButton.y=ConsoleBody.y;
            //Make HideConsoleButton move with ConsoleBody
            //as it isn't a container of ConsoleBody.
        });

        DraggableBar.addEventListener(MouseEvent.MOUSE_OVER,
        function(e:MouseEvent):void{
            AddAWordBalloon(StageObj
            ,"Click this to drag the Console. Click again to stop dragging."
            ,ConsoleBody.x,ConsoleBody.y-50);
            e.updateAfterEvent(); 
        });

        DraggableBar.buttonMode=true;
        ConsoleBody.addChild(DraggableBar);
        
        DoShapeGraphics(HideConsoleButton
        ,ConsoleBody.x+DraggableBar.x+DraggableBar.width
        ,ConsoleBody.y
        ,0xFFFFFF,ConsoleBody.width-DraggableBar.width-2
        ,TextBody_y-15);
        HideConsoleButton.buttonMode=true;
        
        HideConsoleButton.addEventListener(
        MouseEvent.CLICK,function(e:MouseEvent):void{
            HideConsole=(!_HideConsole); //Toggle.
        });
        
        HideConsoleButton.addEventListener(MouseEvent.MOUSE_OVER,
        function(e:MouseEvent):void{
            AddAWordBalloon(StageObj
            ,"Click to hide the console. Click again to show the console."
            ,HideConsoleButton.x-250,HideConsoleButton.y-50); 
        });
        
        StageObj.addChild(HideConsoleButton);
        
        DoShapeGraphics(ScrollToEndButton,UpButton.x+45,UpButton.y
        ,0xFF0000,ConsoleBody.width-(UpButton.x+45)-16,30);
        ScrollToEndButton.buttonMode=true;
        ScrollToEndButton.addEventListener(
        MouseEvent.CLICK,function(e:MouseEvent):void{
            ScrollToEnd=(!_ScrollToEnd); //Toggle.
        });
        var ScrollToEndListener:Function=function(e:MouseEvent):void{
            AddAWordBalloon(StageObj
            ,"Scroll to End: Scroll to the end of the line when Console is printing. When Clear and Print is enabled, this has no effect. "
            +((_ScrollToEnd)?"Enabled.":"Disabled.")
            ,ConsoleBody.x+ConsoleBody.width/4
            ,ConsoleBody.y+ConsoleBody.height/4); 
        };
        ScrollToEndButton.addEventListener(MouseEvent.MOUSE_OVER
        ,ScrollToEndListener);
        ScrollToEndButton.addEventListener(MouseEvent.CLICK
        ,ScrollToEndListener);
        ConsoleBody.addChild(ScrollToEndButton);
        
        DoShapeGraphics(ScrollToEndButtonOutline,UpButton.x+45,UpButton.y
        ,0xFFFF00,ConsoleBody.width-(UpButton.x+45)-16,30,true);
        ConsoleBody.addChild(ScrollToEndButtonOutline);
            //If color transform is used, it would make the
            //lines green/red in ScrollToEndButton as well.
            //ScrollToEndButtonOutline is layered
            //over ScrollToEndButton for the lines.
        DoShapeGraphics(ClearAndPrintButton
        ,UpButton.x+45,UpButton.y+ScrollToEndButton.height
        ,0xFF0000,ConsoleBody.width-(UpButton.x+45)-16,30);
        ClearAndPrintButton.buttonMode=true;
        
        ClearAndPrintButton.addEventListener(
        MouseEvent.CLICK,function(e:MouseEvent):void{
            ClearAndPrint=(!_ClearAndPrint); //Toggle.
        });
        var ClearAndPrintListener:Function=function(e:MouseEvent):void{
            AddAWordBalloon(StageObj
            ,"Clear and Print: Allows tracing variables using getter functions. Example: function():int{return VariableOfDataTypeInt;} with no parameters. "
            +((_ClearAndPrint)?"Enabled.":"Disabled.")
            ,ConsoleBody.x+ConsoleBody.width/4
            ,ConsoleBody.y+ConsoleBody.height/4); 
        };
        ClearAndPrintButton.addEventListener(MouseEvent.MOUSE_OVER
        ,ClearAndPrintListener);
        ClearAndPrintButton.addEventListener(MouseEvent.CLICK
        ,ClearAndPrintListener);
        
        ConsoleBody.addChild(ClearAndPrintButton);
        
        DoShapeGraphics(ClearAndPrintButtonOutline
        ,UpButton.x+45,UpButton.y+ScrollToEndButton.height
        ,0xFF0000,ConsoleBody.width-(UpButton.x+45)-16,30,true);
        ConsoleBody.addChild(ClearAndPrintButtonOutline);
        
        DoShapeGraphics(ClearTextButton
        ,UpButton.x+45,ClearAndPrintButton.y+ClearAndPrintButton.height
        ,0xFFFFFF,ConsoleBody.width-(UpButton.x+45)-16,30);
        ClearTextButton.buttonMode=true;
        ClearTextButton.addEventListener(MouseEvent.MOUSE_DOWN,
        function(e:MouseEvent):void{
            ClearText();
        });
        ClearTextButton.addEventListener(MouseEvent.MOUSE_MOVE,
        function(e:MouseEvent):void{
            AddAWordBalloon(StageObj
            ,"Clears Text if Clear and Print is disabled. But when the meter at the bottom fills up, "
            +"the Console will clear all text when it reaches a maximum of "+MaxNumLines+" lines. "
            +"Current number of lines: "+(T.numLines-1)
            ,ConsoleBody.x+ConsoleBody.width/4
            ,ConsoleBody.y+ConsoleBody.height/4);
        });
        ConsoleBody.addChild(ClearTextButton);
        
        TitleT.autoSize=TextFieldAutoSize.LEFT;
        TitleT.text=" trace.as3";
        TitleT.selectable=false;
        ConsoleBody.addChild(TitleT);
        
        DoShapeGraphics(TextLineProgress
        ,UpButton.x+45,ClearTextButton.y+ClearTextButton.height
        ,0xFFFF00,ConsoleBody.width-(UpButton.x+45)-16,
        ConsoleBody.height-
        (ClearTextButton.y+ClearTextButton.height)-16);
        ConsoleBody.addChild(TextLineProgress);
        
        DoShapeGraphics(TextLineMeter
        ,UpButton.x+45,ClearTextButton.y+ClearTextButton.height
        ,0xFFFF00,ConsoleBody.width-(UpButton.x+45)-16,
        ConsoleBody.height-
        (ClearTextButton.y+ClearTextButton.height)-16,true);
        
        ConsoleBody.addChild(TextLineMeter);
        
        AlreadyInit=true;
    }
    private static var WB_Obj:WordBalloon;
    private static var RemoveTimer:Timer=new Timer(5000,1);
    private static function AddAWordBalloon(
    StageObj:Main,Message:String="a",
    init_x:Number=0,init_y:Number=0):void{
        return;
        AttemptRemoveWordBalloon(StageObj);
        WB_Obj
        =new WordBalloon(Message
        ,init_x,init_y);
        StageObj.addChild(WB_Obj);
        
        
        RemoveTimer.reset();
        //Reset the timer so that the WordBalloons would
        //be displayed until 5 seconds are up.
        RemoveTimer.start();
        var TimerListener:Function=function(e:TimerEvent):void{
            AttemptRemoveWordBalloon(StageObj);
            RemoveTimer.removeEventListener(
            TimerEvent.TIMER,TimerListener);
            //Remove self.
        }
        RemoveTimer.addEventListener(TimerEvent.TIMER,
        TimerListener);
        
    }
    private static function AttemptRemoveWordBalloon(
    StageObj:Main):void{
        try{
            StageObj.removeChild(WB_Obj);
        }catch(E:Error){
            //Attempt to remove from stage.
            //Otherwise, no fault here.
        }
    }
    
    private static function GetColorTransformByBoolean(
    b:Boolean):ColorTransform{
        var ct:ColorTransform=new ColorTransform();
        ct.color=(b)?0x00FF00:0xFF0000;
            //Either green/true or red/false
        return ct;
    }

    private static function ScrollBarRoutine(e:MouseEvent):void{
        ScrollBarOuter.x=ScrollBarInner.x;
            //Keep ScrollBar at same x.
        var GetLocal_y:Point=ConsoleBody.globalToLocal(
        new Point(0,e.stageY));
            //Mouse y (e.stageY) relative to ConsoleBody.
        SetScrollBarAndScrollV(
        GetLocal_y.y-ScrollBarOuter.height/2);
        e.updateAfterEvent();
    }
    private static function SetScrollBarAndScrollV(
    ByPixels:Number):void{
        if(ByPixels<ScrollBarInner.y){
            ScrollBarOuter.y=ScrollBarInner.y;
        }else if(ByPixels>GetMaxScroll_y){
            ScrollBarOuter.y=GetMaxScroll_y;
        }else{
            ScrollBarOuter.y=ByPixels;
        }
        T.scrollV=int(Math.round(
        (ScrollBarOuter.y-ScrollBarInner.y)*
        (T.maxScrollV-1)/MaxScrollBarSpace+1));
        //How much should text and scrollbar scroll
        //by setting y-pixels. It's the inverse
        //of SetScrollBarOffset using algebras.
        //ScrollBarOuter.y=f(T.scrollV)=(stuff down there)
        //into T.scrollV=g(ScrollBarOuter.y)
        //=(stuff up here)
    }

    private static function get GetMaxScroll_y():Number{
        return MaxScrollBarSpace+ScrollBarInner.y;
    }
    private static function SetScrollBarOffset(e:Event=null):void{
        //Calculates how much should ScrollBarOuter object move
        //using T.scrollV
        ScrollBarOuter.y=((T.maxScrollV!=1)
        ?(MaxScrollBarSpace/(T.maxScrollV-1))*(T.scrollV-1)
        :0)+ScrollBarInner.y;
    }
    private static var MaxScrollBarSpace:Number=0;
        //Space of ScrollBarInner-ScrollBarOuter
        //edited using ResizeScrollBar below.
    private static function ResizeScrollBar():void{
        var ScrollBarRatio:Number;
            //To change size of scrollbar by multiplying from 0 to 1.
        if(T.textHeight>T.height){
            ScrollBarRatio=T.height/T.textHeight;
            DoShapeGraphics(ScrollBarOuter,TextBodyWidth+30,TextBody_y+15
            ,0xFFFF00,ScrollBar_width,ScrollBarInner.height*ScrollBarRatio);
        }else{
            ScrollBarRatio=1;
            DoShapeGraphics(ScrollBarOuter,TextBodyWidth+30,TextBody_y+15
            ,0xFFFF00,ScrollBar_width,ScrollBarInner.height);
            //Fills ScrollBarInner object.
        }
        MaxScrollBarSpace=(1-ScrollBarRatio)*ScrollBarInner.height;
    }
    private static function DoShapeGraphics(ObjRef:*,
    set_x:Number,set_y:Number,FillColor:Number,
    rect_width:Number,rect_height:Number,is_outline:Boolean=false):void{
        //Pass objects by reference.
        with(ObjRef){
            x=set_x;
            y=set_y;
            //cacheAsBitmap=true;
            with(graphics){
                clear();
                //Clear any graphics if it's called again.
                lineStyle(1.5,0x000000);
                if(!is_outline)
                    beginFill(FillColor);
                drawRect(0,0,rect_width,rect_height);
            }  
        }
    }
}


/*import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.geom.Rectangle;
final class C{
    private static var T:TextField=new TextField();
    private static var MaskContainer:Sprite=new Sprite();
    private static var INITStarted:Boolean=false;


    public static function INIT():void{
        if(!INITStarted){
            //T.border=true;
            T.wordWrap=true;
            T.width=200;
            T.height=Main.GetStage.stageHeight-5;
            T.scrollRect=new Rectangle(0,0,T.width,200);
            T.autoSize=TextFieldAutoSize.LEFT;
            
            T.text="This is just to add things using the instance \"this.stage\" at Main\nand making a static variable Main.stage so that \"static classes\" \nand non-static classes can use Main\'s object \"this.stage\".\n";
            //T.selectable=false;
            T.cacheAsBitmap=true;
            MaskContainer.x=100;
            MaskContainer.y=100;
            MaskContainer.scrollRect=new Rectangle(0,0,T.width,200);
            MaskContainer.cacheAsBitmap=true;
            MaskContainer.addChild(T);
            Main.GetStage.addChild(MaskContainer);
             //Adding TextField from this "static class".
            INITStarted=true;
        }       
    }
    public static function Print(PrintThis:*):void{
        var OldTextHeight:int=T.textHeight;
        T.appendText(String(PrintThis)+"\n");
        var NewTextHeight:int=T.textHeight;
        var TempRect:Rectangle=T.scrollRect;
        TempRect.y+=(NewTextHeight-OldTextHeight);
        T.scrollRect=TempRect;
    }
}
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.MouseEvent;
//Using http://www.senocular.com/flash/tutorials/as3withmxmlc/
final class Rectangles extends Sprite {
    public function Rectangles(Offset:int=0) {
        var rect:Shape = new Shape();
        drawColoredRectIn(rect.graphics, 0xFFFF00);
        rect.x = 100+Offset;
        rect.y = 100+Offset;
        //Go behind textfield (Using addChildAt index 0)
        Main.GetStage.addChildAt(this,0);
        //Adding object to stage when object is created.
        Main.GetStage.addChildAt(rect,0);
        //Adding object to stage when object is created.
        drawColoredRectIn(graphics, 0xFF0000);
        this.x = 150+Offset;
        this.y = 150+Offset;
        C.Print("Added two rectangles.");
        this.addEventListener("rollOver",abcdefg);
        this.buttonMode=true;
        }
    private function abcdefg(e:Event):void{
        C.Print("You have \""+MouseEvent.ROLL_OVER+"\"ed the Red Rectangle for no reason.");
    }
    
    private function drawColoredRectIn(target:Graphics, color:int):void {
        target.lineStyle(1, 0x000000);
        target.beginFill(color);
        target.drawRect(0, 0, 100, 100);
    }
}*/