Actionscript 3 and Flex 4 Zoom Gesture on SWFLoader - actionscript-3

I seem to be having issue with Zoom Gestures on a SWFLoader. I have an swf file which is a floor plan of a home, I want the user to be able to zoom in and out with two finger touch, the following code below is what I tried and does not work. When I test on a touchscreen, it does not zoom when I place two fingers inside the SWF and try to zoom in.
<s:SWFLoader id="floorplanImage" source="#Embed('assets/test2.swf')" width="100%" height="100%" smoothBitmapContent="true" horizontalAlign="center" />
here is my actionscript 3 code
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
import flash.events.Event;
public var selectedItem:Object;
public function init(): void
{
floorplanImage.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
}
public function onZoom (e:TransformGestureEvent):void{
floorplanImage.scaleX *= e.scaleX;
floorplanImage.scaleY *= e.scaleY;
}
Please Help!
UPDATE
I am going the route of gestouch, however with this code, I CANNOT zoom in or out on an SWF. With a regular image it works, but not with SWF unless I am missing something. Here is my code:
<mx:Script>
<![CDATA[
import org.gestouch.events.GestureEvent;
import org.gestouch.gestures.TransformGesture;
private var _zoom:TransformGesture;
[Embed(source="assets/test2.swf")]
private var myClass:Class;
private var myMovieClip:MovieClip;
private function initModel():void
{
myMovieClip = MovieClip(new myClass());
swfcontainer.addChild(myMovieClip);
_zoom = new TransformGesture(swfcontainer);
_zoom.addEventListener(org.gestouch.events.GestureEvent.GESTURE_BEGAN, onGesture);
_zoom.addEventListener(org.gestouch.events.GestureEvent.GESTURE_CHANGED, onGesture);
}
private function onGesture(event:org.gestouch.events.GestureEvent):void
{
const gesture:TransformGesture = event.target as TransformGesture;
var matrix:Matrix = swfcontainer.transform.matrix;
// Panning
matrix.translate(gesture.offsetX, gesture.offsetY);
swfcontainer.transform.matrix = matrix;
if (gesture.scale != 1)
{
// Scale and rotation.
var transformPoint:Point = matrix.transformPoint(swfcontainer.globalToLocal(gesture.location));
matrix.translate(-transformPoint.x, -transformPoint.y);
matrix.scale(gesture.scale, gesture.scale);
matrix.translate(transformPoint.x, transformPoint.y);
swfcontainer.transform.matrix = matrix;
}
}
]]>
</mx:Script>
<mx:Image id="swfcontainer" horizontalAlign="center" width="100%" height="100%" />
When I use this with a regular image, it still does not work properly...it doesn't keep the image center when zooming, it does not let me zoom in, only out and when I first use it, it moves the image to the right. HOW COME THIS IS SOOOOOO HARD?
Please keep in mind I am very very new to Adobe Flex and Actionscript, so please make your answers as clear as possible.

