Flash authoring environment strange Test Movie behavior (AS3) - actionscript-3

I can't for the life of me figure out why this is happening. Let me describe what I'm experiencing.
I add everything dynamically via actionscript.
In the Flash authoring environment, when I test the movie, sometimes all of the movieclips on stage disappear and all I see is the color of the Stage.
The strange thing is that I can still rollover/rollout (I added trace statements to my rollover/rollout handlers).
I'm also tracing out the 'visible' and the 'alpha' property and visible=true and alpha=1.0 !!!
On thing that I am seeing is sometimes the rollover/rollout methods get called multiple times in quick succession. I.e. the method invocation order is rollover, rollout, rollover or rollout, rollover, rollout.
The actions that I have in my rollover and rollout methods are really simple. All they do is turn on/off other movieclips...imagine a map...when you rollover an icon, a path shows up on the map and when your rolloff, the path goes away.
However, if I adjust the window of the test movie window, everything appears again!
The crazy thing is that when I publish it, this behavior doesn't happen in the browser or as an app!
What's going on? Could it be a memory thing with the authoring environment?
Posting some code here:
private function rollOverUserListener ( e:MouseEvent ) {
trace(">>>>>>>> rollOverUserListener() e.currentTarget.name : " + e.currentTarget.name);
trace("e.currentTarget.alpha: " + e.currentTarget.alpha);
trace("e.currentTarget.visible: " + e.currentTarget.visible);
e.currentTarget.rollOverAction(); //just scales the icon a little
//fade up/down the appropriate path
worldMap.resetPaths(); //turns off all the paths
for (var i=0; i<users.length; i++){
if ( e.currentTarget == users[i] ) { //highlight the right path
worldMap.highlightPath(i);
}
}
}
private function rollOutUserListener ( e:MouseEvent ) {
trace("<<<<<<<< rollOutUserListener() e.currentTarget.name : " + e.currentTarget.name);
e.currentTarget.rollOutAction(); //scales down the icon to normal
worldMap.resetPaths();
}

I don't think it's efficient to try and solve this problem via posting the code you did.
But, my guess is that the difference in behavior that you are seeing is due to the flash player version.
CS5 or whatever version you have of flash, comes with the latest player at that time. But the flash player is constantly being upgraded, so when you are in your browser -- you most likely have the latest flash player. That could account for the differences you are seeing.
However, the code above doesn't help to much without seeing the highlightPaths and resetPaths functions. I see that you have a trace, but right after that -- there's code executed that could potentially easily change the state of anything you traced before rendering the frame.
Stick some traces after that code to see if you get what you expect.
Are you using any libraries that might have features only supported by a newer flash player ?

private function rollOverUserListener ( e:MouseEvent ) {
trace(">>>>>>>> rollOverUserListener() e.currentTarget.name : " + e.currentTarget.name);
trace("e.currentTarget.alpha: " + e.currentTarget.alpha);
trace("e.currentTarget.visible: " + e.currentTarget.visible);
e.currentTarget.rollOverAction(); //just scales the icon a little
//fade up/down the appropriate path
worldMap.resetPaths(); //turns off all the paths
for (var i=0; i<users.length; i++){
if ( e.currentTarget == users[i] ) { //highlight the right path
worldMap.highlightPath(i);
}
}
}
private function rollOutUserListener ( e:MouseEvent ) {
trace("<<<<<<<< rollOutUserListener() e.currentTarget.name : " + e.currentTarget.name);
e.currentTarget.rollOutAction(); //scales down the icon to normal
worldMap.resetPaths();
}

Related

Robot not pressing mouse during mouse movement method

