Does anyone know of any libraries or tools for importing an SVG file into actionscript on the fly? I need to be able to import an SVG file into flash and convert it to a movieclip or preferably a flat 3d object. The end goal here is to implement a vector file with Augmented reality.
A great library for this can be downloaded here: http://code.google.com/p/as3svgrendererlib/
It is easy to implement and reliable. Note that there are two ways to implement the code. I prefer the following because it gives you more control:
private function loadSVG(url:String):void {
ProcessExecutor.instance.initialize(stage);
ProcessExecutor.instance.percentFrameProcessingTime = 0.9;
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, svgLoaded, false, 0, true);
try {
loader.load(new URLRequest(url));
} catch (error:Error) {
trace(error);
}
}
private function svgLoaded(e:Event):void {
var svgString:String = loader.data as String;
var svgDocument:SVGDocument = new SVGDocument();
svgDocument.parse(svgString);
this.addChild(svgDocument);
}
The other way is shorter and might be the way to go when you only have to load a small SVG or just a few.
public function loadSVG(url:String) {
ProcessExecutor.instance.initialize(stage);
ProcessExecutor.instance.percentFrameProcessingTime = 0.9;
var svgDocument:SVGDocument = new SVGDocument();
svgDocument.load(url);
addChild(svgDocument);
}
Two important notes:
1. I could not seem to be able to capture the width or height of the SVGs and the parent Sprite had a width and height of 0 after loading the SVG. I solved this by making all the SVGs the same size before loading them into AS3. After that I knew the dimensions I used the ScaleX and scaleY to resize the loaded SVGs.
2. The stage has to exist before you can use this code. adding the following code will make sure you won't run into problems:yourDisplayClass.addEventListener(Event.ADDED_TO_STAGE, loadYourSVGs);
Now how you convert this to a flat 3D object depends on your 3D Library. I have worked with Away3D where you can use bitmapmaterial on your Sprite3D. The Sprite3D class would be the object to use. I hope your 3D Library supports the use of MovieClips so that you can add them to your 3D Object. Else you will have to use to extract the bitmapMaterial from the movie clip as i have done in the following example:
public function movieClipToBitmapMaterial(mc:MovieClip):BitmapMaterial {
var bmData:BitmapData = new BitmapData(mc.width, mc.height, true, 0xFFFFFF);
bmData.draw(displayObject);
return new BitmapMaterial(bmData);
}
Your input in the above function will be the movieclip onto wich you have loaded your SVG.
I am not sure of this but I think that by using this function you will loose the ability to scale as much as you like without loosing quality.
I hope my input was of some help!
Good luck
PS: don't forget to add the SWC from the link to your project and to check out the provided examples. Please note as well the excellent comment of shaunhusain on your original question. You might not have to use 3D Library.
Salam,
It is very easy:
Open the "name.svg" file in illustartror.
Save it as "name.ai"
Import it into the stage in flash, that is all.
Related
I start creating my flash game using Flashpunk, for collisions i didn't want to use hitboxes because i had images (PNG) with transparent parts in them so i decided to use Collision Detection Kit, i have a problem when creating the collision list, it takes a display object as a parameter and doesn't accept flash punk spritemaps, i tried to cast the spritemap to a flash display object but it's not working, is there a way to use the CDK with flashpunk ?
override public function begin():void
{
_player = new Player(100, 100);// Entity
initCollision(_player.sprPlayer);// The Entity Spritemap
}
private function initCollision(player:Spritemap):void {
collisionChecker = new CollisionList(player); // Problem here
}
Well, you could create an empty BitmapData with the same width & height of your Spritemap and then "render" it to that BitmapData, like so:
var bmd:BitmapData = new BitmapData(64, 64, true, 0);
var sprite:Spritemap = _player.sprPlayer;
sprite.render(bmd, new Point(0,0), new Point(0,0));
collisionChecker = new CollisionList(bmd);
That should draw the spritemap's current frame to a BitmapData which you could then use for the CollisionList. The code above is an example that only demonstrates how to do this. For your actual code, it would be better to avoid constantly initializing new variables during your collision detection.
EDIT: The convertation / copy process it self works, I just cant figure out how to tell the bitmapdata, which part of the stage to copy - I tried to solve that problem by movie the canvas to x=0 y=0 didnt show anychanges.
The only thing that showed a change was that I did move the canvas BEFORE drawing to zero, but this is totally buggy because the part of the drawing which has negativ coordinates wont be copied since the coordinate change only affect the bitmap if you do it before you start to paint
OLDER ENTRY:
I want to convert the Sprite.graphics into bitmapData, because I have a drawTool which allowes the user to paint lines, which are located inside the Sprite.grahpics I think.
I need to convert these lines to bitmapdata, because this allows me to deform them later on, but I cant use this
Bitmapdata.draw(Sprite.graphics);
And using only the Sprite instead of Sprite.graphics doesnt show any result =\
help is needed!
Use a matrix if you want to draw only a certain portion and from an origin other than (0,0). There's plenty in the Adobe docs on this, or a good example here:
http://www.quasimondo.com/archives/000670.php
Only use graphics when drawing. The actual Sprite object contains what you want, so following your convention, simply do:
BitmapData.draw(Sprite);
Although for a literal example:
var mySprite:Sprite = new Sprite();
// add lines etc using mySprite.graphics
var myBitmapData:BitmapData = new BitmapData(mySprite.width, mySprite.height);
myBitmapData.draw(mySprite);
I think, you've not completely understand usage BitmapData.draw().
BitmapData.draw() is a All DisplayObject(Sprite, MovieClip, Shape, Text, Video...) drawing possible. because they are have a IBitmapDrawable.(more information refer a adobe document Is the best teacher.)
If you want implement Paint Board. refer a below code. very simple Paint Board. but some help you.
try copy & paste.
import flash.display.Sprite;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.events.MouseEvent;
var isDraw:Boolean = false;
var brush:Sprite =new Sprite();
brush.graphics.beginFill(0x0000ff);
brush.graphics.drawCircle(0,0,5);
brush.graphics.endFill();
var canvasData:BitmapData = new BitmapData(600,400, false);
var canvas:Bitmap = new Bitmap(canvasData);
addChild(canvas);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDrawStart);
stage.addEventListener(MouseEvent.MOUSE_UP, onDrawStop);
stage.addEventListener(Event.ENTER_FRAME, render);
function onDrawStart(e:MouseEvent):void
{
isDraw = true;
}
function onDrawStop(e:MouseEvent):void
{
isDraw = false;
}
function render(e:Event):void
{
if(!isDraw) return;
brush.x = mouseX;
brush.y = mouseY;
canvasData.draw(brush,brush.transform.matrix);
}
I'am trying to figure out how to change material on loaded 3ds object/mesh during run-time after mouse click.
(Away3D 3.5/3.6)
3ds object is loaded with Loader3D:
//global mesh variable and view3d
var my_mesh:Mesh;
var view:View3D = new View3D();
//creating a parser with initial material
var max3ds_parser:Max3DS = new Max3DS();
max3ds_parser.material = new WireColorMaterial(0xFF0000);
var loader:Loader3D = new Loader3D();
loader.addEventListener(Loader3DEvent.ON_SUCCESS, onSuccess);
loader.loadGeometry("myMesh.3ds", max3ds_parser);
addChild(view);
addEventListener(Event.ENTER_FRAME, onEnterFrameRenderScene);
function onSuccess(e:Loader3DEvent):void{
my_mesh = Mesh(e.loader.handle);
view.scene.addChild(my_mesh)
}
function onEnterFrameRenderScene(e:Event):void{
my_mesh.rotationY += 15;
view.render();
}
So, after all this the 3ds object is added to the scene with initial material (WireColorMaterial) applied with parser object. But now I want to change the initial material after mouse click, so:
stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void{
//start FAIL here:
my_mesh.material = new WireframeMaterial(0x000000);
//end FAIL
trace("clicked!");
trace(my_mesh.material)
}
After the mouse click nothing changes in the view, my_mesh spins as it did with the initial material on. But the trace material shows that the new material was indeed applied.
Is there any other way to do this, or is there some kind of a way to refresh the scene to make it use the new material? Or refresh the view? Or should you somehow parse my_mesh again? Cheers.
I would recommend importing your models via Prefab3D. This will allows you to pre-process all these assets in a visual tool.
I either use the awd format or just export meshes as AS3 classes. Export as AS3 classes also compresses that data with the rest of you assets in the swf, a nice little bonus :)
I am trying to build a portfolio application similar to the used by Whitevoid. I am using Flex 4 and Papervision3D 2. I have everything working except for one issue. When I try to load an external SWF as a material on one of the planes, I can see any native Flex or Flash components in their correct positions, but the papervision objects are not being rendered properly. It looks like the viewport is not being set in the nested swf. I have posted my code for loading the swf below.
private function loadMovie(path:String=""):void
{
loader = new Loader();
request = new URLRequest(path);
loader.contentLoaderInfo.addEventListener(Event.INIT, addMaterial);
loader.load(request);
}
private function addMaterial(e:Event):void
{
movie = new MovieClip();
movie.addChild(e.target.content);
var width:Number = 0;
var height:Number = 0;
width = loader.contentLoaderInfo.width;
height = loader.contentLoaderInfo.height;
//calculate the aspect ratio of the swf
var matAR:Number = width/height;
if (matAR > aspectRatio)
{
plane.scaleY = aspectRatio / matAR;
}
else if (matAR < aspectRatio)
{
plane.scaleX = matAR / aspectRatio;
}
var mat:MovieMaterial = new MovieMaterial(movie, false, true, false, new Rectangle(0, 0, width, height));
mat.interactive = true;
mat.smooth = true;
plane.material = mat;
}
Below I have posted two pictures. The first is a shot of the application running by itself. The second is the application as a MovieMaterial on a Plane. You can see how the button created as a spark object in the mxml stays in the correct position, but papervision sphere (which is rotating) is in the wrong location. Is there something I am missing here?
Man. I haven't seen that site in a while. Still one of the cooler PV projects...
What do you mean by:
I cannot properly see the scene rendered in Papervision
You say you can see the components in their appropriate positions, as in: you have a plane with what looks like the intended file loading up? But I'm guessing that you can't interact with it.
As far as I know, and I've spent a reasonable amount of time trying to make something similar work, the MovieMaterial (which I assume you're using) draws a Bitmap of whatever contents exist in your MovieClip, and if you set it to animated=true, then it will render out a series of bitmaps - equating animation. What it's not doing, is displaying an actual MovieClip (or SWF) on the plane. So you may see your components, but this is how:
MovieMaterial.as line 137
// ______________________________________________________________________ CREATE BITMAP
/**
*
* #param asset
* #return
*/
protected function createBitmapFromSprite( asset:DisplayObject ):BitmapData
{
// Set the new movie reference
movie = asset;
// initialize the bitmap since it's new
initBitmap( movie );
// Draw
drawBitmap();
// Call super.createBitmap to centralize the bitmap specific code.
// Here only MovieClip specific code, all bitmap code (maxUVs, AUTO_MIP_MAP, correctBitmap) in BitmapMaterial.
bitmap = super.createBitmap( bitmap );
return bitmap;
}
Note in the WhiteVoid you never actually interact with a movie until it "lands" = he's very likely swapping in a Movie on top of the bitmap textured plane.
The part that you are interacting with is probably another plane that holds the "button" that simply becomes visible on mouseover.
I think PV1.0 had access to real swfs as a material but this changed in 2.0. Sadly. Hopefully Molehill will.
cheers
I want to rotate a sprite in 3d using AS3. The example below, tells how to do rotate an image using MXML and AS3, however, I want to do it through pure AS3:
Example
thanks
Flex is AS3. Flex compiles down to actionscript. Often, it's just a declarative (as opposed to the imperative) way to get things done.
So the meat of that example is in the code snippets:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
target.play();
}
}
//snip...
<fx:Declarations>
<fx:Number id="rotY">0</fx:Number>
<s:Rotate3D id="fxRotate3DNeg" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
<s:Rotate3D id="fxRotate3DPos" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
</fx:Declarations>
What's doing the work is the "Animate" object in conjunction with the two "Rotate3D" objects. So to get this to work in pure AS3, the only tough thing that's required is linking to the flex libraries. Depending on your IDE, that's pretty easy to do.
From there all you have to do is create the objects you want, imperatively instead of declaratively. So instead of doing things like:
<fx:Number id="rotY">0</fx:Number>
You need to do:
var rotY:Number = 0;
Once you know that, converting from Flex to AS3 and vice versa is pretty straightforward. The translated flex code would look something like the following in ActionScript:
import spark.effects.Rotate3D;
var rotY:Number;
var fxRotate3DNeg:Rotate3D;
var fxRotate3DPos:Rotate3D;
rotY = 0;
fxRotate3DNeg = new Rotate3D(image);; //the constructor sets the "target" property
fxRotate3DNeg.angleYTo = rotY;
fxRotate3DNeg.autoCenterTransform = true;
fxRotate3DPos = new Rotate3D(image);
fxRotate3DPos.angleYTo = rotY;
fxRotate3DPos.autoCenterTransform = true;
Now, that's off the top of my head, glancing at the Rotate3D API and typing in this text editor so I'm sure it's not perfect but it should give you a clear idea on how to move forward. If you need more help, let me know and I could translate more of the example.
I hope that helps,
--gMale
EDIT:
As I look at the code, one other tricky point is that the angleYTo properties are bound to rotY. So to truly get this to work, you have to explicitly set those properties in the playEffect function. As in:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
//manually set properties
fxRotate3DNeg.angleYTo = fxRotate3DPos.angleYTo = rotY;
target.play();
}
}
Alternatively, you could imperatively create the data binding, which is pretty easy to do. Then, the playEffect function would require no modification.
Its like rotating the object as you usually do. However in 3d space you will have to use:
sprite.rotationY
Make sure you are exporting for flash 10 or later since the 3d functionality doesnt exist in earlier versions.