In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Human Theatre

One AWD2 file from max
Two animated model of man and woman on the same squeleton
Multy clone technique with self animation 

Code, Model and map by LoTh
Blog : http://3dflashlo.wordpress.com
Get Adobe Flash player
by Loth2012 20 Oct 2012
/**
 * Copyright Loth2012 ( http://wonderfl.net/user/Loth2012 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/58I2
 */

package {
    import away3d.animators.transitions.CrossfadeStateTransition;
    import away3d.animators.SkeletonAnimationState;
    import away3d.animators.SkeletonAnimationSet;
    import away3d.animators.SkeletonAnimator;
    import away3d.animators.data.Skeleton;
    import away3d.lights.shadowmaps.NearDirectionalShadowMapper;
    import away3d.materials.methods.FilteredShadowMapMethod;
    import away3d.materials.methods.NearShadowMapMethod;
    import away3d.core.managers.Stage3DManager;
    import away3d.core.managers.Stage3DProxy;
    import away3d.containers.ObjectContainer3D;
    import away3d.events.Stage3DEvent;
    import away3d.entities.Mesh;
    import away3d.debug.AwayStats;
    import away3d.primitives.SkyBox;
    import away3d.lights.LightBase;
    import away3d.loaders.Loader3D;
    import away3d.lights.LightProbe;
    import away3d.lights.PointLight;
    import away3d.events.LoaderEvent;
    import away3d.containers.View3D;
    import away3d.events.AssetEvent;
    import away3d.core.base.Geometry;
    import away3d.events.MouseEvent3D;
    import away3d.library.AssetLibrary;
    import away3d.materials.LightSources;
    import away3d.textures.BitmapTexture;
    import away3d.materials.ColorMaterial;
    import away3d.lights.DirectionalLight;
    import away3d.library.assets.AssetType;
    import away3d.loaders.parsers.AWD2Parser;
    import away3d.materials.methods.FogMethod;
    import away3d.materials.methods.OutlineMethod;
    import away3d.materials.methods.CelDiffuseMethod;
    import away3d.materials.methods.CelSpecularMethod;
    import away3d.materials.methods.EnvMapMethod;
    import away3d.materials.methods.LightMapMethod;
    import away3d.materials.methods.FresnelSpecularMethod;
    import away3d.materials.methods.TripleFilteredShadowMapMethod;
    import away3d.materials.lightpickers.StaticLightPicker;
    import away3d.cameras.lenses.PerspectiveLens;
    import away3d.materials.DefaultMaterialBase;
    import away3d.controllers.HoverController;
    import away3d.materials.TextureMaterial;
    import away3d.primitives.SphereGeometry;
    import away3d.primitives.PlaneGeometry;
    
    import org.flintparticles.integration.away3d.v4.A3D4Renderer;
    
    import flash.filters.DropShadowFilter;
    import flash.display.StageScaleMode;
    import flash.display.StageQuality;
    import flash.events.KeyboardEvent;
    import flash.display.BitmapData;
    import flash.display.StageAlign;
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.text.TextFormat;
    import flash.text.TextField;
    import flash.display.LoaderInfo;
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.geom.Vector3D;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.ui.Keyboard;
    import flash.net.URLRequest;
    import flash.display.DisplayObject;
    import flash.events.ProgressEvent;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.system.LoaderContext;
    /**
     * 
     * HUMAN THEATRE beta 0.1
     * 
     * One AWD2 file from max
     * Two animated model of man and woman on the same squeleton
     * Multy clone technique with self animation 
     * 
     * Code, Model and map by LoTh
     * Blog : http://3dflashlo.wordpress.com
     *
     */
    public class HumanTheatre extends Sprite {
        private static const SCALE:Number = 16;
        private static var COLOR:Object = {
            sun : 0xFFFFEF, moon : 0x33FF80,
            sky : 0xFFFFFF , ground : 0x6D6145,
            background : 0x000000 , fog : 0xAEAEA8
        }
        private static var DemoAmbiant:Array = [0.85, 0.1];
        private static var DemoDiffuse:Array = [1, 1];
        private static var DemoSpecular:Array = [1, 0.5];
        private static var _capture : Bitmap;
        private static var _player:Mesh;
        // mapping online
        private static const MESH_PATH:String = 'http://3dflashlo.free.fr/wonderfl/assets/';
        private static const PATH:String = "http://assets.wonderfl.net/images/related_images/"
        private static const FILES:Array =[
        '/f/f1/f1ad/f1ad270ccefb2f72a1a770c69e2003baf4c525ab', '/3/3a/3a97/3a97741efaeeb0f3a556cc39a305fe4278b73e94',
        '/b/b3/b321/b3216c9e0d279b0103e17c780f1c62cfd7e44e6d', '/9/92/92ff/92ffe84a7ebdc2c8841337d9f0fe8cf9cc0e9efa',
        ];
        // mapping Local
        private static const PATH_LOCAL:String = 'assets/';
        private static const FILES_LOCAL:Array = [ 'amphy.jpg', 'front.jpg', 'man.jpg', 'woman.jpg'];
        private static var _local:Boolean = false;
        // engine
        protected static var _lightPicker:StaticLightPicker;
        protected static var _hoverCtrl:HoverController;
        protected static var _stage3DProxy:Stage3DProxy;
        protected static var _manager:Stage3DManager;
        protected static var _stats:AwayStats;
        protected static var _skyBox:SkyBox;
        protected static var _view:View3D;
        // referency
        private var _materialMan:Vector.<DefaultMaterialBase>;
        private var _materialWoman:Vector.<DefaultMaterialBase>;
        private var _materials:Vector.<DefaultMaterialBase>;
        private var _mapList:Vector.<BitmapData>;
        private var _light:Array;
        private var _n:int;
        private var _i:int;
        // animation
        //private var animator:SkeletonAnimator;
        private var _squeleton:Skeleton;
        private var _animationSet:SkeletonAnimationSet;
        private var stateTransition:CrossfadeStateTransition = new CrossfadeStateTransition(0.5);
        // character movement
        private var currentRotationInc:Number = 0;
        private var movementDirection:Number;
        private var isRunning:Boolean;
        private var isMoving:Boolean;
        private var isJumping:Boolean;
        private var currentAnim:String;
        // animation constants
        private static const SEQUENCE:Array = ['Breathe', 'Sit', 'SitWoman' , 'Walk', 'Run'];
        private static const SEQUENCE_MAN:Array = ['Breathe', 'Sit', 'Walk', 'Run'];
        private static const SEQUENCE_WOMEN:Array = ['Breathe', 'SitWoman', 'WalkWoman', 'Run'];
        private static const SEQSPEED:Array = [0.5, 1, 1, 0.5, 0.5, 0.5, 0.5, 0.5];
        private static const ROTATION_SPEED:Number = 10;
        private static const XFADE_TIME:Number = 0.5;
        // scene objects
        private var _hero:Mesh;
        private var _box:Mesh;
        private var _deco:Mesh;
        private var _decoFront:Mesh;
        // Avatar referency
        private var _skinMesh:Vector.<Mesh>;
        private var _cloneAnim:Vector.<SkeletonAnimator>;
        private var _cloneHair:Vector.<Mesh>;
        private var _cloneStyleMan:Vector.<Mesh>;
        private var _cloneStyleWoman:Vector.<Mesh>;
        // Particule container
        private var emitter:EmitterSmoke;
        private var particleContainer:ObjectContainer3D;
        private var particleRenderer:A3D4Renderer;
        // navigation
        private var _prevMouseX:Number;
        private var _prevMouseY:Number;
        private var _mouseMove:Boolean;
        private var _cameraHeight:Number = 0;
        
        private var _eyePosition:Vector3D;
        private var _mapper:Mapper;
        private var _text:TextField;
        
        private var _fog:FogMethod;
        private var _reflect:EnvMapMethod;
        private var _specularMethod:FresnelSpecularMethod;
        private var _shadowMethod:NearShadowMapMethod;
        private var photoLoad:PhotoLoader;
        
        /** Constructor */
        public function HumanTheatre() {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
        }
        
        private function init(e:Event = null):void{
            removeEventListener(Event.ADDED_TO_STAGE, init);
            stage.align = 'TL';
            stage.scaleMode = 'noScale';
            stage.quality = 'low';
            stage.frameRate = 60;
            stage.color = COLOR.background;
            // ★ wonderfl capture
            Wonderfl.disable_capture();
            //_capture = addChild(new Bitmap(new BitmapData(465, 465, false, 0x000000))) as Bitmap ;
            _manager = Stage3DManager.getInstance(stage);
            _stage3DProxy = _manager.getFreeStage3DProxy();
            _stage3DProxy.addEventListener(Stage3DEvent.CONTEXT3D_CREATED, onContextCreated);
        }
        
        private function onContextCreated(e:Stage3DEvent):void{
            _stage3DProxy.color = COLOR.background;
            _stage3DProxy.antiAlias = 4;
            initEngine();
            initText();
            initLights();
            initListeners();
            
            // start by loading all bitmap
            _mapList = new Vector.<BitmapData>();
            loadBitmap();
            
            // character mesh referency
            _skinMesh = new Vector.<Mesh>();
            // hair style clone referency
            _cloneStyleMan = new Vector.<Mesh>();
            _cloneStyleWoman = new Vector.<Mesh>();
            
        }
        
        //-------------------------------- AWAY3D
        
        /** Initialise the engine */
        private function initEngine():void {
            _view = new View3D();
            _view.stage3DProxy = _stage3DProxy;
            _view.shareContext = true;
            _view.backgroundColor = COLOR.background;
            
            _view.camera.lens = new PerspectiveLens(80);
            _view.camera.lens.far = 20000;
            _view.camera.lens.near = 1;
            
            _hoverCtrl = new HoverController(_view.camera, null, 180, 0, 100*SCALE, 6, 90);
            _hoverCtrl.tiltAngle = 0;
            _hoverCtrl.panAngle = 180;
            _hoverCtrl.minTiltAngle = -60;
            _hoverCtrl.maxTiltAngle = 60;
            _hoverCtrl.autoUpdate = false;
            
            addChild(_view);
            
            //away3d stat
            _stats = new AwayStats(_view, false, true);
            _stats.alpha = 0.3;
            addChild(_stats);
            
            //material reference
            _materials = new Vector.<DefaultMaterialBase>();
            _materialMan = new Vector.<DefaultMaterialBase>();
            _materialWoman = new Vector.<DefaultMaterialBase>();
            //light referency
            _light = [];
            // hero content
            _player = new Mesh(new Geometry());
            _view.scene.addChild(_player);
            _player.y = 0//20 * SCALE;
            //auto map generator
            _mapper = new Mapper();
            
        }
        
        //-------------------------------- PARTICULE
        
        private function addParticule():void {
            // flint
            emitter = new EmitterSmoke(this);
            emitter.start();
            
            // Create Particle Container
            particleContainer = new ObjectContainer3D();
            particleContainer.visible = true;
            _view.scene.addChild(particleContainer);
            
            particleRenderer = new A3D4Renderer(particleContainer);
            particleRenderer.addEmitter(emitter);
        }
        
        //-------------------------------- LOOP
        
        /** Render loop */
        private function onEnterFrame(event:Event):void {
            //update character animation
            _player.rotationY += currentRotationInc;
            _hoverCtrl.lookAtPosition = new Vector3D(_player.x,  _player.y + (30 * SCALE), _player.z);
            updateClone();
            
            //update camera controler
            _hoverCtrl.update();
            //update light
            //_light[1].position = _view.camera.position;
            //update view
            _view.render();
            // ★ wonderfl capture
            if (_capture) _stage3DProxy.context3D.drawToBitmapData(_capture.bitmapData);
        }
        
        //-------------------------------- LISTENER
        
        /** Initialise the listeners */
        private function initListeners():void {
            //add render loop
            _stage3DProxy.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
            //add key listeners
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp, false, 0, true);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);
            //navigation
            stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown, false, 0, true);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove, false, 0, true);
            stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseLeave, false, 0, true);
            stage.addEventListener(MouseEvent.MOUSE_WHEEL, onStageMouseWheel, false, 0, true)
            stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave, false, 0, true);
            //add resize event
            stage.addEventListener(Event.RESIZE, onResize, false, 0, true);
            onResize();
        }
        
        //-------------------------------- LIGHT
        
        /** Initialise the lights */
        private function initLights():void {
            //create a light for shadows that mimics the sun's position in the skybox
            var sun:DirectionalLight = new DirectionalLight(0.1, -1, 0.35);
            sun.castsShadows = true;
            sun.shadowMapper = new NearDirectionalShadowMapper(0.3);
            _view.scene.addChild(sun);
            _light.push(sun);
            //create a light for ambient effect that mimics the sky
            var moon:PointLight = new PointLight();
            moon.y = -600*SCALE;
            moon.radius = 200;
            moon.fallOff = 2500;
            _view.scene.addChild(moon);
            _light.push(moon);
            makeSky();
        }
        
        //-------------------------------- SKY
        
        /** sky change */
        private function randomSky():void {
            COLOR.ground = 0xFFFFFF * Math.random();
            COLOR.fog = 0xFFFFFF * Math.random();
            COLOR.sky = 0xFFFFFF * Math.random();
            COLOR.sun = 0xFFFFFF * Math.random();
            COLOR.moon = 0xFFFFFF * Math.random();
            DemoAmbiant = [0.4, 0.3];
            DemoAmbiant = [Math.random(), Math.random()];
            DemoDiffuse = [Math.random(), Math.random()];
            DemoSpecular = [Math.random() * 4, Math.random() * 2];
            makeSky();
        }
        
        private function makeSky():void {
            if (_light[2]) {
                _view.scene.removeChild(_light[2]);
                _light.pop();
            }
            if (_skyBox) {
                _view.scene.removeChild(_skyBox);
                _skyBox.dispose();
            }
            //generate vector degrade sky
            _mapper.vectorSky([COLOR.ground, COLOR.fog, COLOR.sky], 8);
            
            _skyBox = new SkyBox(_mapper.sky);
            _view.scene.addChild(_skyBox);
            //add new probe light
            var probe:LightProbe = new LightProbe(_mapper.sky);
            _view.scene.addChild(probe);
            _light.push(probe);
            //sun
            _light[0].color = COLOR.sun;
            _light[0].ambientColor = COLOR.fog;
            _light[0].ambient = DemoAmbiant[0];
            _light[0].diffuse = DemoDiffuse[0];
            _light[0].specular = DemoSpecular[0];
            // moon
            _light[1].color = COLOR.moon;
            _light[1].ambientColor = COLOR.ground;
            _light[1].ambient = DemoAmbiant[1];
            _light[1].diffuse = DemoDiffuse[1];
            _light[1].specular = DemoSpecular[1];
            _lightPicker = new StaticLightPicker(_light);
            
            for each (var o:DefaultMaterialBase in _materials) {
                o.lightPicker = _lightPicker;
            }
            if(_fog) _fog.fogColor = COLOR.fog;
        }
        
        //-------------------------------- MATERIAL
        
        /** Initialise the material */
        protected function initMaterial():void {
            // global methode
            _fog = new FogMethod(200*SCALE, 2000*SCALE, COLOR.fog);
            //_reflect = new EnvMapMethod(_mapper.sky, 0.5)
            _specularMethod = new FresnelSpecularMethod();
            _specularMethod.normalReflectance = 0.3
            // global shadow
            _shadowMethod = new NearShadowMapMethod(new FilteredShadowMapMethod(_light[0]), 0.05);
            _shadowMethod.epsilon = .0007;
            
            var material:DefaultMaterialBase;
            
            // 0 - ground
            var grid:Shape = new Shape();
            grid.graphics.beginFill(0x333333, 0.3);
            grid.graphics.drawRect(0, 0, 4, 128);
            grid.graphics.drawRect(0, 0, 128, 4);
            var b:BitmapData = new BitmapData(128, 128, false, 0x91825F);
            b.draw(grid);
            material = materialFromBitmap('ground', [b, b, b], true, false);
            material.ambient = 1;
            material.gloss = 30;
            material.specular = 1;
            material.repeat = true;
            
            // 1 - Hero
            var bsize:int = 512;
           /* grid.graphics.clear();
            grid.graphics.beginFill(0xAAAAAA, 1);//full
            grid.graphics.drawRect(0, 0, bsize, bsize);
            grid.graphics.beginFill(0xAA8000, 1);//head
            grid.graphics.drawRect(0, 0, bsize, 178);
            grid.graphics.beginFill(0xEEEEEE, 1);//shirt
            grid.graphics.drawRect(0, 178, bsize, 160);
            grid.graphics.beginFill(0x333333, 1);//shoes
            grid.graphics.drawRect(0, 472, bsize, 40);
            var g:Bitmap = new Bitmap(_mapList[2]);
            var f:Sprite = new Sprite();
            f.addChild(g);
            f.addChild(grid);
            grid.blendMode = 'multiply';
            
            var b:BitmapData = new BitmapData(512, 512, false, 0x606060);
            b.draw(f);*/
            material = materialFromBitmap('hero', [_mapList[2]], false, false, false, true);
            material.gloss = 10;
            material.specular = 0.2;
            material.ambient = 1;
            
            // 2 - Amphy
            material = materialFromBitmap('amphy', [_mapList[0]], false, false, false, true);
            material.ambient = 1;
            material.gloss = 100;
            material.specular = 0.1;
            
             // 3 - Amphy front
            material = materialFromBitmap('front', [_mapList[1]], false, false, false, true);
            material.ambient = 1;
            material.gloss = 30;
            material.specular = 0.2;
            
            // 4 _ hair
            grid.graphics.clear();
            grid.graphics.beginFill(0x333333, 1);//full
            grid.graphics.drawRect(0, 0, bsize, bsize);
            b = new BitmapData(512, 512, false, 0x202020);
            b.draw(grid);
            material = materialFromBitmap('hair', [b], false, false, false, true);
            material.ambient = 1;
            material.gloss = 10;
            material.specular = 0.2;
            
            // 5_woman
            material = materialFromBitmap('hero', [_mapList[3]], false, false, false, true);
            material.gloss = 10;
            material.specular = 0.2;
            material.ambient = 1;
        }
        
        /** Make Material from bitmap */
        protected function materialFromBitmap(name:String, Bitmaps:Array, Norm:Boolean = false, Spec:Boolean = false, Occ:Boolean = false, cartoon:Boolean = false):DefaultMaterialBase {
            var n:int;
            var material:TextureMaterial = new TextureMaterial(new BitmapTexture(Bitmaps[0]));
            // normal map
            if (Norm) { n = 1; material.normalMap = new BitmapTexture(Bitmaps[n]); }
            // specular map 
            if (Spec) { n = 2; material.specularMap = new BitmapTexture(Bitmaps[n]); }
            // occlusion
            if (Occ) { n = 3; material.addMethod(new LightMapMethod(new BitmapTexture(Bitmaps[n]))); }
            
            material.name = name;
            material.lightPicker = _lightPicker;
            material.diffuseLightSources = LightSources.PROBES;
            material.specularLightSources = LightSources.LIGHTS;
           // material.specularMethod = _specularMethod;
            material.shadowMethod = _shadowMethod;
            
            if (cartoon) {
                    material.addMethod(new OutlineMethod(0x000000, 0.2, true));
                   // material.diffuseMethod = new CelDiffuseMethod(3);
                  // CelDiffuseMethod(material.diffuseMethod).smoothness = .3;
                  //material.specularMethod = new CelSpecularMethod(.2);
                    //CelSpecularMethod(material.specularMethod).smoothness = .3;
            }
            material.addMethod(_fog);
            //push to reference
            _materials.push(material);
            return material;
        }
        
        //-------------------------------- BINARY LOADER
        
        /** Global Load Binary file */
        private function load(url:String):void {
            var loader:URLLoader = new URLLoader();
            var extention:String = url.substring(url.length - 3);
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            if(extention == 'awd') loader.addEventListener(Event.COMPLETE, parseAWD, false, 0, true);
            loader.addEventListener(ProgressEvent.PROGRESS, loadProgress, false, 0, true);
            loader.load(new URLRequest(url));
        }
        
        /** Display current load */
        private function loadProgress(e:ProgressEvent):void {
            var P:int = int(e.bytesLoaded / e.bytesTotal * 100);
            if (P != 100) log('Load : ' + P + ' % | ' + int((e.bytesLoaded / 1024) << 0) + ' ko\n');
            else message();
        }
        
        //-------------------------------- BITMAP DISPLAY
        
        /** load bitmap from WonderFl or Local */
        public function loadBitmap():void {
            _n = 0;
            photoLoad = new PhotoLoader();
            completeBitmap(); // start first
        }
        
        protected function completeBitmap(e:Event=null):void {
            if (e) {
                var f:Bitmap = new Bitmap(photoLoad.content);
                _mapList.push(f.bitmapData);
                _n++;
            }
            if (FILES[_n]){ 
                log("image " + _n);
                photoLoad = new PhotoLoader();
                photoLoad.addEventListener(PhotoLoader.COMPLETE, completeBitmap, false, 0, true);
                if (_local) photoLoad.load(PATH_LOCAL + FILES_LOCAL[_n]);
                else photoLoad.load(PATH+FILES[_n]);
            } else {
               // create material
               initMaterial();
               // start Loading AWD
               if (_local) load(PATH_LOCAL + "simple.awd");
               else load(MESH_PATH+"simple.awd");
            }
        }
        
        //-------------------------------- AWD DISPLAY
        
        /** Load AWD */
        private function parseAWD(e:Event):void {
            var loader:URLLoader = e.target as URLLoader
            var loader3d:Loader3D = new Loader3D(false);
            loader3d.addEventListener(AssetEvent.ASSET_COMPLETE, onAssetComplete, false, 0, true);
            loader3d.addEventListener(LoaderEvent.RESOURCE_COMPLETE, finalAWD, false, 0, true);
            loader3d.loadData(loader.data, null, null, new AWD2Parser());
            loader.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
            loader.removeEventListener(Event.COMPLETE, parseAWD);
            loader = null;
        }
        
        /** Listener function for asset complete event on awd */
        private function onAssetComplete(event:AssetEvent):void {
            var mesh:Mesh;
            var material:TextureMaterial;
            var specularMethod:FresnelSpecularMethod;
            // ++ Skeleton referency same for man and woman
            if (event.asset.assetType == AssetType.SKELETON) {
                _animationSet = new SkeletonAnimationSet(2);
                _squeleton = event.asset as Skeleton;
            // ++ Animations create state objects for each animation state encountered 
            } else if (event.asset.assetType == AssetType.ANIMATION_STATE) {
                var animationState:SkeletonAnimationState = event.asset as SkeletonAnimationState;
                _animationSet.addState(animationState.name, animationState);
            // ++ Mesh
            } else if (event.asset.assetType == AssetType.MESH) {
                mesh = Mesh(event.asset);
                // Character Men & Woman
                if (mesh.name.substring(0, 4) == "Skin") {
                        mesh.scale(SCALE * 0.45);
                        if (mesh.name == 'Skin_Man') mesh.material = _materials[1];
                        if (mesh.name == 'Skin_Woman') mesh.material = _materials[5];
                        _skinMesh.push(mesh);
                }
                // Character hair no scale because hero child 
                if (mesh.name.substring(0, 8) == "Hair_Man") {
                    mesh.material = _materials[4];
                    _cloneStyleMan.push(mesh);
                }
                if (mesh.name.substring(0, 8) == "Hair_Wom") {
                    mesh.material = _materials[4];
                    _cloneStyleWoman.push(mesh);
                }
                // Scene decoration
                if (mesh.name == "Deco") {
                    _deco = mesh;
                    _deco.material = _materials[2];
                    _deco.scale(SCALE);
                }
                if (mesh.name == "DecoFront") {
                    _decoFront = mesh;
                    _decoFront.material = _materials[3];
                    _decoFront.scale(SCALE);
                }
                if (mesh.name == "Box") {
                    _box = mesh;
                    _box.material = _materials[0];
                    _box.castsShadows = false;
                    _box.geometry.scaleUV(50, 50);
                    _box.scale(SCALE);
                }
                
            }
        }
        
        /** Check if all resourse loaded */
        private function finalAWD(e:LoaderEvent):void {
            var loader3d:Loader3D = e.target as Loader3D;
            loader3d.removeEventListener(AssetEvent.ASSET_COMPLETE, onAssetComplete);
            loader3d.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, finalAWD);
            
            _view.scene.addChild(_deco);
            _view.scene.addChild(_decoFront);
            _view.scene.addChild(_box);
            
            // add people in theatre
            populateTheatre();
            
            // add player avatar
            _hero = addAvatar({target:_player});
            rest();
            
            addParticule();
        }
        
        //-------------------------------- CLONE AVATAR
        
        /** Duplicate Man or Woman into Avatar with self animation */
        public function addAvatar(o:Object = null):Mesh {
            if (o == null) o = new Object();
            if(!_cloneAnim)_cloneAnim = new Vector.<SkeletonAnimator>();
            if(!_cloneHair)_cloneHair = new Vector.<Mesh>();
            
            var sex:int = o.sex || rand(1);// 0:man 1:woman
            var hair:Mesh; 
            var skin:Mesh = Mesh((_skinMesh[sex]).clone());
            // position & rotation
            if(o.rot!=null)skin.yaw(o.rot.y || 0);
            skin.position = o.pos || new Vector3D();
            
            if (o.target!=null) o.target.addChild(skin);
            else _view.scene.addChild(skin);
            
            // choose random hair style;
            if (o.hair==null) o.hair = true;
            if(o.hair){
            if (sex == 0) hair = Mesh((_cloneStyleMan[rand(_cloneStyleMan.length - 1)]).clone());
            else hair = Mesh((_cloneStyleWoman[rand(_cloneStyleWoman.length - 1)]).clone());
            _cloneHair.push(hair);
            skin.addChild(hair);
            }
            // create new animator
            var animatorX:SkeletonAnimator = new SkeletonAnimator(_animationSet, _squeleton);
            animatorX.updateRootPosition = false;
            if(o.hair)_cloneAnim.push(animatorX);
            
            // play random animation
            var num:int = o.anim || (int(Math.random() * 2));
            var anim:String;
            if (sex == 0) anim = SEQUENCE_MAN[num];
            else anim = SEQUENCE_WOMEN[num];
            animatorX.playbackSpeed = o.speed || -SEQSPEED[num];
            animatorX.play(anim, stateTransition);
            skin.animator = animatorX;
            return skin;
        }
        
        /** Special populate for Theatre */
        private function populateTheatre(n:int = 11):void {
            var list:Vector.<Object> = new Vector.<Object>();
            var r:int, d:int = 200, nh:int = 45, obj:Object;
            for (var j:int = 1; j < n; j++) {
                if (j == 1) { nh = 16; d = 80; }
                if (j == 2) { nh = 22; d = 100; }
                if (j == 3) { nh = 24; d = 120; }
                if (j == 4) { nh = 26; d = 140; }
                if (j == 5) { nh = 30; d = 160; }
                if (j == 6) { nh = 35; d = 180; }
                if (j == 7) { nh = 40; d = 200; }
                for (_i = 1; _i < nh; _i++) {
                    r = -30 + ( _i * (240 / nh));
                    obj = new Object();
                    obj['rot'] = new Vector3D(0, 90 - r, 0);
                    if (j < 7) obj['pos'] = orbit( 90, r , (d + 5) * SCALE, (20 * SCALE) + (j * (20 * SCALE)));
                    else obj['pos'] = orbit( 90, r , (d + 5) * SCALE,  (20 * SCALE) + (j * (20 * SCALE) ) + ((j - 7) * (40 * SCALE)) );
                    list.push(obj);
                }
            }
            var avatar:Mesh;
            for (_i = 0; _i < list.length; _i++ ) {
                avatar = addAvatar(list[_i])
            }
        }
        
        /** Update Hair animation to follow head bone */
        private function updateClone():void {
            var anim:SkeletonAnimator;
            for (_i = 0; _i < _cloneAnim.length; _i++) {
                anim = _cloneAnim[_i];
                if (anim.globalPose.numJointPoses == 25)
                _cloneHair[_i].transform = anim.globalPose.jointPoses[24].toMatrix3D();
            }
        }
        
        //-------------------------------- ANIMATION
        
        /** Character breath animation */
        private function rest():void {
            isMoving = false;
            _hero.animator.playbackSpeed = SEQSPEED[0];
            if (currentAnim == SEQUENCE[0]) return;
            currentAnim = SEQUENCE[0];
            _hero.animator.play(currentAnim, stateTransition);
        }
        
        /** Character fight animation */
        private function fight():void {
            if (currentAnim == SEQUENCE[3]) return;
            currentAnim = SEQUENCE[3];
            _hero.animator.playbackSpeed = SEQSPEED[3];
            _hero.animator.play(currentAnim, stateTransition);
        }
        
        /** Character fight animation */
        private function fight2():void {
            if (currentAnim == SEQUENCE[4]) return;
            currentAnim = SEQUENCE[4];
            _hero.animator.playbackSpeed = SEQSPEED[4];
            _hero.animator.play(currentAnim, stateTransition);
        }
        
        /** Character jump animation */
        private function jump():void {
            isJumping = false;
        }
        
        /** Get animation index in SEQUENCE */
        private function getAnim(name:String):int {
            var n:int;
            for (_i = 0; _i < SEQUENCE.length; _i++)
                if (SEQUENCE[_i] == name) n = _i;
            return n;
        }
        
        /** Character Mouvement */
        private function updateMovement(dir:Number):void {
            isMoving = true;
            var anim:String = isRunning ? 'Run' : 'Walk';
            _hero.animator.playbackSpeed = dir * SEQSPEED[getAnim(anim)];
            if (currentAnim == anim) return;
            currentAnim = anim;
            _hero.animator.play(currentAnim, stateTransition);
        }
        
        //-------------------------------- KEYBORD
        
        /** Key down listener for player animation */
        private function onKeyDown(event:KeyboardEvent):void {
            switch (event.keyCode) {
                case Keyboard.SHIFT: 
                    isRunning = true;
                    if (isMoving)
                        updateMovement(movementDirection);
                    break;
                case Keyboard.UP: case Keyboard.W: case Keyboard.Z: //fr
                    updateMovement(movementDirection = 1);
                    break;
                case Keyboard.DOWN: case Keyboard.S: 
                    updateMovement(movementDirection = -1);
                    break;
                case Keyboard.LEFT: case Keyboard.A: case Keyboard.Q: //fr
                    currentRotationInc = -ROTATION_SPEED;
                    break;
                case Keyboard.RIGHT: case Keyboard.D: 
                    currentRotationInc = ROTATION_SPEED;
                    break;
                case Keyboard.E: 
                    fight2();
                    break;
                case Keyboard.SPACE: case Keyboard.R: 
                    fight();
                    break;
                case Keyboard.N: 
                    randomSky();
                    break;
                case Keyboard.B: 
                   // makeClone();
                    break;
            }
        }
        
        /** Key up listener */
        private function onKeyUp(event:KeyboardEvent):void {
            switch (event.keyCode) {
                case Keyboard.SHIFT: 
                isRunning = false;
                if (isMoving) updateMovement(movementDirection);
                break;
                case Keyboard.UP: case Keyboard.W: case Keyboard.Z: //fr
                case Keyboard.DOWN: case Keyboard.S: case Keyboard.SPACE: 
                case Keyboard.E: case Keyboard.R:
                rest();
                break;
                case Keyboard.LEFT: case Keyboard.A: case Keyboard.Q: //fr
                case Keyboard.RIGHT: case Keyboard.D: 
                    currentRotationInc = 0;
                    break;
            }
        }
        
        //-------------------------------- RESIZE
        
        private function onResize(event:Event = null):void {
            _view.width = _stage3DProxy.width = stage.stageWidth;
            _view.height = _stage3DProxy.height = stage.stageHeight;
            _stats.x = stage.stageWidth - _stats.width;
        }
        
        //-------------------------------- NAVIGATION
        
        private function onStageMouseDown(ev:MouseEvent):void {
            _prevMouseX = ev.stageX;
            _prevMouseY = ev.stageY;
            _mouseMove = true;
        }
        
        private function onStageMouseLeave(event:Event):void {
            _mouseMove = false;
        }
        
        private function onStageMouseMove(ev:MouseEvent):void {
            if (_mouseMove) {
                _hoverCtrl.panAngle += (ev.stageX - _prevMouseX);
                _hoverCtrl.tiltAngle += (ev.stageY - _prevMouseY);
            }
            _prevMouseX = ev.stageX;
            _prevMouseY = ev.stageY;
        }
        
        private function onStageMouseWheel(ev:MouseEvent):void {
            _hoverCtrl.distance -= ev.delta * (5*SCALE)
            if (_hoverCtrl.distance < 500*SCALE) {
                if (ev.delta > 0)
                    _cameraHeight += 5*SCALE;
                else
                    _cameraHeight -= 5*SCALE;
            }
            if (_hoverCtrl.distance < 10*SCALE)
                _hoverCtrl.distance = 10*SCALE;
            else if (_hoverCtrl.distance > 1000*SCALE)
                _hoverCtrl.distance = 1000*SCALE;
        }
        
        //-------------------------------- FLASH SIDE
        
        /** Display simple text */
        private function initText():void {
            _text = new TextField();
            _text.defaultTextFormat = new TextFormat("Verdana", 9, 0xAAAAAA);
            _text.x=2;
            _text.width = 300;
            _text.height = 250;
            _text.selectable = false;
            _text.mouseEnabled = true;
            _text.wordWrap = true;
            _text.filters = [new DropShadowFilter(1, 45, 0x0, 1, 0, 0)];
            addChild(_text);
        }
        
        /** final message */
        protected function message():void {
            _text.htmlText = "<b>Human Theatre</b> beta 0.1\n"
            //_text.appendText("Cursor keys / WSAD / ZSQD - move\n");
            //_text.appendText("SHIFT - hold down to run\n");
            _text.appendText("N - random sky\n");
        }
        
        //-------------------------------- LOG DEBUG
        
        /** log for display info */
        private final function log(t:String):void {
            _text.htmlText = t;
        }
        
        //-------------------------------- MATHEMATICS
        
        private static function randomColor():Number {
            return 0xFFFFFF * Math.random();
        }
        
        private static function rand(max:Number = 1, min:Number = 0):Number { 
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
        
        private static function orbit(H:Number, V:Number, D:Number, extraY:Number=0):Vector3D {
            var p:Vector3D = new Vector3D();
            var phi:Number = radToDeg(H);
            var theta:Number = radToDeg(V);
            p.x = (D * Math.sin(phi) * Math.cos(theta));
            p.z = (D * Math.sin(phi) * Math.sin(theta));
            p.y = (D * Math.cos(phi))+extraY;
            return p;
        }
        
        private static function radToDeg(d:Number):Number {
            return (d * (Math.PI / 180));
        } 
        
    }
}


