Author Topic: Prevent sending events to specific GameObjects  (Read 7276 times)

Asse

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 70
    • View Profile
Prevent sending events to specific GameObjects
« on: July 10, 2012, 09:41:13 AM »
I want to stack popups and each added popup should prevent the lower popups from receiving input.

Now I don't want to use the fullscreen-collider approach (maybe we still want to show tooltips on hover or what do I know) and I also wouldn't like to disable all lower popups when a new one is added on the stack since this always leads to problems (e.g. external source enables it again and so on). I think it's best to not send them any input at all but I can imagine that this takes modifications on UICamera  :-[

Has anyone ever thought about this problem and has a good solution?

JRoch

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 140
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #1 on: July 10, 2012, 12:13:37 PM »
The popups can have their -Z offset by some multiplier of the number of popups currently shown.  Make sure that you have a full-screen sized collider under your popup (for each popup) that does nothing.  Mentally, you're layering up the layers of a cake, with each popup getting closer to the camera, and the frosting layer being a full-screen collider that intercepts interactions and prevents lower-level layers for receiving any events.

[EDIT:  just noticed you said you don't want to use the full-screen collider]

In this case you'll want all popups to have the same class script.  Part of that class would be a private static reference that indicates which dialog is top-most and receives interaction.  Part of the process of instancing a new popup would be setting that variable.  You'd likely need a simple stack or queue, really, so that as topmost dialogs are dismissed you could find the reference to the next one down in the stack.  Simply make sure that your OnClick (and other interactions) check if "this" dialog is the top-most, and return without action if it is not.

I wrote a class specifically for the "is part of a dialog" logical case, which each logical window (parent gameobject) I call a "StoreChildrenRecursively" function that adds the parent and all children to a HashTable using the object transform's InstanceID as the key, and the window's root gameobject transform InstanceID as the value for all of them.  Then I can do a hashtable lookup of something like IsChildOfWindow(windowGameObject, targetGameObject) and do a simple hashtable lookup to determine if it is.  That way you can track interaction at the "window" (or panel) level and not have to independently track every sub-widget.  I use this on pop-up menus that will auto-close if the mouse leaves the window area.

Anyhow, I'm getting a bit far afield from your original question.  The behavior you want is fairly easy to code, as long as all dialogs share a common script class that helps track state and provides a means to get back a boolean of whether or not the clicked/touched item is a child of the topmost popup.
« Last Edit: July 10, 2012, 12:25:51 PM by JRoch »

Asse

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 70
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #2 on: July 10, 2012, 12:17:02 PM »
Quote
Now I don't want to use the fullscreen-collider approach (maybe we still want to show tooltips on hover or what do I know)

JRoch

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 140
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #3 on: July 10, 2012, 12:26:12 PM »
Yeah, sorry.  Read my edited reply above.

Asse

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 70
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #4 on: July 10, 2012, 12:27:49 PM »
Thanks man, will have a closer look at it tomorrow!

JRoch

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 140
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #5 on: July 10, 2012, 12:34:43 PM »
I just realized that there will be behaviors that won't be good by just ignoring the events:  buttons will still Tween on mouseHover events, giving the impression that they are active.

Sooo... perhaps the popup parent object/panel has a collider that covers the whole surface of the popup itself, but the collider starts disabled.  When the popup loses focus (managed by the common class I allude to above) it would turn the collider on, thus preventing raycasts from reaching the widgets of the panel.

If you still want some interactivity, then you'll have to selectively disable widgets... which you may be able to do via getComponent<scriptclass>, but you'll still need some external common method of tracking gameobject references & states.  You don't want to be walking the hierarchy with "find" or "findChild" in instances where it will get called a lot.
« Last Edit: July 10, 2012, 12:38:40 PM by JRoch »

Asse

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 70
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #6 on: July 16, 2012, 04:43:45 AM »
Quote
NEW: UICamera now has a new property: "Generic Event Handler". If set, this object will receive a copy of all events regardless of where they go.

I would love to use this event handler to prevent forwarding events to specific widgets. What do you think Aren, don't you want to add this feature?  ::)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #7 on: July 16, 2012, 11:16:57 AM »
Might be useful...

JRoch

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 140
    • View Profile
Re: Prevent sending events to specific GameObjects
« Reply #8 on: July 16, 2012, 12:13:29 PM »
Some additional thinking on the original question:

You could develop some custom logic for your popup window class that tracks all sub-elements of the window.  Likely you'd want another class for the sub-elements that give you the ability to change some booleans in the editor as toggles.  For example, each control with a collider (and hence receives NGUI events) would have a "panel element" class that includes public vars like "disable if panel is not topmost".  Every sub-element (widget) would have this class attached so you could easily define what is toggled off or left on if the parent panel isn't topmost.

The popup window class could then be controlled by your main game logic.  It would track all currently open popup windows/panels and keep track of which is topmost.  When a popup gains or loses topmost status you can selectively enable/disable the colliders of all that window's widgets based upon the boolean variables alluded to in the paragraph above.  This would give you the ability to disable interactivity widgets (buttons) while leaving other information widgets (tooltips, mouseovers, etc) enabled if you like.

The popup window class would likely have to store the global popup window information in static variables that can be accessed across all instances.  Or perhaps you could create a manager class that does that work in a central location.  All depends upon your programming/logic preferences.