Your code has no problem,I'll explain what I did for my project. Maybe it helped, i have Window design app and i load SWF into starling and have issue
with zoom and pan;
FYI: I Use starling and load SWF file with native overlay in starling and zoom pan work
_mLoader = new Loader();
var mRequest:URLRequest = new URLRequest("drawer.swf" + "?nf=" + getTimer());
_mLoader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, onCompleteHandler);
_mLoader.load(mRequest);
private function onCompleteHandler(loadEvent:flash.events.Event):void
{
_mLoader.contentLoaderInfo.removeEventListener(flash.events.Event.COMPLETE,
Starling.current.nativeOverlay.addChild(LoaderInfo(loadEvent.currentTarget).content);
}
And because the library touching the flash was weak i use above lib,and this is to Strong
first of all test above lib maybe that's work Without Starling
better GESTURE lib than flash lib
my zoom code with this lib
var _zoom:
_zoom = new TransformGesture(this);
_zoom.addEventListener(GestureEvent.GESTURE_BEGAN, onGesture);
_zoom.addEventListener(GestureEvent.GESTURE_CHANGED, onGesture);
private function onGesture(event:org.gestouch.events.GestureEvent):void
{
const gesture:TransformGesture = event.target as TransformGesture;
var matrix:Matrix = container_movieclip.transform.matrix;
if (container_movieclip.scaleX!=1 || container_movieclip.scaleY!=1)
{
matrix.translate(gesture.offsetX, gesture.offsetY);
container_movieclip.transform.matrix = matrix;
}
if (gesture.scale != 1)
{
var transformPoint:Point = matrix.transformPoint(container_movieclip.globalToLocal(gesture.location));
matrix.translate(-transformPoint.x, -transformPoint.y);
matrix.scale(gesture.scale, gesture.scale);
matrix.translate(transformPoint.x, transformPoint.y);
container_movieclip.transform.matrix = matrix;
}
}
I hope I could help

simply your issue solved if you changed multiinputMethod to touchpoint
Multitouch.inputMode=MultitouchInputMode.TOUCH_POINT;

Related

Dynamically display text in Flex, ActionScript 3

I've been having problems displaying text in ActionScript 3 using Flex SDK 4.6. Any method I try results in no change or a black screen; here is my project code and attempts.
MyProject.mxml is simply and mx:Application tag with the relevant parts being
<mx:Script>
<![CDATA[
include "MyProject.as"; //simply running my project file
]]>
</mx:Script>
and
<mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%"/> //defining the canvas
In MyProject.as I have
import flash.display.*;
import flash.events.*;
import mx.events.*;
import mx.controls.*;
import Game;
public static const SCREEN_WIDTH:int = 960;
public static const SCREEN_HEIGHT:int = 720;
private var initializationCompleted:Boolean = false;
public var screenBuffer:BitmapData;
public var game:Game;
public function setup():void {
screenBuffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x00000000);
game = new Game(SCREEN_WIDTH, SCREEN_HEIGHT, screenBuffer);
initializationCompleted = true;
}
private function updateFrame():void {
if (!initializationCompleted) {
return;
}
draw();
gamePanel.graphics.clear();
gamePanel.graphics.beginBitmapFill(screenBuffer, null, false, false);
gamePanel.graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
gamePanel.graphics.endFill();
}
private function draw():void {
game.update();
}
And in Game.as, I simply draw everything using the BitmapData class, and then copy everything to the screenBuffer:
screenBuffer.copyPixels(myBitmap, new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), new Point(0,0));
(This is only the relevant code - I trimmed as much as possible to leave a "Minimal, Complete, and Verifiable example")
Now I have been having problems displaying text in my project. I know that TextField is a subclass of flash.display.Sprite which can be added to the canvas. Whenever I try using something like
var txtHello:TextField = new TextField();
txtHello.text = "Hello World";
gamePanel.addChild(txtHello)
this either changes nothing (if used in setup(), I'm assuming I'm drawing over it or else it is never displayed) or causes a black screen (if used anywhere in updateFrame(), I'm assuming I'm creating infinite sprites).
I have tried instead, creating a new file named "TextWithImage.as" with the contents
//this is ripped off the adobe help page
package {
import flash.display.Sprite;
import flash.text.*;
public class TextWithImage extends Sprite {
private var myTextBox:TextField = new TextField();
private var myText:String = "Hello World";
public function TextWithImage() {
addChild(myTextBox);
myTextBox.text = myText;
}
}
}
importing it in MyProject.as, and then using it as
gamePanel.addChild(new TextWithImage());
to the same effect as my previous attempt.
What is the simplest way to display text in Flex/AS3? Any help is appreciated, and thank you in advance!
There's a trick. Flex components, albeit having the same addChild method derived from DisplayObjectContainer class, cannot actually add regular Flash content - Shape, Sprite, MovieClip, TextField, Bitmap - directly. More to that, they don't produce any runtime error, which I personally think they totally could to not confuse new people.
Flex component can only addChild classes that extend the basic UIComponent class. At the same time, UIComponent can addChild regular Flash content. Thus you do it as following:
var proxyContainer:UIComponent = new UIComponent;
var txtHello:TextField = new TextField;
txtHello.text = "Hello World";
proxyContainer.addChild(txtHello);
gamePanel.addChild(proxyContainer);

