Override the mouse

Hi - an odd problem has just confronted me. Unity’s (much improved) UI system allows easily adding event triggers to UI buttons - for instance my inventory slots all have On Click(), Mouse Enter, Begin Drag etc all calling functions within my code. Which is terrific on PC. On PS Vita it also works, with touchscreen use effectively acting as the mouse.

My problem is that I want to add a joystick controlled cursor for fine control for the player. I can easily detect if no screentouch is happening, and control and draw my own fake mouse pointer, under joypad control. However… how do I get it to trigger UI triggers? I can’t just write into mousePosition.x and y - they’re read-only. Ditto the mouse click stuff.

The horrible solution is to have an entire separate system running that emulates all of these features, for hundreds of buttons, when no mouse or touch is detected - but it would be much nicer to trigger the already existing UI functionality. Any thoughts on this humdinger would be much appreciated.

If you want to make your own control system, then you simply create a new InputHandler system based off either the PointerInputModule/StandaloneInputModule or TouchInputModule.
Then simply remove the others and just use your own.

Check the source on the public UI bitbucket repo here for all the classes:
https://bitbucket.org/Unity-Technologies/ui/src/fd5d3578da8c33883b7c56dd2b2f4d4bbc87095b/UnityEngine.UI/EventSystem/InputModules/?at=4.6

Simon - thanks very much for the response! I’ve not done something like you’re suggesting in C# before - presumably I drop those files into my project (with new class and file names?) with the keyword override liberally sprinkled throughout? Presumably if I want to retain the original touchscreen functionality as well, I could check if the new cursor button is not held down, and just call the original functions from within the overridden ones. Sorry for noob questions!

Shouldn’t need to override, just create your own script and then attach it to the eventsystem GO. All it has to do is either inherit from the BaseInputModule or one of the others (if you just want to replace a specific process)
You can have as many input modules attached to the EventSystem as you like (just don’t go tooo crazy)

There are no Noob questions, just incoherent and unresponsive solutions :stuck_out_tongue:

Here is a quick introductory tutorial - doesnt quite go into the depth you need but it is a start…
http://unity3d.com/learn/tutorials/modules/beginner/ui/ui-events-and-event-triggers

Cheers guys! After several days of banging my head against the desk and mourning the demise of comments, I’ve nearly got it to work, but not quite. I made a Joypad class, which tracks and draws a fake pointer, based on joypad and button presses. That bit works. I also made a Joystick_Input_Module.cs, based on StandaloneInputModule, and that nearly works. It is derived from Pointer_Input_Module.cs, which is similar to the original, except it checks the joystick buttons, not mouse buttons. The problem is that the X button is not being registered - in fact UI elements are getting On Exit messages when I press the X button. Any thoughts as to where I’m going wrong?

Joystick_Input_Modules.cs (changes only listed)

  public override void UpdateModule()
  {
  m_LastMousePosition = m_MousePosition;
  m_MousePosition = Joypad.position; // was Input.mousePosition;
  }
  public override bool ShouldActivateModule()
  {
  if( !base.ShouldActivateModule() )
  return false;
  var shouldActivate = Joypad.active; // ie L trigger held down
  return shouldActivate;
  }
  public override void ActivateModule()
  {
  base.ActivateModule();
  m_MousePosition = Joypad.position;// Input.mousePosition;
  m_LastMousePosition = Joypad.position;// Input.mousePosition;
  var toSelect = eventSystem.currentSelectedGameObject;
  if( toSelect == null )
  toSelect = eventSystem.lastSelectedGameObject;
  if( toSelect == null )
  toSelect = eventSystem.firstSelectedGameObject;
  eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
  }
  private bool SendSubmitEventToSelectedObject()
  {
  if( eventSystem.currentSelectedGameObject == null )
  return false;
  var data = GetBaseEventData();
  if( Joypad.Select_Down() )//Input.GetButtonDown(m_SubmitButton) )
  ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler);
  if( Input.GetButtonDown(m_CancelButton) )
  ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler);
  return data.used;
  }

and Pointer_Input_Module.cs (copied from PointerInputModule.cs)

protected static PointerEventData.FramePressState StateForMouseButton( int buttonId )
  {
  //var pressed = Input.GetMouseButtonDown(buttonId);
  //var released = Input.GetMouseButtonUp(buttonId);
  bool pressed, released;
  if( buttonId == 0 )
  {
  pressed = Joypad.Select_Down();
  released = Joypad.Select_Up();
  }
  else
  {
  pressed = Joypad.Cancel_Down();
  released = Joypad.Cancel_Up();
  }
  // [...] rest of function unaltered
  }
  protected virtual MouseState GetMousePointerEventData()
  {
  // Populate the left button...
  PointerEventData leftData;
  var created = GetPointerData(kMouseLeftId, out leftData, true);
  leftData.Reset();
  if( created )
  leftData.position = Joypad.position;// Input.mousePosition;
  Vector2 pos = Joypad.position;//Input.mousePosition;
  leftData.delta = pos - leftData.position;
  leftData.position = pos;
  if( !Joypad.psp2 )
  leftData.scrollDelta = Input.mouseScrollDelta;
  else
  leftData.scrollDelta = Vector2.zero;
  // [...] rest of function unaltered
  }

Any help much appreciated - going slowly bananas trying to make it work. It’s close - UI elements change state as the pointer moves over them.
Cheers,
Robin.