Check transparency - apache-flex

I have swf file(900x600) and main part of that file is transparense.
So I want by clicking in swf file know either user clicks on transaprent part of image or not...
I can get mouse coordinates by
event.localX
event.localY
So how to know in clicked part swf is transparent or not?

First of all, be sure, that you have some transparent sprite on background of your swf - otherwise you won't receive event.
Second, do not use pure local coordinates, they can contain local coordinates of another inner object, while you need them from root. For example, I've used stage's coordinates
If you receive mouse event, add mouse event listener to the root of that swf and write following:
var bmd:BitmapData = new BitmapData(1, 1, true, 0);
var pt:Point = new Point();
var m:Matrix = new Matrix();
m.translate(-e.stageX, -e.stageY);
bmd.draw(this, m);
var transparent:Boolean = !bmd.hitTest(pt, 0x00, pt);
trace('color: '+bmd.getPixel32(0,0).toString(16));
trace('is tranparent? ' + transparent);
bmd.dispose();

You can add an event listener on the stage for a mouse click, and check if e.target == stage.
Here is the code:
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.CLICK, hClick);
function hClick(e : MouseEvent) : void
{
trace(e.target == stage); // true if we click on the transparent zone, false if we hit a symbol on the stage.
}

Not the best or cleanest code but it should work.
This is not tested code I just whipped it up.
private function handleMouseDown(event:MouseEvent):void {
var pt:Point = new Point(event.localX, event.localY);
pt = event.target.globalToLocal(pt);
var tmp:int = int( (new uint( event.target.getPixel32(pt.x,pt.y) ).toString(16)).substr(0,2) );
if( tmp != 0 ){
trace( 'is transparent' )
}
}

Related

Select a game object and perform actions using GUI.Button (EventTrigger)

