Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Zync

[Solved] Click or Touch through Blitmask to movieclip

Recommended Posts

Hey all,

 

It might just be really late but I'm stumped at the moment on a small blitMask problem.

I've got a blitMask which masks out a lot of movieclips with click events on them. I've got the scrolling working great with the buttons in the blitMask but I can't click on any of them. I think the blitMask is intercepting the clicks and not letting them go through to the buttons but I'm not quite sure what I'm doing here. No more Tequila and coding I think.

 

Cheers

 

-Z

Link to comment
Share on other sites

You have to set bitmapMode to false to enable clicking inside your movieclips again. When bitmapmode is true .. its really just an image of your movie clip. ;)

Link to comment
Share on other sites

Ah cheers for that. Knew it had to be something simple.

 

Small problem now is that on the mouse release it clicks through to the button underneath now instead of just scrolling. Guess it's working a bit too well. Tried testing the see if my moveClip isTweening and if it is don't proceed with the click actions but that doesnt quite work either. Is there a simple or more elegant solution for clicking on a movieclip while having a blitmask that allows for scrolling the clips?

 

Off topic, these new forums are awesome. Way more shiny than the old ones.

Link to comment
Share on other sites

Small problem now is that on the mouse release it clicks through to the button underneath now instead of just scrolling. Guess it's working a bit too well. Tried testing the see if my moveClip isTweening and if it is don't proceed with the click actions but that doesnt quite work either. Is there a simple or more elegant solution for clicking on a movieclip while having a blitmask that allows for scrolling the clips?

 

I'm not 100% sure I understood your question correctly, but if you're trying to disallow clicks through the BlitMask, have you tried simply adding a CLICK (or MOUSE_DOWN or whatever) listener to the BlitMask itself, thus intercepting any clicks and preventing them from affecting whatever is below the BlitMask in the display list? You don't have to actually do anything in your MouseEvent handler - the sole purpose is to tell Flash that this thing is clickable and should be the thing that receives MouseEvents rather than the ones below.

 

Off topic, these new forums are awesome. Way more shiny than the old ones.

Glad you noticed :) Yeah, a lot of effort went into the new forums. I think they're much more functional than the old ones (besides looking better). Enjoy!

Link to comment
Share on other sites

I'm not 100% sure I understood your question correctly, but if you're trying to disallow clicks through the BlitMask, have you tried simply adding a CLICK (or MOUSE_DOWN or whatever) listener to the BlitMask itself, thus intercepting any clicks and preventing them from affecting whatever is below the BlitMask in the display list? You don't have to actually do anything in your MouseEvent handler - the sole purpose is to tell Flash that this thing is clickable and should be the thing that receives MouseEvents rather than the ones below.

 

Yeah sorry about that, sober now. So the BlitMask is working great as well as the throwProps plugin. But at the moment when I goto scroll it's clicking the button in my itemHolder when I release the mouse button.

 

I have about 17 items with click event handlers on them inside my itemHolder and Blitmask is blitting the itemHolder and looking for mousemoves to track velocity for the throwprops. But yeah long story short., Is there a way to stop the click event from travelling through to the buttons in the itemHolder when releasing the mouse as part of a drag? Something about propagation or cancelling it?

 

 


public function setupBlitMask():void
{
//Setup mask
blitMask = new BlitMask(itemHolder, itemHolder.x, itemHolder.y, bounds.width, bounds.height, false, true);
blitMask.x = itemHolder.x;
blitMask.y = itemHolder.y;

blitMask.bitmapMode = false;

blitMask.addEventListener(MouseEvent.MOUSE_DOWN, blitMouseDownHandler);
blitMask.addEventListener(MouseEvent.MOUSE_WHEEL, blitMouseWheelHandler);
}

private function blitMouseWheelHandler(e:MouseEvent):void 
{
ThrowPropsPlugin.to(itemHolder, { throwProps: { y: { velocity: e.delta*50, max: bounds.top, min: bounds.top - yOverlap, resistance: 300 }}, onComplete:bScrolling = false, ease: Strong.easeOut }, 5, 0.2, 0.05);
}