//-------------------------------------o
//          FLINT PARTICULE            o
//-------------------------------------o

import org.flintparticles.integration.away3d.v4.initializers.A3D4CloneObject;
import org.flintparticles.common.initializers.Lifetime;
import org.flintparticles.threeD.initializers.Position;
import org.flintparticles.threeD.initializers.Velocity;
import org.flintparticles.common.actions.TargetScale;
import org.flintparticles.threeD.actions.RandomDrift;
import org.flintparticles.threeD.emitters.Emitter3D;
import org.flintparticles.threeD.actions.DeathZone;
import org.flintparticles.threeD.actions.Friction;
import org.flintparticles.common.counters.Steady;
import org.flintparticles.threeD.zones.BoxZone;
import org.flintparticles.threeD.actions.Move;
import org.flintparticles.common.actions.Fade;
import org.flintparticles.common.actions.Age;

import away3d.primitives.SphereGeometry;
import away3d.materials.ColorMaterial;
import away3d.entities.Mesh;

import flash.geom.Vector3D;

internal class EmitterSmoke extends Emitter3D
{
    public function EmitterSmoke(O:Object = null)
    {
        counter = new Steady(10);
        // test cloning character 
  //      var sphere:Mesh = O.addAvatar({anim:2, speed:1, hair:false})
        var sphere:Mesh = new Mesh(new SphereGeometry(10), new ColorMaterial(0xffffff, 0.3));
        addInitializer(new Position(new BoxZone(100, 100, 1000, new Vector3D(1000, 0, 0))));
        //addInitializer(new Lifetime(10));
        addInitializer(new Velocity(new BoxZone(200, 20, 200, new Vector3D( -100, 0, 0)))); 
        
        var clone:A3D4CloneObject = new A3D4CloneObject( sphere, true, 400 )
        addInitializer( clone );
        //addAction(new Age());
        addAction(new Move());
        addAction(new Friction(0.9));
        addAction(new Fade(0.7, 1.0));
        addAction(new TargetScale(10));
        addAction(new RandomDrift(50, 10, 50));
        addAction(new DeathZone(new BoxZone(2000, 1000, 2000), true));
    }
}


