Pfffft… not to have it rotten on my harddrive here my example of the modified sliced cube PV3D from John Lindquist. Here’s my code (making the “pile of crap” even bigger
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import mx.core.BitmapAsset;
import src.holder;
import gs.TweenMax;
import gs.easing.Quad;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.primitives.Plane;
//[SWF(width="752", height="552", backgroundColor="0xffffff", frameRate="31")]
public class SlicedCube extends BasicView
{
private var _cubeWidth:Number = 620;
// vars
private var mouseDownX:Number = 0;
private var targetRotation:Number = 0;
private var NUM_SLICES:int = 5;
private var _offsetX:int = 30;
private var _offsetY:int = 30;
private var cubes:Array = [];
private var _xml:XML;
private var _xmlLoader:URLLoader;
private var _xmlSource:String = '03_playlist.xml';
private var _numSlides:int; // number of assets in XML
private var _slideNum:int; // index pointer in _XML; starts with 3, because all sides are skinned in the first place
private var _pictures:XMLList;
private var _h:holder; // TEMP MC for composition of image, text - changeSide
private var _mcBottom:holder;
private var _mcTop:holder;
private var _mcBack:holder;
private var _mcFront:holder;
private var _matFront:Bitmap;
private var _matTop:Bitmap;
private var _matBack:Bitmap;
private var _matBottom:Bitmap;
private var _shownSide:Array = new Array("back", "bottom", "front", "top");
private var _shownSidePointer:int = 0;
private var _sideToSkin:String;
public function SlicedCube()
{
//super(_cubeWidth, 752);
//opaqueBackground = 0x000000;
camera.focus = 100;
camera.zoom = 10;
camera.ortho = false;
// init holder(s) with XML data
// read XML
// ...
_xmlLoader = new URLLoader();
_xmlLoader.load(new URLRequest(_xmlSource));
_xmlLoader.addEventListener(Event.COMPLETE, processXML);
// <---
this.addEventListener( Event.ENTER_FRAME, onRenderTick );
//skinCubes(h, "top");
//scene.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
}
private function processXML(e:Event):void
{
_xml = new XML(e.currentTarget.data);
_pictures = _xml.image;
_numSlides = _pictures.length();
_slideNum = 2; // initially it's the 4th node, because the cube is skinned with 4 already
// SKIN CUBE 1st time --> start with BACK
_mcBack = new holder(_pictures[0].@url, _pictures[0].title, _pictures[0].description);
_mcBack.addEventListener(Event.COMPLETE, backLoader, false, 0, true);
}
private function createCubes():void
{
trace('CREATING CUBES');
for(var i:int = 0; i < NUM_SLICES; i++)
{
var materialsList:MaterialsList = new MaterialsList();
var sliceWidth:Number = _cubeWidth / NUM_SLICES;
var sliceX:Number = sliceWidth * i;
materialsList.addMaterial(createSlicedBitmapMaterial(_matFront, sliceX, sliceWidth, true), "front");
materialsList.addMaterial(createSlicedBitmapMaterial(_matBack, sliceX, sliceWidth), "back");
materialsList.addMaterial(createSlicedBitmapMaterial(_matTop, sliceX, sliceWidth), "top");
materialsList.addMaterial(createSlicedBitmapMaterial(_matBottom, sliceX, sliceWidth, true), "bottom");
materialsList.addMaterial(new ColorMaterial(0xffffff), "right");
materialsList.addMaterial(new ColorMaterial(0xffffff), "left");
var cube:Cube = new Cube(materialsList, sliceWidth, 480, 480);
//cube.x = sliceX - _swfWidth/2 + sliceWidth/2;
cube.x = sliceX - _cubeWidth/2 + sliceWidth/2;
cube.z = 240;
scene.addChild(cube);
cubes.push(cube);
}
startRendering();
addEventListener(MouseEvent.MOUSE_UP, mouseDownHandler);
}
/*
* CreateBitMap: Converters
* returns BITMAP from MovieClips
*
*/
private function createBitMapFromMC(mc:MovieClip):Bitmap
{
//Find occupied region
var region:Rectangle = new Rectangle();
region = mc.getBounds(this);
//Build Matrix Transform
var mat:Matrix = new Matrix(1,0,0,1, 0-region.x, 0-region.y);
mc.transform.matrix = mat;
//Draw the bitmap
var temp:BitmapData = new BitmapData(region.width, region.height, true, 0x00000000);
temp.draw(mc,mat);
//Attach the BitmapData to a Bitmap Instance
var bitmap:Bitmap = new Bitmap(temp);
//Re apply an Inverse Matrix
mat = new Matrix(1,0,0,1, region.x, region.y);
bitmap.transform.matrix = mat;
return bitmap;
}
/*
* Create Sliced Bitmap Material from a bitmap
* @returns: BitMapMaterial, sliced
*
*
*/
private function createSlicedBitmapMaterial(asset:Bitmap, sliceX:Number, sliceWidth:Number, isFlipped:Boolean = false):BitmapMaterial
{
var bitmap:Bitmap = asset;
var bitmapData:BitmapData = new BitmapData(sliceWidth, 480, false, 0xcc0000);
//bitmap.pixelSnapping = PixelSnapping.NEVER;
if(isFlipped)
{
var sliceMatrix:Matrix = new Matrix();
sliceMatrix.translate(-1*sliceWidth, -240);
sliceMatrix.rotate(Math.PI);
sliceMatrix.translate(sliceX, 240);
bitmapData.draw(bitmap, sliceMatrix);
}
else
{
bitmapData.copyPixels(bitmap.bitmapData, new Rectangle(sliceX, 0, sliceWidth, 480), new Point());
}
var material:BitmapMaterial = new BitmapMaterial(bitmapData, true);
return material;
}
/*
* mouseDownHandler
* rotates cubes on mouseDown
* re-skins one side - that has just turned over
*/
private function mouseDownHandler(event:MouseEvent):void
{
targetRotation += 90 % 360;
cubes.forEach(cubes_forEachCallback);
// side to skin
_sideToSkin = _shownSide[(_shownSidePointer + 3) % 4]; // which side is to skin? -> the side which is far out... (predecessing one)
// slide (XML pointer)
_slideNum ++; // xml index -> switch to 1st pic, if max is reached; should be 3 initially! (=> top)
if (_slideNum > _numSlides-1) _slideNum = 0; // reset to 0, if limit is reached
trace('XML slide n: '+_slideNum+ ' SIDE = ' + _shownSide[_shownSidePointer] + ' SKINNING ON: ' + _shownSide[(_shownSidePointer+3)%4]);
trace('SIDENUM = ' + _shownSidePointer + ' SKINNING ON: ' + (_shownSidePointer+3)%4);
/*
* change cube face by re-using the HOLDER class to load new XML data
* when holder has finished loading, trigger event to create BitMap from MC
* finally re-skin the selected side
*/
switch (_sideToSkin)
{
case "back": {
_mcBack.setContent(_pictures[_slideNum].@url, _pictures[_slideNum].title, _pictures[_slideNum].description);
//if (!_mcBack.hasEventListener(Event.COMPLETE))
_mcBack.addEventListener(Event.COMPLETE, skinBack, false, 0, true);
break;
}
case "bottom": {
_mcBottom.setContent(_pictures[_slideNum].@url, _pictures[_slideNum].title, _pictures[_slideNum].description);
_mcBottom.addEventListener(Event.COMPLETE, skinBottom, false, 0, true);
break;
}
case "front": {
_mcFront.setContent(_pictures[_slideNum].@url, _pictures[_slideNum].title, _pictures[_slideNum].description);
_mcFront.addEventListener(Event.COMPLETE, skinFront, false, 0, true);
break;
}
case "top": {
_mcTop.setContent(_pictures[_slideNum].@url, _pictures[_slideNum].title, _pictures[_slideNum].description);
_mcTop.addEventListener(Event.COMPLETE, skinTop, false, 0, true);
break;
}
}
// which side is shown AFTER ROTATION?
_shownSidePointer ++;
if (_shownSidePointer > 3) _shownSidePointer = 0; // max 4 sides
}
// skinning functions, after holders are updated
private function skinBack(e:Event):void
{
if (_mcBack.hasEventListener(Event.COMPLETE)) _mcBack.removeEventListener(Event.COMPLETE, skinBack);
skinCubes(_mcBack, "back");
}
private function skinBottom(e:Event):void
{
_mcBottom.removeEventListener(Event.COMPLETE, skinBottom);
skinCubes(_mcBottom, "bottom");
}
private function skinFront(e:Event):void
{
_mcFront.removeEventListener(Event.COMPLETE, skinFront);
skinCubes(_mcFront, "front");
}
private function skinTop(e:Event):void
{
_mcTop.removeEventListener(Event.COMPLETE, skinTop);
skinCubes(_mcTop, "top");
}
private function skinCubes(mc:MovieClip, side:String):void
{
trace("RE-SKINNING cube on " + side);
// re-skin cubes after changing a holder mc
var material:Bitmap = createBitMapFromMC(mc);
for (var i:int = 0; i < NUM_SLICES; i++)
{
var flipped:Boolean = false;
// flip only at front / bottom
if (side == "front" || side == "bottom") flipped = true; else flipped = false;
var sliceWidth:Number = _cubeWidth / NUM_SLICES;
var sliceX:Number = sliceWidth * i;
var sliced_material:BitmapMaterial = createSlicedBitmapMaterial(material, sliceX, sliceWidth, flipped);
//var matSide = cubes[i].materials.getMaterialByName(side);
//matSide.functionInMovieMaterial(sliced_material);
cubes[i].replaceMaterialByName(sliced_material, side);
}
}
/*
* rotate all cubes after rotation is initiated
*
*
*/
private function cubes_forEachCallback(cube:Cube, index:int, array:Array):void
{
index++;
var time:Number = .3 * index;
TweenMax.to(cube, time, { rotationX:targetRotation, ease:Quad.easeInOut } );
//TweenMax.to(cube, time, {x:Math.random()*500-1000, ease:Quad.easeInOut});
}
/* LOADERS -> one per side */
// BACK -> first function to call --> creates a cascade
function backLoader(e:Event):void
{
//trace("BACK completed in main class: " + e.target);
_matBack = createBitMapFromMC(_mcBack);
_mcBack.removeEventListener(Event.COMPLETE, backLoader);
// load next material
_mcBottom = new holder(_pictures[1].@url, _pictures[1].title, _pictures[1].description);
_mcBottom.addEventListener(Event.COMPLETE, bottomLoader, false, 0, true);
}
// BOTTOM
function bottomLoader(e:Event):void
{
//trace("BOTTOM completed in main class: " + e.target);
_matBottom = createBitMapFromMC(_mcBottom);
_mcBottom.removeEventListener(Event.COMPLETE, bottomLoader);
// next
_mcFront = new holder(_pictures[2].@url, _pictures[2].title, _pictures[2].description);
_mcFront.addEventListener(Event.COMPLETE, frontLoader, false, 0, true);
}
function frontLoader(e:Event):void
{
//trace("FRONT completed in main class: " + e.target);
_matFront = createBitMapFromMC(_mcFront);
_mcFront.removeEventListener(Event.COMPLETE, frontLoader);
// next
_mcTop = new holder(_pictures[3].@url, _pictures[3].title, _pictures[3].description);
_mcTop.addEventListener(Event.COMPLETE, topLoader, false, 0, true);
}
function topLoader(e:Event):void
{
_matTop = createBitMapFromMC(_mcTop);
_mcTop.removeEventListener(Event.COMPLETE, topLoader);
createCubes();
}
/*
*
* DEPRECATED: for images only
*
*/
private function createSlicedBitmapMaterialFromAsset(asset:Class, sliceX:Number, sliceWidth:Number, isFlipped:Boolean = false):BitmapMaterial
{
var bitmap:Bitmap = new asset() as Bitmap;
var bitmapData:BitmapData = new BitmapData(sliceWidth, 480, false, 0xcc0000);
if(isFlipped)
{
var sliceMatrix:Matrix = new Matrix();
sliceMatrix.translate(-180, -240);
sliceMatrix.rotate(Math.PI);
sliceMatrix.translate(sliceX, 240);
bitmapData.draw(bitmap, sliceMatrix);
}
else
{
bitmapData.copyPixels(bitmap.bitmapData, new Rectangle(sliceX, 0, sliceWidth, 480), new Point());
}
var material:BitmapMaterial = new BitmapMaterial(bitmapData, true);
return material;
}
/*
override protected function onRenderTick(event:Event=null):void {
// rotate the scene
_camera.yaw(-1);
// call the renderer
super.onRenderTick(event);
}
*/
}
}
