FOUND SOLUTION: PointerDownHandler Events on UI Scrollbar

:white_check_mark:Found a solution!:white_check_mark:

Hello there,

this is my first post, so im not sure if this is the right category.

Quick Summary

  • I have a custom virtual mouse.
  • I can interact with unity UI elements with pointerDownHandler events.
  • It works perfect for UI Sliders
  • :warning: It does not work for UI Scrollbars :warning:
  • except I trigger a dragHandler event after the pointerDownHandler event.
  • But the real mouse only needs the pointerDownHandler
  • Why?

/--------------Complete Details------------------/

My Goal

I want to create a custom virtual mouse on my own.

So far it works pretty well. I use the pointerDownHandler events and all of its “brothers and sisters” like dragHandler and so on.

I can now interact with my “custom virtual mouse” with all kinds of button, sliders and other UI elements.
I can use different kinds of Input Devices.
All fine, smooth and perfect.

/---------------------------------------/

Normal Unity Mouse behavior

When I click on a Scrollbar UI element with the mouse, the handle will jump to the mouse location as close as possible, it uses steps of 0.2 and moves to the nearest value of the mouse click.

Screenshot 2024-08-16 at 16.13.44

The mouse will trigger the following events

  • OnPointerDown —> This one will move the Scrollbar handle.
  • OnInitializePotentialDrag
    When the left mouse button was released
  • OnPointerUp
  • OnPointerClick

/---------------------------------------/

Problem

When I use my custom virtual mouse, which will execute the same events like a normal mouse in the same order, then it does not work for Scrollbars. Very confusing to my self it works out of the box with UI Sliders…
The Scrollbar value will stay at zero, if i debug the valueChange event of the scrollbar element I receive negative values of -0.2

It only works with a workaround of triggering a “dragHandler Event” after the “pointerDownHandler” event.

void OnPointerDown(){
        isPointerDown = true;
        isBeginnDropHandler = true;
        // pointer.position = gameObject.transform.position;
        ExecuteEvents.Execute(target, pointer, ExecuteEvents.pointerDownHandler); 
        ExecuteEvents.Execute(target, pointer, ExecuteEvents.initializePotentialDrag); 
        /* Dont know why i have do to this, 
         * because for the slider it works but the scrollbar always delivers negative values of -2
         * and the handle always stays on 0
        */
        if(target.GetComponent<Scrollbar>() is not null){
             ExecuteEvents.Execute(target, pointer, ExecuteEvents.beginDragHandler);
             ExecuteEvents.Execute(target, pointer, ExecuteEvents.dragHandler);
        }

Does someone know why? :slight_smile:
[/quote]

Hello there,

this is my first post, so im not sure if this is the right category.

Quick Summary

  • I have a custom virtual mouse.
  • I can interact with unity UI elements with pointerDownHandler events.
  • It works perfect for UI Sliders
  • :warning: It does not work for UI Scrollbars :warning:
  • except I trigger a dragHandler event after the pointerDownHandler event.
  • But the real mouse only needs the pointerDownHandler
  • Why?

/--------------Complete Details------------------/

My Goal

I want to create a custom virtual mouse on my own.

So far it works pretty well. I use the pointerDownHandler events and all of its “brothers and sisters” like dragHandler and so on.

I can now interact with my “custom virtual mouse” with all kinds of button, sliders and other UI elements.
I can use different kinds of Input Devices.
All fine, smooth and perfect.

/---------------------------------------/

Normal Unity Mouse behavior

When I click on a Scrollbar UI element with the mouse, the handle will jump to the mouse location as close as possible, it uses steps of 0.2 and moves to the nearest value of the mouse click.

Screenshot 2024-08-16 at 16.13.44

The mouse will trigger the following events

  • OnPointerDown —> This one will move the Scrollbar handle.
  • OnInitializePotentialDrag
    When the left mouse button was released
  • OnPointerUp
  • OnPointerClick

/---------------------------------------/

Problem

When I use my custom virtual mouse, which will execute the same events like a normal mouse in the same order, then it does not work for Scrollbars. Very confusing to my self it works out of the box with UI Sliders…
The Scrollbar value will stay at zero, if i debug the valueChange event of the scrollbar element I receive negative values of -0.2

It only works with a workaround of triggering a “dragHandler Event” after the “pointerDownHandler” event.

void OnPointerDown(){
        isPointerDown = true;
        isBeginnDropHandler = true;
        // pointer.position = gameObject.transform.position;
        ExecuteEvents.Execute(target, pointer, ExecuteEvents.pointerDownHandler); 
        ExecuteEvents.Execute(target, pointer, ExecuteEvents.initializePotentialDrag); 
        /* Dont know why i have do to this, 
         * because for the slider it works but the scrollbar always delivers negative values of -2
         * and the handle always stays on 0
        */
        if(target.GetComponent<Scrollbar>() is not null){
             ExecuteEvents.Execute(target, pointer, ExecuteEvents.beginDragHandler);
             ExecuteEvents.Execute(target, pointer, ExecuteEvents.dragHandler);
        }

Does someone know why? :slight_smile:

I don’t, but did you know the UI code is available up on github?

1 Like

:white_check_mark:
Solution
/---------/

I have found the solution of the problem!

My Custom Virtual Mouse can trigger OnPointerDown events but it will not create Raycasts like the real mouse will do.

What you have todo is the follwowing:

  1. Add a “GraphicRaycaster” Component to the Canvas
  2. On the “OnPointerDown” method perform Raycasts
  3. Check for the UI elements you want to hit
  4. set the “pointerCurrentRaycast” and “pointerPressRaycast”

The following code is very specific to my goal and not refactored yet, you just need to understand that you have to set the CurrentRayCast and PressRayCast before you Execute the PointerDownHandler!!!

public GraphicRaycaster graphicRaycaster;
private PointerEventData pointer = new PointerEventData(EventSystem.current);
private List<RaycastResult> results = new List<RaycastResult>();

void OnPointerDown(){
// I set the target in the OnTriggerEnter method, but I think you can omit it when you use Raycasts.
        if(target is not null){
// specific booleans I need, not important for this solution.
            isPointerDown = true;
            isBeginnDropHandler = true;

 // Here is the magic: Raycast using the Graphics Raycaster and my Custom Virtual Mouse click position
            graphicRaycaster.Raycast(pointer, results);
            // Get the UI Element you need - for me its the Scrollbar, but I will improve this to work for all UI elements.
            foreach (RaycastResult result in results)
            {
                if(result.gameObject.GetComponent<Scrollbar>() is not null){
// Set the CurrentRaycast & PressRayCast
                    pointer.pointerCurrentRaycast = result;
                    pointer.pointerPressRaycast = result;
                     Debug.Log("Hit " + result.gameObject.name);
                }
               
            }
// Finally set the position and Execute the Handlers.
            pointer.position = gameObject.transform.position;
            ExecuteEvents.Execute(target, pointer, ExecuteEvents.pointerDownHandler); 
            ExecuteEvents.Execute(target, pointer, ExecuteEvents.initializePotentialDrag); 
}