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

forked from: [Alternativa3D 7.5] test

Get Adobe Flash player
by shigeok 23 Oct 2012
/**
 * Copyright shigeok ( http://wonderfl.net/user/shigeok )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/oI54
 */

// forked from tencho's [Alternativa3D 7.5] test
/**
 * Alternativa3D7.5の練習
 * Colladaモデルを読み込んでカメラを動かしているだけです
 * カメラの位置によってはエラーが出てしまうみたいで時々固まります。。
 */
package  {
    import alternativ7.engine3d.containers.BSPContainer;
    import alternativ7.engine3d.controllers.SimpleObjectController;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.Sorting;
    import alternativ7.engine3d.core.View;
    import alternativ7.engine3d.loaders.events.LoaderErrorEvent;
    import alternativ7.engine3d.loaders.events.LoaderProgressEvent;
    import alternativ7.engine3d.loaders.MaterialLoader;
    import alternativ7.engine3d.loaders.ParserCollada;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.materials.TextureMaterial;
    import alternativ7.engine3d.objects.Mesh;
    import com.bit101.components.CheckBox;
    import com.bit101.components.Label;
    import com.bit101.components.Style;
    import com.bit101.components.VBox;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.ColorTransform;
    import flash.geom.Vector3D;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.utils.Dictionary;
    import net.hires.debug.Stats;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.Quad;
    import org.libspark.betweenas3.tweens.ITween;
    import org.libspark.betweenas3.tweens.ITweenGroup;
    public class Alternativa3DTest extends Sprite {
        private var _autoCamera:Object3D = new Object3D();
        private var _userCamera:Object3D = new Object3D();
        private var _cameraMode:int = 0;
        private var _camera:Camera3D;
        private var _controller:SimpleObjectController;
        private var _scene:BSPContainer;
        private var _dragger:GlobeDragger;
        
        private var _stats:Stats;
        private var _bg:Sprite;
        private var _header:Sprite;
        private var _info:Label;
        private var _loadingTxt:Label;
        private var _wireMaterial:FillMaterial = new FillMaterial(0, 0, 0, 0xffffff);
        private var _rawTextures:Dictionary = new Dictionary();
        
        private var _loader:URLLoader;
        private var _parser:ParserCollada;
        private var _mloader:MaterialLoader;
        private var _isInitError:Boolean = false;
        
        private const _PATH_DIR:String = "http://www.morocoshi.net/asset/wonderfl/alt3dtest/";
        private const _PATH_DAE:String = "model_wdfl.DAE";
        
        /**
         * コンストラクタ
         */
        public function Alternativa3DTest() {
            stage.frameRate = 60;
            stage.quality = StageQuality.LOW;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.addEventListener(Event.RESIZE, onResize);
            
            _camera = new Camera3D();
            _camera.view = new View(465, 465);
            _camera.view.alpha = 0;
            _controller = new SimpleObjectController(stage, _camera, 1);
                        
            _scene = new BSPContainer();
            _scene.addChild(_camera);
            
            //マウスドラッグで動かすカメラ用
            _dragger = new GlobeDragger(this, 45, 2, 320);
            _dragger.enabled = false;
            _dragger.angleSpeed = _dragger.rotationSpeed = 0.75;
            _dragger.setAngleLimit( -7, 90);
            _dragger.setDistanceLimit(10, 420);
            
            var v:Vector3D = _dragger.position;
            _userCamera.x = v.x;
            _userCamera.y = v.z;
            _userCamera.z = v.y;
            
            //画面に配置するもの色々
            _bg = Painter.createColorRect(465, 465, 0x000000);
            _header = new Sprite();
            _header.addChild(Painter.createColorRect(465, 40, 0, 0.5));
            Style.LABEL_TEXT = 0x000000;
            new SwitchButton(_header, 10, 10, ["CAMERA : AUTO", "CAMERA : DRAG"], onSwitchCamera);
            new SwitchButton(_header, 120, 10, ["WIREFRAME : OFF", "WIREFRAME : ON"], onSwitchMaterial);
            Style.LABEL_TEXT = 0xFFFFFF;
            _info = new Label(_header, 230, 10, "");
            _loadingTxt = new Label(null, 10, 10, "LOADING COLLADA MODEL ...");
            _stats = new Stats( { bg:0x222222 } );
            Style.BACKGROUND = 0x444444;
            var vox:VBox = new VBox(_header);
            vox.x = 8;
            vox.y = 50;
            vox.spacing = 12;
            var chk1:CheckBox = new CheckBox(vox, 0, 0, "VOLUME LIGHT", onClickCheckBox);
            var chk2:CheckBox = new CheckBox(vox, 0, 0, "REFLECTION", onClickCheckBox);
            var chk3:CheckBox = new CheckBox(vox, 0, 0, "BSP SORTING", onClickCheckBox);
            chk1.tag = 0;
            chk2.tag = 1;
            chk3.tag = 2;
            chk1.selected = true;
            chk2.selected = true;
            chk3.selected = true;
            
            addChild(_bg);
            addChild(_loadingTxt);
            addChild(_camera.view);
            addChild(_header);
            addChild(_stats);
            
            _header.visible = false;
            
            onResize(null);
            startLoad();
        }
        private function onClickCheckBox(e:MouseEvent):void{
            var rb:CheckBox = e.currentTarget as CheckBox;
            switch(rb.tag) {
                case 0:
                    _scene.getChildByName("volumelight").visible = rb.selected;
                    break;
                case 1:
                    _scene.getChildByName("floor").blendMode = (rb.selected)? BlendMode.ADD : BlendMode.NORMAL;
                    break;
                case 2:
                    setBSPEnabled(rb.selected);
                    break;
            }
        }
        /**
         * BSPソートとZソートを切り替える
         * @param    enabled
         */
        private function setBSPEnabled(enabled:Boolean):void{
            for (var i:int = 0; i < _scene.numChildren; i++) {
                var m:Mesh = _scene.getChildAt(i) as Mesh;
                if (!m) continue;
                if (["floor", "sunlight", "containerbox", "truss", "poles"].indexOf(m.name) != -1) {
                    m.sorting = (enabled)? Sorting.DYNAMIC_BSP : Sorting.AVERAGE_Z;
                }
            }
        }
        /**
         * カメラモード切り替え
         */
        private function onSwitchCamera(e:MouseEvent, mode:int):void {
            _cameraMode = mode;
            _dragger.enabled = (_cameraMode == 1);
            onTick(null);
        }
        /**
         * マテリアル張り替え
         */
        private function onSwitchMaterial(e:MouseEvent, mode:int):void {
            for (var i:int = 0; i < _scene.numChildren; i++) {
                var o:Object3D = _scene.getChildAt(i);
                if (o is Mesh) {
                    var m:Mesh = o as Mesh;
                    m.setMaterialToAllFaces(mode? _wireMaterial : _rawTextures[m]);
                }
            }
            _camera.render();
        }
        /**
         * 画面リサイズ時
         */
        private function onResize(e:Event):void {
            var sw:Number = stage.stageWidth;
            var sh:Number = stage.stageHeight;
            _bg.width = sw;
            _bg.height = sh;
            _stats.y = sh - 100;
            _camera.view.width = sw;
            _camera.view.height = sh;
            _camera.render();
            _header.getChildAt(0).width = sw;
        }
        /**
         * Collada読み込み開始
         */
        private function startLoad():void {
            _loader = new URLLoader();
            _loader.addEventListener(Event.COMPLETE, onLoadCollada);
            _loader.addEventListener(IOErrorEvent.IO_ERROR, onErrorAsset);
            _loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onErrorAsset);
            _loader.load(new URLRequest(_PATH_DIR + _PATH_DAE));
        }
        private function onErrorAsset(e:ErrorEvent):void {
            _loadingTxt.text = e.text;
            _loadingTxt.transform.colorTransform = new ColorTransform(0, 0, 0, 1, 0xFF, 0, 0);
            _isInitError = true;
        }        
        /**
         * Colladaモデル読み込み完了時
         * @param    e
         */
        private function onLoadCollada(e:Event):void {
            //Colladaファイルをパース
            _parser = new ParserCollada();
            _parser.parse(new XML(_loader.data), _PATH_DIR);
            
            //テクスチャ読み込み
            _mloader = new MaterialLoader();
            _mloader.addEventListener(LoaderErrorEvent.LOADER_ERROR, onErrorAsset);
            _mloader.addEventListener(LoaderProgressEvent.LOADER_PROGRESS, onProgressMaterial);
            _mloader.addEventListener(Event.COMPLETE, onCompleteMaterial);
            _mloader.load(_parser.textureMaterials, new LoaderContext(true));
        }
        private function onProgressMaterial(e:LoaderProgressEvent):void {
            if (_isInitError) return;
            var per:Number = e.totalProgress;
            _loadingTxt.text = "LOADING COLLADA MODEL ... " + int(per * 100) + "%";
        }
        /**
         * テクスチャ読み込み完了時
         * @param    e
         */
        private function onCompleteMaterial(e:Event):void {
            //マテリアルの読み込みに失敗していたら処理停止
            if (_isInitError) return;
            addEventListener(Event.ENTER_FRAME, onTick);
            //黒画面からのフェードイン
            BetweenAS3.to(_camera.view, { alpha:1 }, 2, Quad.easeIn).play();
            _header.visible = true;
            _loadingTxt.visible = false;
            
            //全テクスチャのリピートをOFFにする
            for each(var tm:TextureMaterial in _parser.textureMaterials) tm.repeat = false;
            
            //天井からの光の筋
            _parser.getObjectByName("volumelight").blendMode = BlendMode.OVERLAY;
            //床
            _parser.getObjectByName("floor").blendMode = BlendMode.ADD;
            
            var totalFaceNum:int = 0;
            var cameras:Vector.<Object3D> = new Vector.<Object3D>();
            
            for each(var o:Object3D in _parser.objects) {
                if (!o.name) continue;
                _scene.addChild(o);
                if (o is Mesh) {
                    var m:Mesh = o as Mesh;
                    _rawTextures[m] = m.geometry.orderedFaces[0].material;
                    totalFaceNum += m.geometry.orderedFaces.length;
                } else if (o.name.indexOf("Camera") != -1) {
                    //カメラリストに追加
                    cameras.push(o);
                }
            }
            setBSPEnabled(true);
            _info.text = "TOTAL FACES: " + totalFaceNum;
            //カメラリストを名前順にソート
            cameras.sort(function(a:Object3D, b:Object3D):int { return int(a.name > b.name) - int(a.name < b.name) } );
            
            //自動カメラの動きをBetweenAS3で設定する
            var list:Array = [];
            var leng:int = cameras.length;
            for (var i:int = 0; i < leng; i++) {
                var cf:Object3D = cameras[i];
                var ct:Object3D = cameras[(i + 1) % leng];
                var it:ITween = BetweenAS3.tween(
                    _autoCamera,
                    { x:ct.x, y:ct.y, z:ct.z, rotationX:ct.rotationX, rotationY:ct.rotationY, rotationZ:ct.rotationZ },
                    { x:cf.x, y:cf.y, z:cf.z, 
                        rotationX:Angle.toNearRadian(cf.rotationX, ct.rotationX),
                        rotationY:Angle.toNearRadian(cf.rotationY, ct.rotationY),
                        rotationZ:Angle.toNearRadian(cf.rotationZ, ct.rotationZ)
                    },
                    2.5,
                    Quad.easeInOut
                );
                it = BetweenAS3.delay(it, 0.5, 0);
                list.push(it);
            }
            if (leng) {
                var itg:ITweenGroup = BetweenAS3.serialTweens(list);
                itg.stopOnComplete = false;
                itg.play();
            }
            
            onResize(null);
        }
        /**
         * 毎フレーム処理
         * @param    e
         */
        private function onTick(e:Event):void {
            if (_cameraMode == 0) {
                //自動カメラモード
                _controller.setObjectPosXYZ(_autoCamera.x, _autoCamera.y, _autoCamera.z);
                _controller.lookAtXYZ(0, 0, 0);
                _camera.rotationX = _autoCamera.rotationX;
                _camera.rotationY = _autoCamera.rotationY;
                _camera.rotationZ = _autoCamera.rotationZ;
            } else {
                //ドラッグカメラモード
                var v:Vector3D = _dragger.position;
                _userCamera.x += (v.x - _userCamera.x) * 0.3;
                _userCamera.y += (v.z - _userCamera.y) * 0.3;
                _userCamera.z += (v.y - _userCamera.z) * 0.3;
                _controller.setObjectPosXYZ(_userCamera.x, _userCamera.y, _userCamera.z + 80);
                _controller.lookAtXYZ(0, 0, 80);
            }
            _camera.render();
        }
    }
}
import com.bit101.components.PushButton;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Vector3D;
class Angle {
    static public const PI2:Number = Math.PI * 2;
    /**
     * baseのラジアン度をnearに一番近くなるよう再設定(+Math.PI*2/-Math.PI*2)する
     */
    static public function toNearRadian(base:Number, near:Number):Number {
        var rad:Number = base - near;
        rad = (rad % PI2 + PI2) % PI2;
        if (rad > Math.PI) rad -= PI2;
        return rad + near;
    }
}
/**
 * シーンをマウスでぐるぐる
 */