Playing a video with flex, AS3

I am currently trying to make a game on flex and one of the problems I ran in to is how to play a short animation at the beginning. This is what I have so far:
Game.mxml
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
name="Game"
backgroundColor="#000000"
horizontalAlign="center"
creationComplete="Init();"
enterFrame="UpdateFrame();"
paddingLeft="0"
paddingTop="0"
paddingBottom="0"
paddingRight="0"
width="800" height="600">
<mx:Script>
<![CDATA[
include "Game.as";
]]>
</mx:Script>
<mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%" mouseDown="MouseDown(event)" mouseUp="MouseUp(event)" mouseMove="MouseMoved(event)"/>
</mx:Application>
and Game.as
import flash.display.*;
import flash.events.*;
import flash.external.ExternalInterface;
import mx.events.*;
import mx.controls.*;
[Embed(source="MyVideoClip.flv")] private var MyVideoClip:Class;
public function Init():void
{
var MyVideo:Video = new Video(800, 600);
addChild(MyVideo);
var qNetConnection:NetConnection = new NetConnection();
qNetConnection.connect(null);
var qNetStream:NetStream = new NetStream(qNetConnection);
MyVideo.attachNetStream(qNetStream);
qNetStream.client = new Object();
qNetStream.play(MyVideoClip);
}
private function UpdateFrame():void
{
}
private function MouseDown(event:MouseEvent):void
{
}
private function MouseUp(event:MouseEvent):void
{
}
private function MouseMoved(event:MouseEvent):void
{
}
I am rather new to Flex and AS3 so most of this code was ripped off web tutorials. Whenever I try to compile it I get: 'Error: 'MyVideoClip.flv' does no have a recongnized extention, and a mimeType was not provided. Error: unable to transcode 'MyVideoClip.flv''
If I remove the 'embed' line and replace MyVideoClip with "MyVideoClip.flv" in the play() function, the code compiles with no errors, but when I open the SWF all I get is a black screen. What am I doing terribly wrong?
Thanks in advance!!
Try setting the mime-type, e.g.:
[Embed(source = "MyVideoClip.flv", mimeType = "application/octet-stream")]
You embedded the video file (its bytes) into the output SWF. So now NetStream must play from a bytes source. Just set a byteArray as equal to new MyVideoClip(); and append to NetStream.
Try this...
[Embed(source="MyVideoClip.flv", mimeType="application/octet-stream")] private var MyVideoClip:Class; //# embed the FLV's bytes
public var VideoClipBytes : ByteArray;
public var MyVideo:Video;
public var qNetConnection:NetConnection;
public var qNetStream:NetStream;
public function Init():void
{
VideoClipBytes = new MyVideoClip() as ByteArray; //# fill a byte Array with embedded bytes
qNetConnection = new NetConnection(); qNetConnection.connect(null);
qNetStream = new NetStream(qNetConnection);
qNetStream.client = new Object();
MyVideo = new Video(800, 600);
MyVideo.attachNetStream(qNetStream);
addChild(MyVideo);
qNetStream.play(null); //# play mode is now bytes
qNetStream.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN); //# ready for new audio/video data
qNetStream.appendBytes( VideoClipBytes ); //# add bytes to decoder queue (playback)
}
PS : I made some of your variables as public so later you can access & control them from any other functions. Remember if you make var inside a public function it stays valid only in that one function and doesn't exist to other functions. Best make such vars as publicly available to all functions.

AS3/AIR Mobile Click and/or touchevents on moving objects