//-------------------------------------o
//           VECTOR MAPPER             o
//-------------------------------------o

import flash.display.Stage;
import flash.filters.DisplacementMapFilter;
import away3d.textures.BitmapCubeTexture;
import flash.display.DisplayObject;
import flash.filters.ShaderFilter;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Shader;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;
    
internal class Mapper extends Sprite {
    private var _shaders:Vector.<Shader>;
    private var _bitmap:Vector.<Bitmap>;
    private var _bitdata:Vector.<BitmapData>;
    private var _skydata:Vector.<BitmapData>;
    private var _sky:BitmapCubeTexture;
    
    //-------------------------------- REFERENCY

    public function get bitdata():Vector.<BitmapData> { return _bitdata; }  
    public function get sky():BitmapCubeTexture { return _sky; }
    
    //-------------------------------- VECTOR SKY
    
    /** create vector sky */
    public function vectorSky(C:Array, quality:uint=8):void {
        var xl:uint = 128 * quality;
        var pinch:uint = xl / 3.6;
        // sky color from bottom to top;
        var color:Array = [brighten(C[0], 50), darken(C[0], 25), darken(C[0], 5), darken(C[1], 0), C[1], C[2], darken(C[2], 25), darken(C[2], 50)];
        var side:BitmapData = new BitmapData(xl, xl, false, color[1]);
        var top:BitmapData = new BitmapData(xl, xl, false, color[6]);
        var floor:BitmapData = new BitmapData(xl, xl, false, color[1]);
        // side
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(xl, xl, -Math.PI / 2)
        var g:Sprite = new Sprite();
        g.graphics.beginGradientFill('linear', [color[1], color[2], color[3], color[4], color[5], color[6]], [1, 1, 1, 1, 1, 1], [90, 110, 120, 126, 180, 230], matrix);
        g.graphics.drawRect(0, 0, xl, xl);
        g.graphics.endFill();
        var displacement_map:DisplacementMapFilter = new DisplacementMapFilter(pinchMap(xl, xl), new Point(0, 0), 4, 2, 0, pinch, "clamp")
        g.filters = [displacement_map];
        side.draw(g);
        // top
        matrix = new Matrix();
        g.graphics.clear();
        matrix.createGradientBox(xl, xl, 0, 0, 0);
        g.graphics.beginGradientFill('radial', [color[7], color[6]], [1, 1], [0, 255], matrix);
        g.graphics.drawEllipse(0, 0, xl, xl);
        g.graphics.endFill();
        top.draw(g);
        // bottom
        matrix = new Matrix();
        matrix.createGradientBox(xl, xl, 0, 0, 0);
        g.graphics.clear();
        g.graphics.beginGradientFill('radial', [color[0], color[1]], [1, 1], [0, 255], matrix);
        g.graphics.drawEllipse(0, 0, xl, xl);
        g.graphics.endFill();
        floor.draw(g);
        
        _skydata = new Vector.<BitmapData>();
        _skydata.push(side, top, floor);
        if (_sky) _sky.dispose();
        _sky = new BitmapCubeTexture(side, side, top, floor, side, side);
    }
    
