How to consume mouse click on OnClicked event?

I have a player controller which executes an action if the mouse is pressed. And i have an actor with a OnClicked event, which does something if it’s clicked on.
Simple question: If the actor is clicked on, how to i prevent the player controller from executing it’s action?
I want the actor to block the input. The documentation says that actors have a higher priority than the player controller and if the actor consumes the input it will not be send to the player controller. However i can’t find any way to consume the mouse events on the OnClicked event.

I have the same problem, using Enhanced Input …
I have input mode to Game and UI
I have an OnClick for particular actions, and I’ve enabled click events in the player controller
I also have an IA_LeftClick bound to mouse left-click in the player controller
I’d love for the OnClick handler to be able to prevent the enhanced input action to fire when the actor is clicked, but so far, it seems both the OnClick on the targeted actor, and the IA_LeftClick will fire

personally i dont use onclicked, what you could do is on

IA_LeftClick do a gethitresultundercursor, if it hits an actor with say a clickable interface then run that code otherwise run your normal code

Yeah, it just seems silly to re-implement all that dispatch code that the engine already has …
I already do the cursor hit trace, for the click-on-ground-based box selection, but I use a channel that only traces for ground.

i find most of the inbuilt stuff half ■■■■■ at best, same with like apply damage.

also i want my controls to be on my controller, onclicked being on actors seems silly, you then have to send a message back to say if it was successfully clicked or not, etc

so yeah i trace, if the hit actor implements an interface i call events if not i assume its ground and issue move orders etc

If there are many different behaviors for different actors, having to code all of them into the player controller doesn’t actually work out very well – it’s a nightmare to maintain once you have more than three or four.

Yes, there needs to be a protocol for “things” to be able to present success/failure to the UI. Again, when there is large variability in what “things” and “actions” are, then well defined interfaces for the underlying operations will scale much better than twenty options in a switch statement.

Anyway, yes, I end up also ray casting, because I couldn’t find an easy way to “swallow” the click event from enhanced input. It might exist, but I consumed my “step through code” budget for now by tracing through the overlap object selection code for another action, so the original question will remain unanswered…

1 Like

thats what interfaces are for, just have a onclicked interface which returns a bool if its successful, i keep them in an array of actors so it works for everything so say if i click something new and want to disable the previously clicked actors i just run through an array. easy :smiley:

Why, yes, that is how you delegate to actors, rather than keeping all the logic in the player controller.

And there already exists an interface that does that in the engine – OnClicked()!

It’s a shame that we have to duplicate the functionality of that interface, just because there’s no way to make it play nice with Enhanced Input.
If we want to share code between projects, or get something into the marketplace, or just illustrate things in the forums, having to also add a bunch of custom interfaces is noticeably more cumbersome.

Here’s what I ended up with:
image
Nothing special, just very boring repetitive re-implementation.

well i dont disagree my point was more that it proves the inbuilt onclicked is borderline useless.

i mean the controller should know what it clicked on, the actor doesnt really care who it was clicked by therefore its better on the controller than the actor.

this way the logic is on the controller where it should be, which also makes it super easy to change between click,touch,gamepad or whatever, and only the effect is on the actor (highlight for instance)

Have you considered that having a global onclick event and another in actor doesn’t make much sense?
Have you looked at how the cropout Sample project works?

It makes total sense.

I can “click on an interactive thing” which will select or interact with that particular thing.
I can also “click on the non-interactive world” which will start a drag-select interaction.
The user experience of each of these interactions is different.

I understand you’re trying to share your experience, which is valuable. In this particular case, I don’t need suggestions for how to implement something if I do it all by myself – if that’s what I needed, I’d ask for that! What I’m asking for is whether there’s some way to use the facilities that are built-into the engine.

One conclusion I can draw, though, is that everyone who answered in this thread ended up “roll your own” rather than using the built-in facility, which is a data point in and of itself!

Well, one thing is where the event is managed and another is where the logic works. now I go back to my cave :sweat_smile:

That documentation is for input action events.

I don’t know much about EnhancedInput but with the old input events it looks like this

image

There you can easily have an actor consume input and it will not be received by PlayerController, because actor has a higher priority (provided it also has ReceiveInput set), just like the doc says. It might work the same with enhanced input events.
The caveat however is that the actor will eat all your clicks while it has input enabled, even if mouse cursor is not over it, so you’d have to enable its input when mousing over actor, and disable its input when mousing out.

OnClicked event looks like an afterthought that is not really integrated within the input system. You can see in the PlayerController code (function InputKey) that it does the OnClicked checks after forwarding the input to the input manager, so there’s no way you can consume it in the OnClicked event.
However you can override function in your own PlayerController class to rewrite the code as you see fit.

bool APlayerController::InputKey(const FInputKeyParams& Params)
{
    //... default boilerplate code for exotic devices that you might want to copy ...//

    // start by checking ClickEvents
    if (bEnableClickEvents && (ClickEventKeys.Contains(Params.Key) || ClickEventKeys.Contains(EKeys::AnyKey)))
    {
        //... copy code that retrieves ClickedPrimitive ...//

        if (ClickedPrimitive)
        {
            if (Params.Event == IE_Pressed || Params.Event == IE_DoubleClick)
                ClickedPrimitive->DispatchOnClicked(Params.Key);
            else if (Params.Event == IE_Released)
                ClickedPrimitive->DispatchOnReleased(Params.Key);
            return true;  //eat the input
        }
    }

    // default = forward to input manager
    if (PlayerInput)
        return PlayerInput->InputKey(Params);

    return false;
}