I am currently working on a basic utility software that has the ability to record Keyboard & Mouse input, save the input to a .txt file, and playback the data on a file. I am revising the program for added file and playback functionality. The problem I'm having is with the Robot.mousePress() method within the mouse movement method:
public static void executeMouseMovementData() {
mouseRobot.mousePress(InputEvent.BUTTON1_MASK);
for (int i=0; i < MouseDataHandler.mouseData.size(); i++) {
mouseRobot.moveMouse(MouseDataHandler.mouseData.get(i).getX(), MouseDataHandler.mouseData.get(i).getY());
mouseRobot.delay(MouseDataHandler.mouseData.get(i).getTimeElapsed());
}
mouseRobot.releaseMouse();
}
This program follows a basic sequence of events: 1 Data initialization, 2 Press mouse, 3 Move mouse, 4 Release mouse. Unlike another method I've successfully implemented, this method does not press the mouse at any time for no obvious reason. Mouse movement works beautifully with the playback feature. I just can't seem to get the Robot to execute any type of mouse event other than movement, even if I restructure the method.
I've tried editing the method to make sure the Robot doesn't press the mouse at the time in which the "playback" button on the GUI is pressed, as to not mess with the focus of the mouse event. The error likely isn't related to other aspects of the code, because everything else in the program runs smoothly. The object "mouseRobot" is an basic extension class of the Java.awt.Robot class with a basic interface for compound Robot mouse methods(), and I even directly call the mousePress method from the Robot class.
What could be the malfunction that occurs with within this method?
Solved. Improved the method in which mouse movements are handled to do one mouse movement per frame. The class can now accurately perform various checks and data changes in between mouse movements, while also allowing other classes to function without being held up from a lengthy for loop. The method in the question was extremely inefficient, impractical and basically acted as a 'while' loop.
public void handleMouseMovements() {
if (shouldAttemptToMoveMouse) {
if (!targetHasBeenReached(currentAdjustedX, currentAdjustedY, targetX, targetY)) {
if (!movementCreated) {
calculateDirection(startX, startY, targetX, targetY);
getLineIndexToUse();
initializeMoveData(repositoryFileIndex, fileIndex);
movementCreated = true;
firstTime = System.currentTimeMillis();
}
if (CMMI >= Main.mouseDataHandler.getSizeOfRepositoryIndex(repositoryFileIndex, fileIndex)){
CMMI =0;
loopMovement();
}
if (movementfileIndexTimeHasElapsed(repositoryFileIndex, fileIndex)) {
moveMouse(repositoryFileIndex, fileIndex);
CMMI++;
firstTime = System.currentTimeMillis();
}
}
else {
resetData();
}
}
}
public void moveMouse(int repositoryFileIndex, int fileIndex) {
currentX = MouseDataHandler.mdr.get(repositoryFileIndex).get(fileIndex).get(CMMI).getX();
currentY = MouseDataHandler.mdr.get(repositoryFileIndex).get(fileIndex).get(CMMI).getY();
currentAdjustedX = currentX + distanceX;
currentAdjustedY = currentY + distanceY;
Main.bot.moveMouse(currentAdjustedX + Main.getX(), currentAdjustedY + Main.getY() + 25);
}
This method is vastly more efficient and handles all criteria necessary to determine direction, determine file index of mouse data to be used, calculates target-file index offsets, and has proper time intervals inbetween mouse movements.

Set rotation flash tween to shortest distance as3?

I am working on an adobe air interactive table project and I'm trying to tween some rotations. For the most part it works fine, but occasionally it spins aaall the way around version just spinning a little to the other direction. Does anyone of a good way to prevent this in the flash tweens?
A snippet of my code:
var rotatePos:Number;
if (event.rotation > 180) { rotatePos = event.rotation - 360; } else { rotatePos = event.rotation; }
var rotateDifference:Number = Math.abs(Math.abs(rotatePos) - Math.abs(Number(rotationCurrent[tempCircleNumber])));
if ( rotateDifference > 4 && rotateDifference < 60) {
rotateTheFiducial();
} else if ( rotateDifference > 100 ) {
trace("too far, ignore : " + rotateDifference);
}
function rotateTheFiducial():void
{
try
{
var cardTweenRotation:Tween = new Tween(MovieClip(fiducialArray[tempCircleNumber]), "rotation", Regular.easeOut, Number(rotationCurrent[tempCircleNumber]), rotatePos, .2, true);
rotationCurrent[tempCircleNumber] = rotatePos;
}
catch (e:Error)
{
trace(fiducialId + " : Rotate Error : " + e);
}
}
Regular.easeOut is supposed to perform the above behavior.
Sometimes, while having multiple tweens with easing, flash even misses out the final point.
So if you do have to use easeout, add a tween complete event wherein you set the final point manually.
Else use None.easeNone
You really should avoid using Flash built-in Tween engine. Its slow, bloated, and is lacking a lot of really useful things.
Try using TweenLite/TweenMax or better, eaze that both have built-in functions for short rotations like you are facing.
They are waaaay faster than using the default Tween engine ! (as you can see here)
Not only you will be able to sort that kind of short-rotation problems, but your app will gets faster with one of them :-)