class GlobeDragger extends EventDispatcher {
    public var zoomSpeed:Number = 1.2;
    public var rotationSpeed:Number = 1;
    public var angleSpeed:Number = 1;
    public var distanceMin:Number = NaN;
    public var distanceMax:Number = NaN;
    public var rotationMin:Number = NaN;
    public var rotationMax:Number = NaN;
    public var angleMin:Number = NaN;
    public var angleMax:Number = NaN;
    
    private var _distance:Number;
    private var _rotation:Number;
    private var _angle:Number;
    private var _enabled:Boolean = true;
    private var _eventObj:InteractiveObject;
    private var _saveRotation:Number;
    private var _saveAngle:Number;
    private var _saveMousePos:Point;
    private var _position:Vector3D = new Vector3D();
    
    public var onMoveCamera:Function;
    
    public function get position():Vector3D { return _position; }
    public function get enabled():Boolean { return _enabled; }
    public function set enabled(value:Boolean):void {
        onMsUp();
        _enabled = value;
    }
    
    /**
     * @param    obj    マウスイベントを登録する場所
     * @param    rotation    初期の横方向角度
     * @param    angle    初期の縦方向角度
     * @param    distance    初期の中心点からの距離
     */
    public function GlobeDragger(obj:InteractiveObject, rotation:Number = 0, angle:Number = 30, distance:Number = 1000) {
        _distance = distance;
        _angle = angle;
        _rotation = rotation;
        _eventObj = obj;
        _eventObj.addEventListener(MouseEvent.MOUSE_DOWN, onMsDown);
        _eventObj.stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMsWheel);
    }
    private function dispose():void {
        _eventObj.removeEventListener(MouseEvent.MOUSE_DOWN, onMsDown);
        _eventObj.stage.removeEventListener(MouseEvent.MOUSE_UP, onMsUp);
        _eventObj.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMsWheel);
        _eventObj.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
    }
    private function onMsWheel(e:MouseEvent):void {
        if (!_enabled) return;
        var vec:int = (e.delta < 0)? -1 : 1;
        _distance *= Math.pow(zoomSpeed, -vec);
        _distance = checkLimit(_distance, distanceMin, distanceMax);
        updatePosition();
    }
    public function dispatch():void {
        dispatchEvent(new Event(Event.CHANGE));
        if (onMoveCamera != null) onMoveCamera.apply(null, [_position]);
    }
    public function setDistanceLimit(min:Number, max:Number):void {
        distanceMin = min;
        distanceMax = max;
    }
    public function setAngleLimit(min:Number, max:Number):void {
        angleMin = min;
        angleMax = max;
    }
    public function setRotationLimit(min:Number, max:Number):void {
        rotationMin = min;
        rotationMax = max;
    }
    private function onMsDown(e:MouseEvent):void {
        if (!_enabled) return;
        _eventObj.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
        _eventObj.stage.addEventListener(MouseEvent.MOUSE_UP, onMsUp);
        _saveRotation = _rotation;
        _saveAngle = _angle;
        _saveMousePos = new Point(_eventObj.mouseX, _eventObj.mouseY);
    }
    private function onMsMove(e:MouseEvent):void {
        if (!_enabled) return;
        var dragOffset:Point = new Point(_eventObj.mouseX, _eventObj.mouseY).subtract(_saveMousePos);
        _rotation = _saveRotation - dragOffset.x * rotationSpeed;
        _rotation = checkLimit(_rotation, rotationMin, rotationMax);
        _angle = Math.max(-89, Math.min(89, _saveAngle + dragOffset.y * angleSpeed));
        _angle = checkLimit(_angle, angleMin, angleMax);
        updatePosition();
    }
    private function checkLimit(num:Number, min:Number, max:Number):Number {
        if (!isNaN(min) && num < min) num = min;
        if (!isNaN(max) && num > max) num = max;
        return num;
    }
    private function onMsUp(...rest):void {
        _eventObj.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
        _eventObj.stage.removeEventListener(MouseEvent.MOUSE_UP, onMsUp);
        updatePosition();
    }
    private function updatePosition():void {
        var per:Number = Math.cos(Math.PI / 180 * _angle);
        var px:Number = Math.cos(Math.PI / 180 * _rotation) * _distance * per;
        var py:Number = Math.sin(Math.PI / 180 * _angle) * _distance;
        var pz:Number = Math.sin(Math.PI / 180 * _rotation) * _distance * per;
        _position = new Vector3D(px, py, pz)
        dispatch();
    }
}
/**
 * クリックでラベルが切り替わるボタン
 */
