// forked from narutohyper's noFlashSeal(偽物) // forked from clockmaker's [Alternativa3D] Basic Template package { import alternativ5.engine3d.materials.MovieClipMaterial; import alternativ5.engine3d.materials.FillMaterial; import alternativ5.engine3d.primitives.Plane; import flash.display.Shape; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import alternativ5.engine3d.core.Object3D; import alternativ5.engine3d.primitives.Box; import alternativ5.engine3d.primitives.Cone; import alternativ5.engine3d.events.MouseEvent3D; import alternativ5.types.Point3D; import flash.display.Sprite; import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.Loader; import flash.net.URLRequest; import flash.geom.Matrix; import flash.events.Event; import flash.utils.ByteArray; import flash.net.*; import org.libspark.thread.EnterFrameThreadExecutor; import org.libspark.thread.Thread; [SWF(width = 465, height = 465, frameRate = 60)] /* 自分用に作っただけなので、特に深い意図は無いです、 中に配置する画像(背景が透明のPNG)をロード。 */ /** * Alternativa3D を簡単に扱うためのベーシックテンプレート * @author Yasu (clockmaker) */ public class SimpleDemo extends Sprite { public var img1:Loader public var template:BasicTemplate public var mc1:MovieClip; public var plane:Plane; public function SimpleDemo():void { // テンプレートを作成します var bg:Shape = new Shape(); bg.graphics.beginFill(0x0); bg.graphics.drawRect(110, 200, 200, 200); bg.graphics.endFill(); addChild(bg); var template:BasicTemplate = new BasicTemplate(); addChild(template); template.camera.coords=new Point3D(-800,-800,700); Thread.initialize(new EnterFrameThreadExecutor()); new MainThread(this).start(); img1 = new Loader(); //img2 = new Loader(); img1.load(new URLRequest('http://assets.wonderfl.net/images/related_images/a/a2/a235/a23539b3cebd3c86ed745a2ae2afae32bfa32bfc')); addChild(img1); //img1.alpha = 0.2; img1.x = (465 - 341) >> 1; img1.y = (465 - 450) >> 1; mc1=new MovieClip() //MovieClipMaterialのスケーリングにバグがあるので、以下の対処方で処理 var clipWidth:int = 200; var clipHeight:int = 200; mc1.scaleY = clipWidth/clipHeight; var matrix:Matrix = new Matrix(1, 0, 0, clipWidth/clipHeight); var mcm1:MovieClipMaterial=new MovieClipMaterial(mc1,clipWidth,clipWidth,null,matrix,true) // プリミティブを作成します plane = new Plane(200, 200, 20, 20); plane.rotationX = 90; plane.setMaterialToSurface(mcm1, 'front'); template.scene.root.addChild(plane); var pos:Point3D = new Point3D(); pos.x = plane.x; pos.y = plane.y; pos.z = plane.z; template.cameraContoller.lookAt(pos); with(template.camera) { x = 907.2257738784996 y = -2246.0827362651494 z = -1944.3373132335682 rotationX = -0.863937979737193 rotationY = -0.11999999999999998 rotationZ = 0.2617993877991494 fov = 0.22689280275926252 } stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler); stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown); stage.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler ); stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler ); stage.addEventListener( Event.MOUSE_LEAVE, mouseUpHandler ); } private function mouseUpHandler(e:Event):void { stage.removeEventListener( MouseEvent.MOUSE_MOVE, moveHandler ); stage.removeEventListener( MouseEvent.MOUSE_MOVE, scaleHandler ); } private function mouseDownHandler(e:MouseEvent):void { pastX = mouseX; pastY = mouseY; if (shiftKey) { stage.addEventListener( MouseEvent.MOUSE_MOVE, scaleHandler ); } else { stage.addEventListener( MouseEvent.MOUSE_MOVE, moveHandler ); } } private function scaleHandler(e:MouseEvent):void { plane.scaleX += ( pastY - mouseY ) * .01; plane.scaleY = plane.scaleX; pastY = mouseY; } private var pastX:Number = 0; private var pastY:Number = 0; private var shiftKey:Boolean = false; private function moveHandler(e:MouseEvent):void { plane.x -= pastX - mouseX; plane.y -= pastY - mouseY; pastX = mouseX; pastY = mouseY; } private function KeyDownHandler(e:KeyboardEvent):void { if (e.keyCode == 16) { shiftKey = true; } } private function keyUpHandler(e:KeyboardEvent):void { if (e.keyCode == 16) { shiftKey = false; } } private function KeyDown(e:KeyboardEvent):void{ if (e.keyCode == 38) { plane.z += 2; } if (e.keyCode == 37) { plane.x -= 2; } if (e.keyCode == 40) { plane.z -= 2; } if (e.keyCode == 39) { plane.x += 2; } } } } import org.libspark.thread.Thread; import flash.events.Event; import flash.events.MouseEvent; import flash.display.SimpleButton; import flash.utils.ByteArray; import flash.net.FileReference; import flash.net.FileReferenceList; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.display.*; import flash.text.*; import flash.system.Security; class MainThread extends Thread { public static const CROSSDOMAIN:String = "http://assets.wonderfl.net/crossdomain.xml"; private var _base:SimpleDemo; private var _loadButton:Button; private var _saveButton:Button; private var _original:Loader; private var _guide:Guide; private var bmd1:BitmapData private var bm1:Bitmap public function MainThread(base:SimpleDemo) { this._base = base; this._loadButton = this._base.addChild(new Button('LOAD', 60)) as Button; this._loadButton.x = this._loadButton.y = 1; this._saveButton = this._base.addChild(new Button('SAVE', 60)) as Button; this._saveButton.x = 1; this._saveButton.y = this._loadButton.height + 2; this._guide = this._base.addChild(new Guide()) as Guide; this._guide.x = (465 - 341) >> 1; this._guide.y = (465 - 450) >> 1; this.bmd1=new BitmapData(200,200,false,0x0) this.bm1=new Bitmap() } protected override function run():void { this._event(); } private function _event():void { event(this._loadButton, MouseEvent.CLICK, this._loadImage); event(this._saveButton, MouseEvent.CLICK, this._saveImage); Security.loadPolicyFile(CROSSDOMAIN); } // load image private function _loadImage(e:MouseEvent):void { trace(Button(e.target).label) var file:FileReference = new FileReference(); event(file, Event.SELECT, this._loadFileSelected); event(file, Event.CANCEL, this._loadFileCancel); file.browse(); } private function _loadFileSelected(e:Event):void { var file:FileReference = FileReference(e.target); event(file, Event.COMPLETE, this._fileLoaded); file.load(); } private function _fileLoaded(e:Event):void { if (this._original) { //this._original.parent.removeChild(this._original); this._original.unload(); } this._original = new Loader(); this._original.loadBytes(FileReference(e.target).data); event(this._original.contentLoaderInfo, Event.COMPLETE, this._imageLoaded); } private function _loadFileCancel(e:Event):void { this._event(); } private function _imageLoaded(e:Event):void { var a:Number = 200 / this._original.height; var mtr:Matrix=new Matrix(a,0,0,a,(200-(this._original.width*a))/2,(200-(this._original.height*a))/2) this.bmd1=new BitmapData(200,200,false,0x0) this.bmd1.draw(this._original.content,mtr) this.bm1.bitmapData=bmd1 this._base.mc1.addChild(this.bm1) this._event(); } // save image private function _saveImage(e:Event):void { var raw:BitmapData = new BitmapData(341, 450, true, 0x0); this._guide.visible = false; raw.draw(this._base, new Matrix(1, 0, 0, 1, -this._guide.x, -this._guide.y), null, null, null, true); this._guide.visible = true; var png:ByteArray = PNGEnc.encode(raw); raw.dispose(); var file:FileReference = new FileReference(); event(file, Event.SELECT, this._saveFileSelected); event(file, Event.CANCEL, this._saveFileSelected); file.save(png, 'pad.png'); } private function _saveFileSelected(e:Event):void { this._event(); } } class Guide extends Shape { public function Guide() { var g:Graphics = this.graphics; g.lineStyle(1, 0xFFFFFF, 0.3, true); g.drawRect(0, 0, 341, 450); } } class Button extends SimpleButton { public var label:String public function Button(_label:String, width:int = 0):void { label=_label var up:Sprite = _buildImage(label, 0x0, width); var over:Sprite = _buildImage(label, 0x333333, width); var down:Sprite = _buildImage(label, 0x333333, width); down.y = 1; super(up, over, down, up); } private static function _buildImage(label:String, color:int, width:int = 0):Sprite { var text:TextField = new TextField(); text.defaultTextFormat = new TextFormat('Verdana', 10, 0xffffff, true, null, null, null, null, TextFormatAlign.CENTER); text.autoSize = TextFieldAutoSize.LEFT text.selectable = false; text.text = label; text.x = (width - text.width) >> 1; text.y = 5; var base:Shape = new Shape(); var g:Graphics = base.graphics; g.beginFill(color); g.drawRect(0, 0, width, text.height + 10); g.endFill(); var sp:Sprite = new Sprite(); sp.addChild(base); sp.addChild(text); return sp; } } import alternativ5.engine3d.controllers.CameraController; import alternativ5.engine3d.core.Camera3D; import alternativ5.engine3d.core.Object3D; import alternativ5.engine3d.core.Scene3D; import alternativ5.engine3d.display.View; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; /** * BasicTemplate for Alternativa3D * Alternativa3Dを扱いやすくするためのテンプレートです * @author Yasu */ class BasicTemplate extends Sprite{ /** * シーンインスタンスです。 */ public var scene:Scene3D; /** * ビューインスタンスです。 */ public var view:View; /** * カメラインスタンスです。 */ public var camera:Camera3D; /** * カメラコントローラーです。 */ public var cameraContoller:CameraController; private var _viewWidth:int; private var _viewHeight:int; private var _scaleToStage:Boolean; /** * 新しい BasicTemplate インスタンスを作成します。 * @param viewWidth * @param viewHeight * @param scaleToStage */ public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) { _viewWidth = viewWidth; _viewHeight = viewHeight; _scaleToStage = scaleToStage; // Creating scene scene = new Scene3D(); scene.splitAnalysis = false; // not analysis for performance scene.root = new Object3D(); // Adding camera camera = new Camera3D(); camera.z = -1000; scene.root.addChild(camera); // camera contoller cameraContoller = new CameraController(this); cameraContoller.camera = camera; // set view view = new View(); view.camera = camera; addChild(view); // stage if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } /** * 初期化されたときに実行されるイベントです。 * 初期化時に実行したい処理をオーバーライドして記述します。 */ protected function atInit():void {} /** * 初期化されたときに実行されるイベントです。 * 初期化時に実行したい処理を記述します。 */ private var _onInit:Function = function():void { }; public function get onInit():Function { return _onInit; } public function set onInit(value:Function):void { _onInit = value; } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング前に実行したい処理をオーバーライドして記述します。 */ protected function atPreRender():void {} /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング前に実行したい処理を記述します。 */ private var _onPreRender:Function = function():void{}; public function get onPreRender():Function { return _onPreRender; } public function set onPreRender(value:Function):void { _onPreRender = value; } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング後に実行したい処理をオーバーライドして記述します。 */ protected function atPostRender():void { } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング後に実行したい処理を記述します。 */ protected var _onPostRender:Function = function():void{}; public function get onPostRender():Function { return _onPostRender; } public function set onPostRender(value:Function):void { _onPostRender = value; } /** * レンダリングを開始します。 */ public function startRendering():void { addEventListener(Event.ENTER_FRAME, onRenderTick); } /** * レンダリングを停止します。 */ public function stopRendering():void { removeEventListener(Event.ENTER_FRAME, onRenderTick); } /** * シングルレンダリング(レンダリングを一回だけ)を実行します。 */ public function singleRender():void { onRenderTick(); } /** * @private */ private function init(e:Event = null):void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.HIGH; // resize stage.addEventListener(Event.RESIZE, onResize); onResize(null); // render startRendering(); atInit(); _onInit(); } /** * @private */ private function onRenderTick(e:Event = null):void { atPostRender(); _onPostRender(); scene.calculate(); atPreRender(); _onPreRender(); } /** * @private */ private function onResize(event:Event = null):void { if (_scaleToStage) { view.width = stage.stageWidth; view.height = stage.stageHeight; }else { view.width = _viewWidth; view.height = _viewHeight; } } } // http://www.5etdemi.com/blog/archives/2006/12/as3-png-encoder-faster-better/ class PNGEnc { public static function encode(img:BitmapData, type:uint = 0):ByteArray { // Create output byte array var png:ByteArray = new ByteArray(); // Write PNG signature png.writeUnsignedInt(0x89504e47); png.writeUnsignedInt(0x0D0A1A0A); // Build IHDR chunk var IHDR:ByteArray = new ByteArray(); IHDR.writeInt(img.width); IHDR.writeInt(img.height); if(img.transparent || type == 0) { IHDR.writeUnsignedInt(0x08060000); // 32bit RGBA } else { IHDR.writeUnsignedInt(0x08020000); //24bit RGB } IHDR.writeByte(0); writeChunk(png,0x49484452,IHDR); // Build IDAT chunk var IDAT:ByteArray= new ByteArray(); switch(type) { case 0: writeRaw(img, IDAT); break; case 1: writeSub(img, IDAT); break; } IDAT.compress(); writeChunk(png,0x49444154,IDAT); // Build IEND chunk writeChunk(png,0x49454E44,null); // return PNG return png; } private static function writeRaw(img:BitmapData, IDAT:ByteArray):void { var h:int = img.height; var w:int = img.width; var transparent:Boolean = img.transparent; for(var i:int=0;i < h;i++) { // no filter if ( !transparent ) { var subImage:ByteArray = img.getPixels( new Rectangle(0, i, w, 1)); //Here we overwrite the alpha value of the first pixel //to be the filter 0 flag subImage[0] = 0; IDAT.writeBytes(subImage); //And we add a byte at the end to wrap the alpha values IDAT.writeByte(0xff); } else { IDAT.writeByte(0); var p:uint; for(var j:int=0;j < w;j++) { p = img.getPixel32(j,i); IDAT.writeUnsignedInt( uint(((p&0xFFFFFF) << 8)| (p>>>24))); } } } } private static function writeSub(img:BitmapData, IDAT:ByteArray):void { var r1:uint; var g1:uint; var b1:uint; var a1:uint; var r2:uint; var g2:uint; var b2:uint; var a2:uint; var r3:uint; var g3:uint; var b3:uint; var a3:uint; var p:uint; var h:int = img.height; var w:int = img.width; for(var i:int=0;i < h;i++) { // no filter IDAT.writeByte(1); if ( !img.transparent ) { r1 = 0; g1 = 0; b1 = 0; a1 = 0xff; for(var j:int=0;j < w;j++) { p = img.getPixel(j,i); r2 = p >> 16 & 0xff; g2 = p >> 8 & 0xff; b2 = p & 0xff; r3 = (r2 - r1 + 256) & 0xff; g3 = (g2 - g1 + 256) & 0xff; b3 = (b2 - b1 + 256) & 0xff; IDAT.writeByte(r3); IDAT.writeByte(g3); IDAT.writeByte(b3); r1 = r2; g1 = g2; b1 = b2; a1 = 0; } } else { r1 = 0; g1 = 0; b1 = 0; a1 = 0; for(j=0;j < w;j++) { p = img.getPixel32(j,i); a2 = p >> 24 & 0xff; r2 = p >> 16 & 0xff; g2 = p >> 8 & 0xff; b2 = p & 0xff; r3 = (r2 - r1 + 256) & 0xff; g3 = (g2 - g1 + 256) & 0xff; b3 = (b2 - b1 + 256) & 0xff; a3 = (a2 - a1 + 256) & 0xff; IDAT.writeByte(r3); IDAT.writeByte(g3); IDAT.writeByte(b3); IDAT.writeByte(a3); r1 = r2; g1 = g2; b1 = b2; a1 = a2; } } } } private static var crcTable:Array; private static var crcTableComputed:Boolean = false; private static function writeChunk(png:ByteArray, type:uint, data:ByteArray):void { var c:uint; if (!crcTableComputed) { crcTableComputed = true; crcTable = []; for (var n:uint = 0; n < 256; n++) { c = n; for (var k:uint = 0; k < 8; k++) { if (c & 1) { c = uint(uint(0xedb88320) ^ uint(c >>> 1)); } else { c = uint(c >>> 1); } } crcTable[n] = c; } } var len:uint = 0; if (data != null) { len = data.length; } png.writeUnsignedInt(len); var p:uint = png.position; png.writeUnsignedInt(type); if ( data != null ) { png.writeBytes(data); } var e:uint = png.position; png.position = p; c = 0xffffffff; for (var i:int = 0; i < (e-p); i++) { c = uint(crcTable[ (c ^ png.readUnsignedByte()) & 0xff] ^ (c >>> 8)); } c = uint(c^uint(0xffffffff)); png.position = e; png.writeUnsignedInt(c); } } 某Pad