few weeks ago i asked a question about a similair issue, but within the Starling Framework (Starling TouchEvent on Sprite)
Now, i am working on another mobile app/game with Away3d. I seem to have the same problem touching/tapping a moving sphere or box. When the sphere is not moving, i can just tap it exactly at its position, but when it rotates, the click-event doesnt fire very accurate.
this only happens on Mobile (tested on Android 4.2.2: Nexus7/Galaxy S2 and iOS: iPad2/iPad Retina)
package {
import away3d.containers.ObjectContainer3D;
import away3d.containers.View3D;
import away3d.core.pick.PickingColliderType;
import away3d.core.pick.PickingType;
import away3d.debug.AwayStats;
import away3d.entities.Mesh;
import away3d.events.MouseEvent3D;
import away3d.primitives.SphereGeometry;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Vector3D;
[SWF(frameRate="60")]
public class Main extends Sprite {
private var _container:ObjectContainer3D;
private var _view:View3D;
private var _sphere:Mesh;
public function Main()
{
super();
addEventListener(Event.ADDED_TO_STAGE, onAdded_toStage);
}
private function onAdded_toStage(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded_toStage);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, onResize_stage);
init3d();
}
private function onResize_stage(e:Event):void {
_view.width = stage.stageWidth;
_view.height = stage.stageHeight;
}
private function onEnter_frame(e:Event):void {
_container.rotationY += 1;
_view.render();
}
private function onClick_sphere(e:MouseEvent3D):void {
//reposition the sphere
var deg:Number = Math.random() * 360;
_sphere.x = 250 * Math.cos(deg);
_sphere.z = 250 * Math.sin(deg);
_sphere.y = 80 + (Math.random() * 40);
}
private function init3d():void {
//create the 3d-view
_view = new View3D();
_view.width = stage.stageWidth;
_view.height = stage.stageWidth;
addChild(_view);
//create a cub
_view.camera.z = -400;
_view.camera.y = 75;
_view.camera.lookAt(new Vector3D(0, 125, 0));
//create container
_container = new ObjectContainer3D();
_view.scene.addChild(_container);
//create sphere to tap
_sphere = new Mesh(new SphereGeometry(10));
_sphere.pickingCollider = PickingColliderType.AS3_FIRST_ENCOUNTERED;
_sphere.y = 100;
_sphere.z = -250;
_sphere.mouseEnabled = true;
_sphere.addEventListener(MouseEvent3D.CLICK , onClick_sphere);
_container.addChild(_sphere);
var stats:AwayStats = new AwayStats(_view);
addChild(stats);
addEventListener(Event.ENTER_FRAME, onEnter_frame);
}
}
NOTE: i also tried different framerates, more events(Mouse_up, down etc), different pickers.
As this problem also happens with 2d moving sprites (in starling) my guess is that is might be Stage3D or AIR related, instead of starling/away3d.
Anyone has some suggestions? Maybe i'm forgetting to set something in the app.xml?
Both framework have to deal with an event less system (Stage3D). Stage3D doesn't catch or receive any events and certianly not touch or mouse event. So both frameworks simulate those events with an internal system that catches events on the stage and try to reproduce an accurate estimation. I personally find those systems too CPU expensive and not accurate enough so my advice is to do like me, create your own system. Simply catch event on the stage and decide which of displayed objects (on Stage3D using their position) has been touched. I personally get a performance boost out of it (especially with starling) and much more accuracy.

Coordinates don't change dragging scaled fxg graphics