private function blitMouseDownHandler(e:MouseEvent):void
{
e.stopImmediatePropagation();
TweenMax.killTweensOf(itemHolder);
y1 = y2 = itemHolder.y;
yOffset = this.mouseY - itemHolder.y;
yOverlap = Math.max(0, itemHolder.height - bounds.height);
t1 = t2 = getTimer();
itemHolder.stage.addEventListener(MouseEvent.MOUSE_MOVE, blitMouseMoveHandler);
itemHolder.stage.addEventListener(MouseEvent.MOUSE_UP, blitMouseUpHandler);

}

private function blitMouseUpHandler(e:MouseEvent):void
{
itemHolder.stage.removeEventListener(MouseEvent.MOUSE_UP, blitMouseUpHandler);
itemHolder.stage.removeEventListener(MouseEvent.MOUSE_MOVE, blitMouseMoveHandler);
var time:Number = (getTimer() - t2) / 1000;
var yVelocity:Number = (itemHolder.y - y2) / time;
ThrowPropsPlugin.to(itemHolder, { throwProps: { y: { velocity: yVelocity, max: bounds.top, min: bounds.top - yOverlap, resistance: 300 }}, onComplete:bScrolling = false, ease: Strong.easeOut }, 5, 0.2, 0.05);
}

private function blitMouseMoveHandler(e:MouseEvent):void
{
var y:Number = this.mouseY - yOffset;
//if mc's position exceeds the bounds, make it drag only half as far with each mouse movement (like iPhone/iPad behavior)
//trace(bounds.top, itemHolder.y);
if (y > bounds.top)
{
itemHolder.y = (y + bounds.top) * 0.5;
}
else if (y < bounds.top - yOverlap)
{
itemHolder.y = (y + bounds.top - yOverlap) * 0.5;
}
else
{
itemHolder.y = y;
}
//blitMask.update();
var t:uint = getTimer();
//if the frame rate is too high, we won't be able to track the velocity as well, so only update the values 20 times per second
if (t - t2 > 50)
{
y2 = y1;
t2 = t1;
y1 = itemHolder.y;
t1 = t;
}
e.updateAfterEvent();
}

Link to comment
Share on other sites

This becomes a common problem. Can you provide a well-working solution Jack?

 

This becomes really an issue on touch based devices.

 

Thanks.

Link to comment
Share on other sites

Below code seems sufficient.

if you just click and release, it fires button/movieclip listeners for the interactive items.

if you click and move the mouse, it detects throw action and does not fire button/mc listeners.

 

if you click while items animating, it does not fire button/mc listeners. Just stops the throw action.

 

//mc is the big moving movieclip

//mc_1 is the clickable movieclip inside the mc.

 

//note that i add onComplete:throwComplete for the ThrowPropsPlugin

 


import com.greensock.*; 
import com.greensock.easing.*;
import com.greensock.plugins.*;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import flash.events.MouseEvent;
import flash.text.*;
import flash.display.*;
import net.hires.debug.Stats;

TweenPlugin.activate([ThrowPropsPlugin]);

this.addChild(new Stats());

var bounds:Rectangle = new Rectangle(0, 200, 1280, 600);


var blitMask:BlitMask = new BlitMask(mc, bounds.x, bounds.y, bounds.width, bounds.height, false);
blitMask.bitmapMode=false;

var t1:uint, t2:uint, y1:Number, y2:Number, x1:Number, x2:Number, xOverlap:Number, xOffset:Number, yOverlap:Number, yOffset:Number;
var isMoving:Boolean=false;
var isCatched:Boolean=false;
blitMask.stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

function mouseDownHandler(event:MouseEvent):void {
TweenLite.killTweensOf(mc);
blitMask.disableBitmapMode();
if(isMoving==true)
{
isCatched=true;
isMoving=false;
}

x1 = x2 = mc.x;
xOffset = this.mouseX - mc.x;
xOverlap = Math.max(0, mc.width - bounds.width);
y1 = y2 = mc.y;
yOffset = this.mouseY - mc.y;
yOverlap = Math.max(0, mc.height - bounds.height);
t1 = t2 = getTimer();
mc.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
mc.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);



}