class SwitchButton extends PushButton {
    private var _mode:int = 0;
    private var _labels:Array = [];
    private var _switchFunc:Function;
    public function get mode():int { return _mode; }
    public function SwitchButton(parent:DisplayObjectContainer = null, x:Number = 0, y:Number = 0, labels:Array = null, clickFunc:Function = null) {
        _switchFunc = clickFunc;
        _labels = (labels == null)? [""] : labels.concat();
        if (_labels.length == 0) _labels = [""];
        super(parent, x, y, _labels[0], onClick);
    }
    public function setMode(mode:int):void {
        _mode = mode;
        label = _labels[mode];
    }
    private function onClick(e:MouseEvent):void {
        setMode(++_mode % _labels.length);
        //引数の数が足りない場合は処理を振り分ける
        if (_switchFunc != null) {
            try {
                _switchFunc.apply(null, [e, _mode]);
            } catch (error:Error) {
                try {
                    _switchFunc.apply(null, [e]);
                } catch (error:Error) {
                    _switchFunc.apply(null, []);
                }
            }
        }
    }
}
class Painter {
    /**
     * べた塗りスプライト生成
     */
    static public function createColorRect(width:Number, height:Number, color:uint = 0x000000, alpha:Number = 1, x:Number = 0, y:Number = 0):Sprite {
        var sp:Sprite = new Sprite();
        sp.graphics.beginFill(color, alpha);
        sp.graphics.drawRect(0, 0, width, height);
        sp.graphics.endFill();
        sp.x = x;
        sp.y = y;
        return sp;
    }
}