Kinetic.js don't lose grip on mouse out

When you drag an object and mouse is out of rendering area, dragging stops (firing an event) and user loses a grip.
It's extremelly inconvenient, taking into account that all other technologies (Flash, raw HTML5 Canvas, etc) allows to save the grip even if mouse is out.
Is there a way to solve the problem?
UPDATE: Up to the moment solved the problem by changing library file and binding listeners to the document, not to the container. I know that it's bad to hack into library files, but after inspecting the library's source code I haven't found out way around.
you could check if the element is out of sight and if so bring it back:
shape.on('dragend', function() {
var pos = shape.getPosition();
var layer = pos.getLayer();
if (pos.y < 0) {
pos.y = 0;
}
var maxY = layer.getHeight() - shape.getHeight();
if (pos.y > maxY) {
pos.y = maxY
}
shape.setPosition(pos);
}
Look at element.setCapture(). You can call it from within an event handler for a mouse event, eg. mousedown:
function mouseDown(e) {
e.target.setCapture();
e.target.addEventListener("mousemove", mouseMoved, false);
}
Although browser support is a bit spotty (IE and Firefox support it, not sure about other browsers), for cross browser use you would have to fall back to the binding on the document approach you've already hit upon.

Detect Click on Empty Space in the Chromeless Youtube Player While Overlay Ad is Showing

Quick Summary
Is there a way in actionscript to detect when the user clicks on "empty space" in a chromeless video player instance (i.e. a click that doesn't cause the player to react)? This is particularly important when the chromeless player is displaying an overlay ad.
If not, is there a way to detected when a user clicks-on or closes an overlay ad?
Details
My flash-based application needs to interpret "empty" mouse clicks on the video window as a trigger for a specific action. This behavior is is demonstrated in youtube's "full" flash player - clicking on an "empty area" that doesn't otherwise invoke an action toggles between pause-and-play, and double-clicking an empty area toggles between windowed-and-fullscreen.
This is simple enough while playing self-hosted content - I can just assume any click on the video window is an empty click, and can act appropriately.
This, however, is not the case when I'm playing a youtube video, as it can popup an overlay ad over the video content. I need to allow the user to interact with the ad, but still let my application's logic handle clicks on the "empty" areas of the chromeless player.
I've spent ages trying to solve this, and haven't made any headway. The documentation doesn't cover this. There isn't any new state thrown via onStateChange in response to displaying or interacting with an ad. There doesn't appear to be an API change associated with displaying an overlay ad (no onApiChange is thrown, and polling getOptions() didn't turn up anything). Kludging a work-around using getObjectsUnderPoint didn't work. I even tried backwards-engineering the information by polling the Mouse.cursor state (it visually gets set to "hand" when hovering over interactive objects in the chromeless player... but it's set to "auto").
Any suggestion on how to accomplish this? Particularly in a manner that's transparent to whether the chromeless player is using StageVideo or not?
While this is an area where the Players API team recognizes the need to improve things (by creating a callback that's fired when an ad or other overlay is shown, or trying to return information about what rectangle of a video player is "safe" from overlays), there's nothing at the moment in the API that accomplishes what you're after.
Feel free to file a feature request for tracking purposes, and we can keep that up to date if anything develops.
As per Jeff Posnick's answer (no official way to do this), I ended up cobbling together a brittle solution using the code equivalent of screen-scraping.
On a mouse click, I traverse the chromeless player's DisplayObject hierarchy, filter out noise, and see if there's an object under the current point that's mouse-interactive.
It's brittle - a future change to the chromeless player can easily break this. And if the overlay ad contains AVM1 content it won't be accessible and will eat mouse events. But it's better than nothing. :(
Here's some sample code to demonstrate the concept. Pass in the chromeless player's DisplayObject, and the current mouse position in stage space. This will return whether the point has a mouse-interactive element under it, and will trace what the supported mouse-interactions are.
private function IsPointInteractive(displayObject:DisplayObject,
stageX:Number,
stageY:Number) : Boolean
{
const className:String = flash.utils.getQualifiedClassName(displayObject);
const container:DisplayObjectContainer = displayObject as DisplayObjectContainer;
if (!displayObject.visible)
return false;
if (className != "com.google.youtube.application::SwfProxy" &&
className != "com.google.youtube.application::VideoApplication" &&
className != "com.google.youtube.players::HTTPVideoPlayer" &&
className != "com.google.youtube.players::TagStreamPlayer" &&
(null == container || container.mouseEnabled) &&
displayObject.hitTestPoint(stageX, stageY, true) )
{
var supports:String = "";
if (displayObject.hasEventListener(MouseEvent.CLICK))
supports += "MouseEvent.CLICK";
if (displayObject.hasEventListener(MouseEvent.DOUBLE_CLICK))
supports += (0 == supports.length ? "" : ", ") + "DOUBLE_CLICK";
if (displayObject.hasEventListener(MouseEvent.MOUSE_DOWN))
supports += (0 == supports.length ? "" : ", ") + "MOUSE_DOWN";
if (displayObject.hasEventListener(MouseEvent.MOUSE_UP))
supports += (0 == supports.length ? "" : ", ") + "MOUSE_UP";
if (0 != supports.length)
{
trace(displayObject + " (" + className + ") [" + supports + "]");
return true;
}
}
if (container && container.mouseChildren)
{
for (var i:int = container.numChildren - 1; i >= 0; i--)
{
if (IsPointInteractive(container.getChildAt(i), stageX, stageY))
return true;
}
}
return false;
}

Can't get a working progress bar for file download AS3

I'm currently enrolled in an ActionScript course, and cannot seem to get my progress bar to work correctly. We were tasked with creating a simple image loader application, which would access externally hosted images (through use of a PHP proxy script), and then spit the image onto the user's screen (with a progress event and progress bar to track the image's download progress).
However, when I run it, I get these mysterious black graphical glitches everywhere, as well as a non-functioning progress bar. In some browsers I get the following error: "ArgumentError: Error #2109: Frame label NaN not found in scene NaN. at flash.display.MovieClip/gotoAndStop() at Document/imageLoadProgress().
Here is my code - I cant for the life of me figure out what is wrong. I figure it has something to do with the imageLoadProgress() function, or my progress bar (which is just a simple 100-frame movie clip with a motion tween and a "stop()" command at the beginning).
public function loadImage()
{
var imageURL:String = imageArray[currentImageIndex];
if(loaderInfo.url.substr(0,4) == "http")
{
trace("we're online");
//use the proxy script
//escape() will replace spaces in file names with %20
imageURL = "./image_proxy.php?filename=" + escape(imageArray[currentImageIndex]);
}
var imageRequest:URLRequest = new URLRequest(imageURL);
this.imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.imageIOError);
this.imageLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, this.imageLoadProgress);
this.imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.imageLoadComplete);
this.imageLoader.load(imageRequest);
//end loadImage
}
public function imageIOError(e:Event)
{
trace("ImageIOError called. Error=" + e);
//end imageIOError
}
public function imageLoadProgress(e:ProgressEvent)
{
var percentLoaded:Number = e.bytesLoaded/e.bytesTotal;
percentLoaded = Math.round(percentLoaded * 100);
//this.progress_mc.scaleY = percentLoaded;
if (percentLoaded < 1)
{
this.progressBar.gotoAndStop(1);
}
else
{
this.progressBar.gotoAndStop(percentLoaded);
}
//end imageLoadProgress
}
Your loader script seems absolutely fine to me, except for a tiny flaw:
The only way the NaN(== not a Number) in your error message makes sense to me is if your ProgressEvent's bytesTotal property equals 0 - because division by zero doesn't produce valid results, as we all know.
I can't say for sure why this happens, not knowing any of your server-side code, but I assume it would occur if your PHP proxy script does not set the Content-Length HTTP response header correctly. If you were loading an actual image file, the web server would automatically set the header for you - in the case of your proxy script, it seems you have to take care of it yourself.
Anyway, you can make your loader script more error-proof by testing for NaN, and making sure the frame you jump to is never greater than 100:
var frame:int = isNaN (percentLoaded) || percentLoaded < 1 ? 1 :
percentLoaded > 100 ? 100 : percentLoaded;
progressBar.gotoAndStop(frame);
(I chose shorthand notation, but this is essentially the same as writing two if statements and an else).