Author Topic: scene picking and ui input handling  (Read 7400 times)

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
scene picking and ui input handling
« on: September 14, 2014, 02:36:49 AM »
Hello,

I just recently purchased ngui, and watched all the tutorial videos. Maybe this is really simple, or I missed it, but what is the suggested implementation for determining if a mouse button down or finger down happens, and whether or not it happened on a ngui control?

Previously I have an update method, and each time I check the mouse position, if its not over my UI, I check if any mouse buttons are down, and do scene picking via raycast.

Would I just hook into the uiroot's click events and perform a raycast for scene picking? Do I need to do anything specific to support touch vs mouse? What happens if my mouse goes down on a 3d object, is dragged over a button, and released..

My game has UI input handling and non-UI input handling, for scene picking and camera manipulation. Its not clear to me how to handle input. Suggestions?

Thanks for any help.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: scene picking and ui input handling
« Reply #1 on: September 14, 2014, 03:41:01 AM »
NGUI's events always go to the widget or collider underneath it, so if you click on a box visible by your main camera, that box will receive an OnClick event (assuming the main camera has UICamera attached).

Don't try to hook into UICamera's generic events (assuming thats what you meant by UIRoot's click events? UIRoot has no events). Generic event handlers give you a way to receive a copy of all events going out to other game objects. The actual events will still be sent to the proper objects (such as your buttons). Unless this is what you want -- to receive all events regardless of whether they're going?

UICamera.hoveredObject tells you what the mouse is hovering over. This won't work on touch devices as there is no "hover" on them.

Easiest way to do events in NGUI is to attach handlers directly to objects that you know will receive those events. So as in the box example above, there would be a script implementing "OnClick" function on it.

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
Re: scene picking and ui input handling
« Reply #2 on: September 14, 2014, 10:51:38 AM »
My game is made of tiles, and you can click them to select them.

I see how I can implement the OnClick functions for them, but how would I go about implementing the following:

1. When the player clicks space, i.e. nothing, de-select the currently selected tile.
2. When the player clicks and drags across space, the camera pans around.
3. Whenever player holds down right mouse button, moving mouse will rotate camera.
4. 2 finger pinch gesture for camera zoom and rotate

I guess it would be nice if I could know when a mouse down/mouse up/finger down/finger up happened, and whether it is over a UI control. I was thinking the uiroot has a panel and if it got input events, it means no widgets handled it.

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
Re: scene picking and ui input handling
« Reply #3 on: September 15, 2014, 03:32:04 AM »
I think I've figured it out.  I'm not sure what you mean when you say UIRoot has no events, but I added a "UIEvent Trigger" component to my UI Root, and now I can get notified when press/release/click/double click/drag/etc events occur and are not consumed by any UI elements (with box colliders).  Excellent! (My input handler script will get these events that are not consumed by the UI and use them to do scene picking and camera manipulation)

Thanks Aren for the quick response earlier.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: scene picking and ui input handling
« Reply #4 on: September 15, 2014, 04:33:37 AM »
That's the UICamera.fallThrough object. If not explicitly set, UICamera sets it to the root by default, so that object gets a copy of all events if nothing else does.

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
Re: scene picking and ui input handling
« Reply #5 on: September 15, 2014, 02:36:52 PM »
2 more questions:

1. My InputHandler stores a reference to my camera system, however when the OnDragOver function is called, my reference is null. Is this some kind of multi-threading issue?
2. The OnDragOver function is only called once, I was hoping for a function that lets me know every time the mouse/finger is down and has been moved.  Will I just need to track this in my own update loop, or am I missing something?

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
Re: scene picking and ui input handling
« Reply #6 on: September 15, 2014, 05:00:01 PM »
First issue I believe is a bug in my code. The object I want to receive the events does not exist until runtime, so I need to programmatically register my callbacks.

Will the following code cause any unforeseen issues? I'm used to just doing x.OnClick += myFunction.  Seems to be working..
  1.                 UIEventTrigger trigger = GameObject.Find ("UI Root").GetComponent<UIEventTrigger> ();
  2.                 trigger.onPress.Add (new EventDelegate (OnPress));
  3.                 trigger.onRelease.Add (new EventDelegate (OnRelease));
  4.                 trigger.onClick.Add (new EventDelegate (OnClick));
  5.                 trigger.onDoubleClick.Add (new EventDelegate (OnDoubleClick));
  6.                 trigger.onDragOut.Add (new EventDelegate (OnDragOver));
  7.  

And the second question still remains. It seems like UICamera.cs internally has an OnDrag event type, but its not exposed for some reason. Maybe my situation is unique, but I'd like to know when the finger or mouse is pressed and is dragged across a UI control with a hit collider. (I'd want it to be called repeatedly over time while dragging occurs)
« Last Edit: September 15, 2014, 05:06:04 PM by bkinsey »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: scene picking and ui input handling
« Reply #7 on: September 16, 2014, 09:21:52 AM »
1. Never use GameObject.Find(name). If you must find something by name, use tags (GameObject.FindObjectWithTag). I'm pretty tired of explaining this over and over, so I won't bother anymore. You can search the forum if you like, there are hundreds of these posts.

2. Why do you say onDrag isn't exposed? UICamera.onDrag is there, a public delegate. Same as onDragOver, onDragOut, onDragStart, onDragEnd. Why do you use UIEventTrigger? Why not just use the UICamera's generic delegates that I just mentioned?

bkinsey

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 30
    • View Profile
Re: scene picking and ui input handling
« Reply #8 on: September 16, 2014, 01:05:17 PM »
I must be searching for the wrong keywords, FindObjectWithTag only gave me one other post, and it wasn't informative at all.  I'm guessing GameObject.Find is not very efficient, or is there another reason it can be bad? I typically only use this to store a reference to an object, so unless its ridiculously expensive, I wouldn't worry about it. (Also, I never tag anything.. maybe I should start doing that or something)

Ok so I figured out what you were talking about.  UICamera will make blind function calls for the events when they occur, but it doesn't expose any explicit way to get the "OnDrag" event, for example.. it will just call any 'void OnDrag(Vector2 delta)' function signature it can find.

I've updated the UIEvent Trigger class to expose this event.. however can I make the request that you add it to your next set of updates?  That way I don't have an NGUI code base that is divergent from yours.

  1. [AddComponentMenu("NGUI/Interaction/Event Trigger")]
  2. public class UIEventTrigger : MonoBehaviour
  3. {
  4.         ...
  5.         public List<EventDelegate> onDrag = new List<EventDelegate>();
  6.         ...
  7.         void OnDrag (Vector2 delta)
  8.         {
  9.                 if (current != null) return;
  10.                 current = this;
  11.                 EventDelegate.Execute(onDrag);
  12.                 current = null;
  13.         }
  14.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: scene picking and ui input handling
« Reply #9 on: September 17, 2014, 11:45:40 AM »
Yes, it's ridiculously expensive and it's also very poor programming practice to find objects by name. Names can change easily, and there is no reference between object's name and your code, so you won't see any compile errors when you or your coworker renames something without thinking.

I'll add OnDrag, OnDragStart and OnDragEnd.