/* * Scratch Project Editor and Player * Copyright (C) 2014 Massachusetts Institute of Technology * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package { import com.adobe.utils.*; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.display.Shape; import flash.display.Sprite; import flash.display.Stage3D; import flash.display3D.*; import flash.events.ErrorEvent; import flash.events.Event; import flash.events.KeyboardEvent; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Matrix3D; import flash.geom.Point; import flash.geom.Rectangle; import flash.geom.Vector3D; import flash.utils.ByteArray; import flash.utils.Dictionary; import flash.utils.Endian; /** * A display object container which renders in 3D instead * @author Shane M. Clements, shane.m.clements@gmail.com */ public class DisplayObjectContainerIn3D extends Sprite implements IRenderIn3D { private var contextRequested:Boolean = false; /** Context to create textures on */ private var __context:Context3D; private var program:Program3D; private var indexBuffer:IndexBuffer3D; private var vertexBuffer:VertexBuffer3D; private var fragmentShaderAssembler:AGALMiniAssembler; private var vertexShaderAssembler:AGALMiniAssembler; private var spriteBitmaps:Dictionary; private var spriteRenderOpts:Dictionary; private var bitmapsByID:Object; /** Texture data */ private var textures:Array; private var testBMs:Array; private var textureIndexByID:Object; private static var texSize:int = 2048; private var penPacked:Boolean; /** Triangle index data */ //private var indexData:Vector. = new []; private var indexData:ByteArray = new ByteArray(); /** Vertex data for all sprites */ //private var vertexData:Vector. = new []; private var vertexData:ByteArray = new ByteArray(); private var projMatrix:Matrix3D; private var textureCount:int; private var childrenChanged:Boolean; private var movedChildren:Dictionary; private var unrenderedChildren:Dictionary; private var stampsByID:Object; private var indexBufferUploaded:Boolean; private var vertexBufferUploaded:Boolean; private var uiContainer:StageUIContainer; private var scratchStage:Sprite; private var stagePenLayer:DisplayObject; private var stage3D:Stage3D; private var pixelateAll:Boolean; private var statusCallback:Function; /** * Make the texture * @param context Context to create textures on * @param sprite Sprite to use for the texture * @param bgColor Background color of the texture */ public function DisplayObjectContainerIn3D() { uiContainer = new StageUIContainer(); uiContainer.graphics.lineStyle(1); spriteBitmaps = new Dictionary(); spriteRenderOpts = new Dictionary(); fragmentShaderAssembler = new AGALMiniAssembler(); vertexShaderAssembler = new AGALMiniAssembler(); bitmapsByID = {}; textureIndexByID = {}; textures = []; cachedOtherRenderBitmaps = new Dictionary(); penPacked = false; testBMs = []; textureCount = 0; childrenChanged = false; pixelateAll = false; movedChildren = new Dictionary(); unrenderedChildren = new Dictionary(); stampsByID = {}; indexData.endian = Endian.LITTLE_ENDIAN; vertexData.endian = Endian.LITTLE_ENDIAN; indexBufferUploaded = false; vertexBufferUploaded = false; } public function setStatusCallback(callback:Function):void { statusCallback = callback; } public function setStage(stage:Sprite, penLayer:DisplayObject):void { if(scratchStage) { scratchStage.removeEventListener(Event.ADDED_TO_STAGE, addedToStage); scratchStage.removeEventListener(Event.ADDED, childAdded); scratchStage.removeEventListener(Event.REMOVED, childRemoved); scratchStage.removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStage); if(scratchStage.stage) scratchStage.stage.removeEventListener(Event.RESIZE, onStageResize); scratchStage.cacheAsBitmap = true; (scratchStage as Object).img.cacheAsBitmap = true; scratchStage.visible = true; while(uiContainer.numChildren) scratchStage.addChild(uiContainer.getChildAt(0)); for(var i:int=0; i vertexData.length) { // Increase and fill in the index buffer var index:uint = indexData.length; var base:int = (index/12)*4; indexData.length = numChildren * 12; indexData.position = index; var numAdded:int = (indexData.length - index) / 12; for(var i:int=0; i> 1); //trace('indexBuffer created'); indexBuffer.uploadFromByteArray(indexData, 0, 0, indexData.length >> 1); indexBufferUploaded = true; //trace('indexBuffer uploaded'); vertexBuffer = __context.createVertexBuffer((indexData.length/12)*4, vStride); vertexBufferUploaded = false; } } else { indexBufferUploaded = false; vertexBufferUploaded = false; } } private var childrenDrawn:int = 0; private var tlPoint:Point; private function draw():void { checkBuffers(); var textureDirty:Boolean = false; var numChildren:uint = scratchStage.numChildren; var i:int; var dispObj:DisplayObject; if(childrenChanged) { if(debugTexture) { uiContainer.graphics.clear(); uiContainer.graphics.lineStyle(1); } for(i=0; i