I'm using FlashDevelop, actionscript 3 and fxg graphics build with Illustrator (exported as fxg 2.0).
I import a fxg rectangle build with Illustrator, then I set it draggable when you clik on it, so its coordinates change. This works if the rectangle scale is 1 (this means: no scale).
But, if I change its scale (ex. fxgRect.scaleX = fxgRect.scaleY = 0.5; ) you can drag it but its coordinates doesn't change!! And this make me crazy because the sprite changes position but if you ask its coordinates they aren't changed!!
And I set the fxgRect.mouseChildren = false; so I'm sure to move the sprite fxgRect and not something inside it.
(This is just an example, my aim is to build complex graphics with illustrator and use it in FlashDevelop).
Thank you in advance for help me.
This is the code done to test this problem. To use this example you have to create a fxg rectangle (fxgrectangle.fxg) and put it in the same folder of the SimpleDragFxg.as class.
import flash.display.*;
import flash.events.*;
import fxgrectangle;
public class SimpleDragFxg extends Sprite
{
public var fxgRect:Sprite = new fxgrectangle(); // make an istance of fxgRect
public function SimpleDragFxg()
{
//----------------------------------------------------------
addChild(fxgRect);
fxgRect.name = "FXGrect";
fxgRect.x = fxgRect.y = 50;
fxgRect.mouseChildren = false;
fxgRect.scaleX = fxgRect.scaleY = 0.5; //<<< this makes the problem
trace ("I'm ", this.name, "and I contain ", this.fxgRect.name, "which contains ", fxgRect.getChildAt(0).name);
fxgRect.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
//--------------------------------------------------------------
}
private function onMouseDown (e:MouseEvent):void
{
trace ("e.target: ", e.target.name);
if (DisplayObject(e.target).name == "FXGrect")
{
trace ("FXGrect position BEFORE drag: ", fxgRect.x, fxgRect.y);
Sprite(e.target).startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
private function onMouseUp (e:MouseEvent):void
{
fxgRect.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
if (DisplayObject(e.target).name == "FXGrect")
{
trace ("FXGrect position AFTER drag: ", fxgRect.x, fxgRect.y);
}
}
}
Try
public var fxgRect:Sprite = new Sprite();
fxgRect.addChild(new fxgrectangle());

How to make pre-loaded swf fill the browser?

Let me explain my question a bit.
I am creating a flash website and I am using a small external preloader swf to load in the main swf. I have been able to get my preloader swf to take up the whole browser window but as soon as it loads in the main swf it only displays in its normal dimensions that it was built in.
I do have a resize listener within the main flash application and as soon as I change the size of the browser the main swf then occupies the whole browser. But how can I get it to start out that way?
-I've tried using an ENTER_FRAME handler but that broke some of my animations.
-I've tried setting the width and height of my loader object in the preloader and that doesn't seem to work either.
-I've also tried adding an ADDED_TO_STAGE listener to the loader, but that doesn't seem to have changed anything.
-I also tried having the preloader be in one scene and the main application be in another so that I was only loading one swf, but that didn't seem to work and I don't prefer that method of pre-loading.
I haven't been able to find a solution anywhere. Is there something easy that I'm missing? Let me know what you all think. preloader code is as follows:
import flash.net.URLRequest;
import flash.display.Loader;
import flash.events.Event;
import flash.events.ProgressEvent;
var request:URLRequest = new URLRequest("flashNew.swf");
var loader:Loader = new Loader();
loader.load(request);
this.addChild(loader);
function loadProgress(event:ProgressEvent):void
{
var percentLoaded:Number = event.bytesLoaded / event.bytesTotal;
var percentLoadedBar:Number = Math.round((event.bytesLoaded / event.bytesTotal) * 100);
percentLoaded = Math.round(percentLoaded * 100);
this.percentLoaded.text = String(uint(percentLoaded)) + "%";
progressBar.width = percentLoadedBar * 3.36;
}
function loadComplete(event:Event):void
{
//loader.content.height = stage.stageHeight;
//loader.content.width = stage.stageWidth;
}
function setDimensions(event:Event):void
{
loader.width = stage.stageWidth;
loader.height = stage.stageHeight;
}
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.contentLoaderInfo.addEventListener(Event.ADDED_TO_STAGE, setDimensions);
Is there a way I can change via javascript or something? I'm at a loss here and I've been stuck on this for hours. Any help would be appreciated. Thank you!
UPDATE
Here is my code for my resize function.
function resizeListener(e:Event):void
{
background_mc.width = stage.stageWidth;
background_mc.height = stage.stageHeight;
//The rest of the function is omitted. It is if's and else-if's that just reposition various elements.
//That's really all this function does is re-position elements with the exception of the above code which resizes the background.
}
Here is the event listener call.
stage.addEventListener(Event.RESIZE, resizeListener);
Try this:
removed this line of code: this.addChild(loader);
then tweak your loadComplete function to this:
function loadComplete(event:Event):void
{
addChild(loader.content);
loader.content.height = stage.stageHeight;
loader.content.width = stage.stageWidth;
}