function mouseMoveHandler(event:MouseEvent):void {
isMoving=true;
if(blitMask.bitmapMode==false)
{
blitMask.enableBitmapMode();
}
/*
var y:Number = this.mouseY - yOffset;
//if mc's position exceeds the bounds, make it drag only half as far with each mouse movement (like iPhone/iPad behavior)
if (y > bounds.top) {
mc.y = (y + bounds.top) * 0.5;
} else if (y < bounds.top - yOverlap) {
mc.y = (y + bounds.top - yOverlap) * 0.5;
} else {
mc.y = y;
}
*/
var x:Number = this.mouseX - xOffset;
if (x > bounds.left) {
mc.x = (x + bounds.left) * 0.5;
} else if (x < bounds.left - xOverlap) {
mc.x = (x + bounds.left - xOverlap) * 0.5;
} else {
mc.x = x;
}
blitMask.update();
var t:uint = getTimer();
//if the frame rate is too high, we won't be able to track the velocity as well, so only update the values 20 times per second
if (t - t2 > 50) {
x2 = x1;
x1 = mc.x;
//y2 = y1;
t2 = t1;
//y1 = mc.y;
t1 = t;
}
event.updateAfterEvent();
}

function mouseUpHandler(event:MouseEvent):void
{
mc.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
mc.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
var time:Number = (getTimer() - t2) / 1000;
var xVelocity:Number = (mc.x - x2) / time;
//var yVelocity:Number = (mc.y - y2) / time;

ThrowPropsPlugin.to(mc, {throwProps:{ x:{velocity:xVelocity, max:bounds.left, min:bounds.left - xOverlap, resistance:50}}, onUpdate:blitMask.update, onComplete:throwComplete, ease:Strong.easeOut}, 5, 0.3, 1); 

}

function throwComplete ()
{
isMoving=false;
isCatched=false;
blitMask.disableBitmapMode();
}




mc.mc_1.addEventListener(MouseEvent.CLICK,onC);
function onC (e:MouseEvent)
{
if(isMoving==false && isCatched==false)
{
isc.text="Item Clicked..";
} else
{
isc.text="";
}
}


Link to comment
Share on other sites

That's a really nice solution. I was trying it with TweenMax.isTweening(itemHolder) on the button click handler but sadly no dice as it said the itemHolder was always tweening. Dunno why. But yeah this is common problem when building for AIR on touch devices.

 

Thought there would be a really sweet elegant solution for this by now but spent almost all of today searching and there's mostly just a few hacks. If I get a day free soon going to deifnintely develop something bulletproof but cheers so far mhmttosun

Link to comment
Share on other sites

Glad to see it is working. I updated the above code block.

Focus on blitMask.disableBitmapMode() and blitMask.enableBitmapMode() lines. It gives performance when mc is moving.

Link to comment
Share on other sites

I've noticed something weird with blitMask though and not sure if its a bug or its intended behavior but when I tween my individual clips inside of my holder clip the blitMask stops masking the spillover clips that would be outside the masks area and it reveals them.

 

I can still click and drag on the blitmask but the area outside of the blitMask's rect is now visible revealing everything that should be hidden. Weird ya? Only happens when tweening the child clips in the target of the blitmask.

Link to comment
Share on other sites

when those child clips are tweening are you forcing the BlitMask to update(null true)? Keep in mind that every time the content of the target of the BlitMask is changing, BlitMask needs to re-capture those pixels.

Link to comment
Share on other sites

yeah double checked that too Carl. Also

 

blitMask = new BlitMask(itemHolder, itemHolder.x, itemHolder.y, bounds.width, bounds.height, true, true);

 

If I setup the constructor like that it should autoUpdate as thats what the 2nd true is for right?

But I'm not sure if that makes any difference though as I've set:

 

blitMask.bitmapMode = false;

 

Because if its set to true nothing renders at all in the blipmask as the itemHolder animates in.