    /** add some sphericale distortion */
    private function pinchMap(w:int, h:int):BitmapData {
        var i:int, BCol:Number, GCol:Number;
        var b:BitmapData = new BitmapData(w, h, false, 0x000000)
        var vx:int = w >> 1, vy:int = h >> 1;
        for (var j:int = 0; j < h; j++) {
            for ( i = 0; i < w; i++) {
                BCol = 127 + (i - vx) / (vx) * 127 * (1 - Math.pow((j - vy) / (vy), 2));
                GCol = 127 + (j - vy) / (vy) * 127 * (1 - Math.pow((i - vx) / (vx), 2));
                b.setPixel(i, j, (GCol << 8) | BCol);
            }
        }
        return b;
    }
    
    //-------------------------------- COLORS UTILS
        
    /** brighten color */
    public function brighten(hexColor:Number, percent:Number):Number {
        if (isNaN(percent)) percent = 0;
        if (percent > 100) percent = 100;
        if (percent < 0) percent = 0;
        var factor:Number = percent / 100, rgb:Object = hexToRgb(hexColor);
        rgb.r += (255 - rgb.r) * factor; rgb.b += (255 - rgb.b) * factor; rgb.g += (255 - rgb.g) * factor;
        return rgbToHex(Math.round(rgb.r), Math.round(rgb.g), Math.round(rgb.b));
    }
        
