Archive for March, 2009

Dynamic Custom Event

Tuesday, March 31st, 2009

Custom Events has become very useful when you’re building more complex applications.
You create them for especific cases and usualy they came with especific parameters.

Let’s say you create a custom event for a video player class and you use it to check the loading progress and video playback events, like play, pause, playback progress and playback complete. So when you create this event you must pass these parameters somehow, directly as an opitional parameter, inside an object, array or whatever you want.

Although, when you’re loading the video you need stream bytesLoaded and stream bytesTotal, but you don’t need the current time of playback. Other case is when you dispatch an event saying that the stream is paused or the playback is complete, you don’t need any other parameters. The problem (not a problem but a pain in the ass)  is that, for every param, you need to create a var in your class to store the value passed, otherwise you can’t pass any of them thru the event.

To avoid this you can set your custom event as a dynamic class. For those who don’t know, dynamic classes allow you to add properties at runtime, like movie clips. So you can pass any param thru an object as a opitional param of your event an store them in your class, like this:

package app.events {
	import flash.events.Event;
 
	dynamic public class CustomEvent extends Event {
		public function CustomEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, param:Object = null):void{
			super(type, bubbles, cancelable);
 
			if(param){
				for(var i:String in param){
					this[i] = param[i];
				}
			}
		}
	}
}

So when you need to pass any value you should add it to an object:

dispatchEvent(new CustomEvent(CustomEvent.LOAD_PROGRESS, false, false, {bytesLoaded:135817, bytesTotal:521387}));
dispatchEvent(new CustomEvent(CustomEvent.VIDEO_PROGRESS, false, false, {currentTime:8.65}));
dispatchEvent(new CustomEvent(CustomEvent.PAUSE));

And you recieve then like this:

function onLoadProgress(event:CustomEvent):void{
	trace(Math.floor(event.bytesLoaded*100/event.bytesTotal)+"% loaded");
}
function onVideoProgress(event:CustomEvent):void{
	trace("Current time:", event.currentTime);
}
function onPause(event:CustomEvent):void{
	trace("Video paused");
}

Papervision3D – Max3DS Parser bug

Friday, March 27th, 2009

Since papervision added the Max3DS parser I’ve been working with it instead of DAE. Although there’s a bug that I noticed when I imported an asymmetric model to my scene. It appear to be mirrored at the X axis. I was in a rush so I took the easy way, and flipped my model before export the 3ds file.

After that I tried to chage the 3ds parser to import the file correctly but it was taking me much more time than I had, so I wrote this method to fix the mesh after parsing.

Here is my scene in 3D Max

objects

Note that the box is behind the teapot and the cylinder is in front of it.

Here is a picture of the PPV scene when I import them usign Max3DS parser.

objects_fliped

And here it is after running my script

objects_normalized

I didn’t test it for complex models, but this will work just fine in 90% of the cases.

Here is the script:

normalize(object3ds);
 
function normalize(max3ds:Max3DS):void{
	max3ds.rotationX = 0;
	max3ds.rotationY = 0;
	max3ds.rotationZ = 0;
 
	for each(var mesh:DisplayObject3D in max3ds.children){
		mesh.scaleZ *= -1;
		mesh.rotationX *= -1;
		mesh.rotationY *= -1;
		mesh.rotationZ *= -1;
 
		var m:Matrix3D =  new Matrix3D();
		m.calculateMultiply(m, Matrix3D.rotationX(mesh.rotationX*Math.PI/180));
		m.calculateMultiply(m, Matrix3D.rotationY(mesh.rotationY*Math.PI/180));
		m.calculateMultiply(m, Matrix3D.rotationZ(mesh.rotationZ*Math.PI/180));
 
		m.calculateMultiply(m, Matrix3D.scaleMatrix(mesh.scaleX, mesh.scaleY, mesh.scaleZ));
 
		for(var i:Number = 0; i<mesh.geometry.vertices.length; i++){
			var vertex:* = mesh.geometry.vertices[i];
 
			var vx :Number = vertex.x;
			var vy :Number = vertex.y;
			var vz :Number = vertex.z;
 
			var tx :Number = vx * m.n11 + vy * m.n12 + vz * m.n13 + m.n14;
			var ty :Number = vx * m.n21 + vy * m.n22 + vz * m.n23 + m.n24;
			var tz :Number = vx * m.n31 + vy * m.n32 + vz * m.n33 + m.n34;
 
			vertex.x = tx;
			vertex.y = ty;
			vertex.z = tz;
		}
 
 
		mesh.rotationX = 0;
		mesh.rotationY = 0;
		mesh.rotationZ = 0;
		mesh.scaleZ *= -1;
 
		mesh.geometry.flipFaces();
	}
}