I am currently working on a strategy game and I want to preform actions using GUI.Button on game objects. I am using ray cast and mouse click to select the object however when I click on GUI.Button to take out another action the button disappears. I want to use that button to open up another GUI.Box to show some descriptions.
I know why the button is disappearing, it is because I am projecting the ray cast to my button clicks in the update function but how can I avoid this? I also know that I have to use EventTrigger however I am not familiar with javascript event trigger, I searched online but I couldn't find any helpful javascript.
Screenshots:
Here is my script:
#HideInInspector
var isCalled:int = 0;
#HideInInspector
var scWidth:int = 0;
#HideInInspector
var scHeight:int = 0;
function Start () {
scWidth = Screen.width;
scHeight = Screen.height;
}
function Update () {
if (Input.GetMouseButtonDown(0)) {
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)) {
if (hit.collider.tag == "House") {
isCalled = 1;
} else{
isCalled = 0;
}
}
}
}
function OnGUI(){
if(isCalled==1)
GUI.Button(Rect(scWidth/2,(scHeight/2)+(scHeight/4),120,120), name);
}
}
If I understood you right, the problem is that when you click on button the raycast is fired up before button click and you select different object or no object at all and button disappears or reappears but for another object, what you need to do is check if you clicked on GUI and if yes don't project the raycast that selects the objects. Here is how you are gonna do it.
var selectedUI : GameObject = EventSystem.current.currentSelectedGameObject;
if (Input.GetMouseButtonDown(0) && selectedUI) {
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)) {
if (hit.collider.tag == "House") {
isCalled = 1;
} else{
isCalled = 0;
}
}
}
I work in C#, so I might have done some syntax errors, but the logic is right.
There is a good trick when using legacy GUI system to avoid raycast when mouse is over GUI elements. Using tooltip to controll if you may cast your ray =)
Something like this (I also don't work with US so may I it needs some work):
var hover : String;
function OnGUI(){
if(GUI.Button (Rect (10,10,100,20), "My Button"));
hover = GUI.tooltip;
function Update () {
if(hover != "") {
// raycast logic
}
}
If you need to avoid raycast when your "popUp" window/panel is shown but you don't want a tooltip on it you may approach using a MouseOverGUI manager too.
It is just a static or singleton holding a boolean that you will set true when your mouse is over some rect that you don't want to cast rays using Rect.Contains(Event.current.mousePosition) and to false whenever it runs out of this rect.
Use this bool with or without tooltip var to allow raycast:
if(!MouseManager.MouseOverGUI) {
// raycast logic
}
Note that creating your rect on each OnGUI cycle will difficult to catch it and control the MouseOveGUI. Also it is a bad practice for performance because OnGUI runs more than once per frame so I'll suggest you to create you rects just once (recalculate it just when needed) and pass it to your GUI elements ;)
I think the easiest way is to create a GameObject(input blocker) which is not visible but have a collider. Place it in between the camera and level objects and deactivate it. When you select a GameObject using Raycast you enable that input blocker GameObject and place it around the area of selected GameObject and GUI. Then you have to ignore the selection if raycast is collided with Input Blocker. When you deselect the Gameobject then you deactivate input blocker
You should also maintain current state of the game for example:
enum State
{
NothingSelected = 0,
GameobjectSelected,
BigMenuOpen
}
State currentState;
So according to state you can define the behavior on mouse click. Like if Full screen menu is Open then raycast does not fire.

Unity How do I set up a GUITexture as a button?

I added GUITexture by going to Game object>>Create Other>>GUI Texture and added its texture in the inspector what I want now is when the user touches (Game is for android and IOS) that GUITexture to move cube up I tried this code
var up : GUITexture;
var player : Rigidbody2D;
function Update () {
for (var evt : Touch in Input.touches) {
var HitTest1 = up.HitTest(evt.position);
if (evt.phase == TouchPhase.Began) {
if(HitTest1){
player.rigidbody2D.AddForce(Vector2(-2,0));
fireButton.enabled = false;
}
}
}
}
But it didn't work. What can I do?
if (GUI.Button(Rect(10,10,50,50),up))
//Code to move cube up
This will create a GUIButton out of your texture. You would need to put this into the OnGUI function in your script. Here is a link to the reference for GUIButtons: GUIButtons
In your code you have declared player as a rigidbody
var player : Rigidbody2D;
and below are trying to access its rigidbody
player.rigidbody2D.AddForce(Vector2(-2,0)); //this won't work
player.AddForce(Vector2(-2,0));//*use this instead*
OR
Try declaring player as gameobject
var player:GameObject
and add force correctly
player.rigidbody2D.AddForce(Vector2(-2,0));

In ActionScript 3.5/Flex, how do I apply a border to whatever UI Component or container the user clicks?

I am working on a project where I want to add a click listener to the root DisplayObjectContainer, which, if the user clicks on a UIComponent, will add a red border to whatever the user clicked on. Currently, my code to do so looks something like this:
private static var _root:DisplayObjectContainer;
private static var labelStyle:CSSStyleDeclaration;
public static function initialize(root:DisplayObjectContainer):void
{
_root = root;
labelStyle = new CSSStyleDeclaration();
labelStyle.setStyle("borderColor", "red");
labelStyle.setStyle("borderThickness", 4);
labelStyle.setStyle("color", "red");
labelStyle.setStyle("borderStyle", "solid");
StyleManager.setStyleDeclaration(".mystyle", labelStyle, true);
_root.addEventListener(MouseEvent.CLICK, highlightBorder, true, Infinity, true);
}
private static function highlightBorder(event:MouseEvent):void
{
event.stopPropagation();
if(event.target is UIComponent)
{
var tmp:UIComponent = event.target as UIComponent;
tmp.styleDeclaration = labelStyle;
tmp.invalidateProperties();
tmp.invalidateDisplayList();
tmp.validateNow();
}
}
This code is in a .as file, not the .mxml.
Unfortunately, nothing actually happens. The UI component the user clicks on remains distinctly un-bordered. I've tested event.target and am reasonably sure that it does actually point to the UI Component the user clicked on; I also used Alerts to make sure that the if statement was actually executing fully.
Does anyone have any idea why the border is not changing?
Use the setStyle method on the UIComponent. So instead of tmp.styleDeclaration = labelStyle, do something like tmp.setStyle("styleName", "mystyle"), or skip the CSSStyleDeclaration part and do tmp.setStyle("borderColor", "red") and so on directly on the UIComponent.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/UIComponent.html#setStyle

How to dynamically load image for drag and drop?

I am implementing drag and drop from a DataGrid onto a List in a Flex 3 AIR application. I would like to have the drag image be a photo (jpg) referenced by a String field in the data grid item, named 'imagePath'. I'm having trouble getting the image to show up during dragging. I have triple checked that it is not because of an invalid path to the image. I have tried Image's source() and load() methods in every way I can think of. I am calling this method 'dragCurrentToList(event)' on a mouseDown event.
private function dragCurrentToList(event:MouseEvent):void
{
var current:Object = event.currentTarget.selectedItem;
var dragImg:Image = new Image();
dragImg.load(current.imagePath);
dragImg.width = 100;
dragImg.width = 100;
var dsource:DragSource = new DragSource();
dsource.addData(current, 'record');
DragManager.doDrag(event.currentTarget as DataGrid, dsource, event, dragImg);
}
This works perfectly if I set the image source to the following bindable variable but I don't want to hardcode the image name.
[Bindable]
[Embed(source='assets/icons/default.jpg')]
public var dragIcon:Class;
...
dragImg.source = dragIcon
...
In your dragCurrentToList method, why are you loading the image instead of just specifying the source attribute as the URL to the image?
http://livedocs.adobe.com/flex/3/langref/mx/controls/SWFLoader.html#source
private function dragCurrentToList(event:MouseEvent):void
{
var current:Object = event.currentTarget.selectedItem;
var dragImg:Image = new Image();
dragImg.source = current.imagePath;
dragImg.width = 100;
dragImg.width = 100;
var dsource:DragSource = new DragSource();
dsource.addData(current, 'record');
DragManager.doDrag(event.currentTarget as DataGrid, dsource, event, dragImg);
}
Also make sure you are responding to the dragStart event. ( http://livedocs.adobe.com/flex/3/langref/mx/core/UIComponent.html#event:dragStart ). And I believe instead of accessing the DragManager class; you should simply modify the dragSource property of the dragStart event.

Can an overlapping sibling prevent an Event?

Below is the code for a simple Flex actionscript project. A sprite is partially covering a hyperlink. What's happening is that when you hover over the sprite, if you're also hovering over the hyperlink, the hyperlink is activated. I want to prevent that. I want the hyperlink to be activated only when the mouse hovers over it -- but not when the mouse hovers over the sprite which covers it.
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TextEvent;
import flash.text.Font;
import flash.text.StyleSheet;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class SpriteHyperlinkTest extends Sprite
{
private var style : StyleSheet = new StyleSheet();
public function SpriteHyperlinkTest()
{
createOutputTextField();
}
public var output_txt : TextField;
private function createOutputTextField() : void {
// set styles
var hover : Object = new Object();
hover.fontWeight = "bold";
hover.color = "#0000FF";
var link : Object = new Object();
link.fontWeight = "bold";
link.textDecoration = "underline";
link.color = "#555555";
var active : Object = new Object();
active.fontWeight = "bold";
active.color = "#FF0000";
var visited : Object = new Object();
visited.fontWeight = "bold";
visited.color = "#cc0099";
visited.textDecoration = "underline";
style.setStyle("a:link", link);
style.setStyle("a:hover", hover);
style.setStyle("a:active", active);
style.setStyle(".visited", visited);
output_txt = new TextField();
output_txt.backgroundColor = 0xFFFFFF;
output_txt.background = true;
//output_txt.embedFonts = true;
output_txt.wordWrap = true;
output_txt.multiline = true;
output_txt.name = "output_txt";
output_txt.x = 100;
output_txt.y = 100;
output_txt.width = 300;
output_txt.height = 200;
output_txt.htmlText = "<b>sample <a href='http://www.google.com'>hyperlink text</a></b>";
addChild(output_txt);
var mySprite:Sprite = new Sprite();
mySprite.graphics.lineStyle(.5,0x000000);
mySprite.graphics.beginFill(0xff0000, 1);
mySprite.alpha = .7;
mySprite.graphics.drawRect(100, 100, 90, 20);
mySprite.graphics.endFill();
mySprite.useHandCursor = true;
mySprite.mouseChildren = true;
mySprite.buttonMode = true;
mySprite.name = "Sprite1";
this.addChild(mySprite);
output_txt.styleSheet = style;
}
}
}
I've almost found a workaround. It is just amazing that there isn't some object that you can place on top of the textfield in order to prevent its seeing the mouse overing over a hyperlink.
Here, for the record, are some of the things I've tried.
stopPropagation () // didn't work
stopImmediatePropagation(P //didn't work
Because the textfield and the sprite are siblings on the displaylist, I think all of the event propagation stuff is irrelevant. All of that has to do with ancestors and descendants, but what we're dealing with here is neither.
I tried placing another ('cover') textfield on top of the 'target' textfield. I tried setting the cover.visible = false; but that just meant it effectively wasn't there. I tried setting its alpha to .1, but that didn't work either -- just like the covering sprite, it allowed the mouseOver to go through it, so that the hyperlink responded.
I thought about trying to use preventDefault () on the hyperlink but a) I don't know how to reference the hyperlink (it has no ID) and b) the only event that is dispatched from a hyperlink is the TextEvent, and that's when it's clicked. We're not clicking, we're hovering. So I don't know what event to cancel.
The other thing I thought to do was to a kind of a fake 'cancel'. That is, maybe I could set the textformat, or style, of the hyperlink to look like normal text while the mouse is hovering over the sprite. The hyperlink would actually be being activated, but it would look like it isn't being activated because the style would be changed. This is what worked.
But it's only a fake visual workaround...
I'd add a rollOver (or whatever event you're trying to block) event listener to the sprite on top of the hyperlink. In the rollover handler, be sure to call event.stopImmediatePropagation() and that should prevent the hyperlink underneath from receiving the event.
I've never seen that sort of behavior before. Your sample code doesn't even assign events. I would be curious to see how you are assigning the events, because that in itself could be the cause of your problem.

Resources