LibGDX offers event listeners that we can attach to buttons. Inside listener there is a method touchUp() we can override. I come from iOS dev and in iOS there was an option touchUpInside and touchUpOutside. Namely, if the user released the finger inside the area of a button touchUpInside was called and if the user lifted finger outside the button area, touchUpOutside was called. Does libGDX offer similar functionality or is up to developers to implement that? The default libgdx touchUp does not differentiate these to scenarios.
edit: I used this code but this is extremely imprecise. I'm getting a lot of false touchUp's
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
if(x<button.getX()||x>(button.getX()+button.getWidth())||y<button.getY()||y>(button.getY()+button.getHeight())){
System.out.println("retuuurn");
return;
}
}
This works:
if(x<button.getOriginX()-button.getWidth()*0.5f||x>(button.getOriginX()+button.getWidth()*0.5f)||y<button.getOriginY() - button.getHeight()*0.5f||y>(button.getOriginY()+button.getHeight()*0.5f)){
//do stuff
}
Related
What's the proper way to start a Litho animation when an Activity is first displayed. All of the Litho animation examples are initiated by a user action, but I want to run one automatically.
I tried to extend a Litho animation example RTAnimationComponentSpec to fire the animation for the #OnEvent(VisibleEvent.class) instead of just #OnEvent(ClickEvent.class). But it didn't fire though.
Existing click event handler:
#OnEvent(ClickEvent.class)
static void onClick(ComponentContext c) {
RTAnimationComponent.updateStateSync(c);
}
Additional event handler that I added:
#OnEvent(VisibleEvent.class)
static void onVisible(ComponentContext c) {
RTAnimationComponent.updateStateSync(c);
}
I confirmed the VisibleEvent didn't fire by:
Loading the Render Thread example and confirmed the animation didn't start
Setting a breakpoint in the onVisible() method
How can I run a Litho animation automatically?
One solution I found works is to make use of the #OnCreateInitialState
#OnCreateInitialState
static void createInitialState(
ComponentContext c,
StateValue<Boolean> state) {
state.set(true);
}
This runs the animation, but I'm not sure if it's the preferred way.
I have a :
Screen implementing InputProcessor
A stage created in the screen.
an Actor added to the stage
the Actor has a InputListener with a touchUp method, which is called when the actor is touched.
When clicking on the actor the method touchUp of the actors inputlistener is called and the touchUp from the InputProcessor is also called.
Question:
How can I prevent calling the touchup method from the screen ? My goal is only to handle the event from actor. I would like to only react on the touch from the actor and not also from the screen.
Here's a references to help you better understand my answer:
https://libgdx.badlogicgames.com/ci/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/InputListener.html#touchDown-com.badlogic.gdx.scenes.scene2d.InputEvent-float-float-int-int-
That link shows one of the methods in the InputListener class. In your question, you asked about the touchUp method which is also related to the touchDown method.
The touchDown method returns a boolean while touchUp is void. Because of this, you can't cancel a "touch up" event. However, you can "cancel" a "touch down" event by returning true. I say "cancel" because it's not really cancelling it, it's just letting the implementation know that you are handling the "touch down" and "touch up" events now.
Using the touchDown method is probably your best option. I believe you will still be able to use touchUp but I am unaware if other listeners receive the touchUp call if touchDown returned true (Given the documentation, I don't think they will). That's something you'll have to test for yourself.
Now if you really need cancel a "touch up" event, do this:
https://libgdx.badlogicgames.com/ci/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/Event.html#cancel--
You can try to cancel the event. Because the touchUp method in InputListener passes an InputEvent object, you can try to cancel it using inputEvent.cancel()
If you will catch Events like touchUp, touchDown etc. you must say that the event is handled otherwise the event will run to the next InputListener until one Listener says that the event is handled.
To set the Event to handled you must call the handle() method on the event object:
actor.addListener(new InputListener(){
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
event.handle();
}
});
Here it is described a little bit more with InputMultiplexer: Screen responds when button is clicked
I'm making this game in flash in which I want the user to draw straight lines (to create an unclosed shape) and I want to stop drawing the lines by double clicking.
My drawing board is a movie clip (not the stage).
I've put the double click event listener on the board and also added the doubleClickEnabled = true to the board.
However, no matter what I do, the board won't recognise my double click.
The click event gets triggered when there is some clickable entity at the event location. In other words, by for example, "double clicking" on a "transparent" region in your "drawing board", the associated event handler will not be called.
As a solution to the issue, however, you may utilize the stage object, since it occupies the entire display area; thus receives the mouse events anyways. The idea is to let the stage's event handler to inform the drawing-board's counterpart about the event occurrence:
board.doubleClickEnabled = true;
board.addEventListener(MouseEvent.DOUBLE_CLICK, onBoardDBLClick);
stage.doubleClickEnabled = true;
stage.addEventListener(MouseEvent.DOUBLE_CLICK, onStageDBLClick);
function onStageDBLClick(e:MouseEvent):void {
trace("STAGE double clicked.");
// if the location is inside the "board", then inform the "board" about the event!
if (board.getBounds(stage).contains(e.stageX, e.stageY)) {
onBoardDBLClick(e);
}
}
function onBoardDBLClick(e:MouseEvent):void {
trace("The Double-click logic of the board.");
e.stopPropagation();
}
Two years ago, when I was developing an application for the iPhone, I used the following built-in system method on all of my buttons:
[button setExclusiveTouch:YES];
Essentially, if you had many buttons on screen, this method insured that the application wouldn't be permitted do crazy things when several button events firing at the same time as any new button press would cancel all others.
problematic: ButtonA and ButtonB are available. Each button has a mouse up event which fire a specific animated (tweened) reorganization/layout of the UI. If both button's events are fired at the same time, their events will likely conflict, causing a strange new layout, perhaps a runtime error.
solution: Application buttons cancel any current pending mouse up events when said button enters mouse down.
private function mouseDownEventHandler(evt:MouseEvent):void
{
//if other buttons are currently in a mouse down state ready to fire
//a mouse up event, cancel them all here.
}
It's simple to manually handle this if there are only a few buttons on stage, but managing buttons becomes more and more complicated / bug-prone if there are several / many buttons available.
Is there a convenience method available in AIR specifically for this functionality?
I'm not aware of such thing.
I guess your best bet would be creating your own Button class where you handle mouse down, set a static flag and prevent reaction if that flag has been already set up by other instance of the same class.
In pseudo-code:
class MyButton
{
private static var pressed : Boolean = false;
function mouseDown(evt : MouseEvent)
{
if(!pressed)
{
pressed = true;
// Do your thing
}
}
}
Just remember to set pressed to false on mouse up and you should be good to go.
HTH,
J
I am coding a drag and drop application where I can grab an object and then place it over different object containers. When I am dragging the object (keeping the mouse button pressed) and I leave the stage, I can still control the object with the mouse...this is not what I want.
I would like to lose control of the object when the mouse leaves the stage.
I tried to remove the event listener for MOUSE_DOWN on a MOUSE_LEAVE event but nothing.
I also tried to dispatch a MOUSE_UP event on a MOUSE_LEAVE event but it does not work either...it works only if I manually release the mouse button.
Is there any way to override the MOUSE_DOWN event when the user moves the mouse away from the screen but he is still pressing the mouse button???
Any suggestion???
Thanks in advance
Is the stage actually listening to the MOUSE_LEAVE event? In any case , check this article, it may help:
http://www.kirupa.com/developer/flashcs3/detecting_when_mouse_leaves_movie.htm
Here's a couple tricky traps not to fall into :
One bizarre thing is that in Chrome + Firefox, the MOUSE_LEAVE event isn't dispatched for a WMODE of OPAQUE orTRANSPARENT. It just doesn't fire - mouse down or up.
With WINDOW it works fine. That one took me a long time to find out! grr... http://bugs.adobe.com/jira/browse/FP-892
Second, make sure you're using Event for the parameter type for your Event.MOUSE_LEAVE handler and not MouseEvent. If you try to handle MOUSE_LEAVE with e:MouseEvent you'll get an error that you may never see (unless you're using the debug flash player). It's a very easy mistake to make because you're probably pointing all your other handlers to the same method.
Here's what I do: (just call my main endDrag from mouseLeave(e:Event)
stage.addEventListener(MouseEvent.MOUSE_MOVE, drag);
stage.addEventListener(MouseEvent.MOUSE_UP, endDrag);
stage.addEventListener(Event.DEACTIVATE, endDrag);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
private function mouseLeave(e:Event):void
{
endDrag(new MouseEvent("MOUSE_LEAVE"));
}
public function endDrag(evt:MouseEvent):void
{
/// handle end drag
}
I believe you are talking about the user leaving the flash content altogether with mouse clicked, and when he/she returns it continues the process right?
I suggest, you track the mouse x & y coordinates. Set a condition which triggers the mouse up event handler when the x or y is equal to the stage width or height respectively.
When you drag an object outside the flash movie, the object will fire a MOUSE_OUT event. You can listen to this event, use a variable to check if the object is being dragged, and, if so, dispatch a MOUSE_UP event.
some_object.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
some_object.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
some_object.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
private function mouseOutHandler(e:MouseEvent):void
{
if (isDragging)
e.target.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
}
private function mouseDownHandler(e:MouseEvent):void
{
e.target.startDrag();
isDragging = true;
}
private function mouseUpHandler(e:MouseEvent):void
{
e.target.stopDrag();
isDragging = false;
}