Link to comment
Share on other sites

Try putting this right under your blitMask = new line

 

TweenLite.delayedCall(0.1, blitMask.update, [null, true]);

Link to comment
Share on other sites

Zync, just to clarify, autoUpdate only monitors the BlitMask target's scale, rotation and position. It isn't aware that there are child clips "doing there own thing".

 

from what I understand if bitmapMode = true AND the content is constantly changing, you will need to constantly recapture the bitmap which isn't great for performance.

 

if you need have child clips animating, bitmapMode should be set to false during that animation. When that happens, BlitMask reverts to acting like a plain old mask.

 

if you are scrolling the BlitMask's target while child animations are taking place you will not gain the performance benefits of BlitMask.

 

make sense?

Link to comment
Share on other sites

Hi Carl,

 

Yup that makes perfect sense. I'm basically just rotating all the items in as a startup animation and after that point it's just a plain old movieclip with items and click listeners attached to them. Do I need to recapture the bitmap for blitmask everytime I start scrolling my itemHolder?

 


TweenMax.allFrom(aItems, 0.7, new TweenMaxVars( { rotationX:90, autoAlpha:0 } )
.onStart(blitMask.disableBitmapMode )
.onComplete(function() { blitMask.update() } )
, 0.1)

 

 

I'll upload a sample in a sec. Update. So here it is with bitmapMode turned off.

http://www.zyncinter....au/dev/vicmix/

 

Here's one without childAnimation for the transition in:

http://www.zyncinter...ev/vicmixNoAni/

 

When i turn bitmapmode mode on at anytime. The ImageLoaders in each item clip go blank. It's like it doesnt support bitmap mode for a nested clip either that or I havn't updated the bitmap properly. But you can still see how the masking from the blitmask doesnt work either. This only happens when i animate in the child clips of my itemHolder.

Link to comment
Share on other sites

immediately after setting bitmapMode = true, do blitMask.update(null, true) which will recapture the target with all the children in place

I think what is happening is that when your BlitMask is first initiatialized it is taking a capture prior to the assets being loaded(its totally blank) so when you turn bitmapMode on it is reverting to that empty capture.

Link to comment
Share on other sites

I get a really weird error when i try to enable bitmap mode now as well:

 

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.greensock::BlitMask/update()[F:\AS3Classes\com\greensock\BlitMask.as:265]
at com.greensock::BlitMask/set bitmapMode()[F:\AS3Classes\com\greensock\BlitMask.as:524]
at src.panels::vm_BasePanel/blitMouseDownHandler()[F:\wamp\www\vicmix2012\src\panels\vm_BasePanel.as:147]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at com.greensock::BlitMask/_mouseEventPassthrough()[F:\AS3Classes\com\greensock\BlitMask.as:443]

 

line 147 in my panelClass is just : blitMask.bitmapMode = true;

blitmask is definitely tracing out fine and it's there so no idea why it thinks its a null object.

Link to comment
Share on other sites

Did you call dispose() on it previously or something? That would null some variables to make it eligible for gc, so that'd explain the error (obviously you shouldn't dispose() a BlitMask that you intend to use again). Or did you maybe set a 3D property on the target, thus causing its transform.matrix to become null?

  • Like 1
Link to comment
Share on other sites

ZOMG thanks for the clarification on the 3D property. Yeah I am calling the following functions to hide and show the itemHolder mc. Had no idea the matrix had that kind of glitch in it (promise no black cat jokes):

 

 

public static function hidePanel(mc:MovieClip, nDelay:Number = 0)
{
TweenMax.to(mc, 0.5, { rotationY:-120, autoAlpha:0, delay:0 } );
}

public static function showPanel(mc:MovieClip, nDelay:Number = 0):void
{
TweenMax.fromTo(mc, 0.5, {rotationY:90, autoAlpha:0 }, {rotationY:0, autoAlpha:1, delay:0 } );
}

 

Got rid of the rotation Y's and now all is well with the blitmask and the click through's are working ace thanks to tosun as well. Cheers guys you rock!!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×