    /** darken color */
    public function darken(hexColor:Number, percent:Number):Number {
        if (isNaN(percent)) percent = 0;
        if (percent > 100) percent = 100;
        if (percent < 0) percent = 0;
        var factor:Number = 1 - (percent / 100), rgb:Object = hexToRgb(hexColor);
        rgb.r *= factor; rgb.b *= factor; rgb.g *= factor;
        return rgbToHex(Math.round(rgb.r), Math.round(rgb.g), Math.round(rgb.b));
    }
        
    /** conversion */
    public function rgbToHex(r:Number, g:Number, b:Number):Number { return (r << 16 | g << 8 | b); }
    public function hexToRgb(hex:Number):Object { return {r: (hex & 0xff0000) >> 16, g: (hex & 0x00ff00) >> 8, b: hex & 0x0000ff}; }
        
    /** apply color to object */
    public function color(o:DisplayObject, c:int=0, a:Number=1):void {
        if (!o) return;
        var nc:ColorTransform = o.transform.colorTransform;
        nc.color = c;
        nc.alphaMultiplier = a;
        if (c == 0) o.transform.colorTransform = new ColorTransform();
        else o.transform.colorTransform = nc;
    }
}


//-------------------------------------o
//           LOADING BITMAP            o
//-------------------------------------o

import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.system.LoaderContext;

internal class PhotoLoader extends Sprite {
    private var loader:Loader;
    public var content:BitmapData;
    public static const COMPLETE:String = Event.COMPLETE;

    public function PhotoLoader() {
        loader = new Loader();
    }
    public function load(file:String):void {
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, complete, false, 0, true);
        loader.load(new URLRequest(file), new LoaderContext(true));
    }
    private function complete(evt:Event):void {
        loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, complete);
        content = Bitmap(loader.contentLoaderInfo.content).bitmapData;
        dispatchEvent(new Event(PhotoLoader.COMPLETE));
        loader.unload();
        loader = null;
    }

}