Demo
Source

DataLib

Wednesday, March 25th, 2009

During my last jobs I wrote a queue loader class that stores all loaded files for future requests.

DataLib

Overview:

-Static

Since it’s a static class, any loaded file can be used from any parto of the app, even from external SWF files.

-Load queue

Any file must be add to a load queue passing the url and type of file to be loaded. The file can be added at the end of the queue or in a especific position.

DataLib.addItem("file.swf", DataLib.TYPE_SWF);
DataLib.addItemAt("file.png", 0, DataLib.TYPE_PNG);
DataLib.addItem("file.wav", DataLib.TYPE_BINARY);

Also is possible get the load queue.

var queue:Array = DataLib.queue;

To start loading you must call DataLib.load()
Also it’s possible to pause, resume and close the loading.

DataLib.pause();
DataLib.resume();
DataLib.close();

-Data storage

Every load file is stored for future requisitions. If necessary, files can be deleted freeing memory. Get loaded files using it’s URL.

var image:Bitmap = DataLib.lib[fileURL].data;
 
addChild(image);
 
DataLib.removeItem(fileURL);

-Custom Events

Custom Events cam be added to follow the loading. You can add an event in the class or in a especific item.

*Remember to remove all events from the class to prevent conflicts with other loadings.

DataLib.addItemAt("file.png", 0, DataLib.TYPE_PNG).addEventListener(DataLibEvent.PROGRESS, onItemProgress);
DataLib.lib["file.xml"].addEventListener(DataLibEvent.COMPLETE, onItemComplete);
 
DataLib.addEventListener(DataLibEvent.COMPLETE, onComplete);
 
DataLib.load();
 
function onItemProgress(e:Event):void{
	trace(Math.floor(e.bytesLoaded*100/e.bytesTotal)+"%");
}
function onItemComplete(e:Event):void{
	trace(e.data);
}
function onComplete(e:Event):void{
	addChild(DataLib.lib["file.png"].data);
}

-JPG, GIF, PNG, SWF, XML and BINARY

These are the supported files. You can get embed classes in SWF loaded files using the main movie application domain.

DataLib.addItem("asset.swf", DataLib.TYPE_SWF);
 
addChild(DataLib.lib["asset.swf"].data)
 
var EmbedClass:Class = ApplicationDomain.currentDomain.getDefinition("assetEmbedClass") as Class;
var instance:* = new EmbedClass();

You can get this and other classes using my google code.

http://andreanaya.googlecode.com/svn/trunk/

Theres also an example of usage of this class.

Thanks and I hope this could be usefull for you guys. Any problem or sugestion please tell me.

Anaya

PaperPlane Test

Tuesday, March 24th, 2009

Early experiments of nothing that could become something.

Use the arrows to control the plane
Speed up pressing space

Demo

plane

Source

Loader issue

Monday, March 23rd, 2009


Last friday I was checking Flash Bookmarks and I noticed a question about Loader.
While ago I needed to load a file using a Loader and then add it to the stage. However it raised an error.

ArgumentError: Error #2025 : The supplied DisplayObject must be a child of the caller.


To solve the problem I needed to extract the conten in a var and then call a loader.unload() before add it to the stage.

function onLoadComplete(e:Event):void{
	var image:Bitmap = e.currentTarget.content;
	loader.unload();
	addChild(image);
}


It’s the same case when you try to load two or more files using the same loader.


Example

Google code

Friday, March 20th, 2009


I’ve decided to create a google code with my classes, there’s no docs yet but there’s some usage examples


So far there’s 4 libs that I use in my works:

-DataLib


Loader class (example) usign queue

-CromelessPlayer


Video class with playlist

-SoundControl


Sound class (example). *Still need ajustments

-MatrixTween


Tweening class based on Tweener and TweenLite with time control

After a long time

Friday, March 20th, 2009


Last jobs

http://www.kvarch.com/

#24 @ http://www.designcharts.com/ – FEB 8th 2009

http://www.marciokogan.com

#24 @ http://www.designcharts.com/ – MAR 22nd 2009


Also @:

http://dopeawards.com/
http://iblog.chubzz.com/
http://anotherbookmark.com/
http://spyline.de/
http://www.webdesignfile.com/
http://www.designlicks.com/
http://bm.straightline.jp/

Long nights no sleep