- Home /
What does 'Event.Use()' actually do, and when to call it?
I'm writing a node-based editor. This is the first time I interact heavily with Unity's GUI events. I'm confused about the 'Use' method. The doc says:
Call this method when you've used an event. The event's type will be set to EventType.Used, causing other GUI elements to ignore it.
While other links explain it as 'it makes the event get eaten'
I appreciate the doc effort doing such an amazing job to explain it thoroughly like that but I'm afraid my mind is too thick.
First of all "Call this method when you've used an event" - what does "you've used an event" mean, and when does that happen?
Usually, you get the current event and use it to query things, i.e.
var e = Event.current;
if (e.type == EventType.MouseDown && e.button == 0)
// do LMB stuff
else if (e.type == EventType.KeyDown && etc)
// do more stuff
Does that count as "me using the event"?
Another example, moving a window rect with mouse:
if (e.type == EventType.MouseDrag && rect.Contains(e.mousePosition))
{
rect.x += e.delta.x;
rect.y += e.delta.y;
}
How about that? does that require 'Use'?
Can somebody please explain to me any of the following:
What does 'Use' actually do?
When and why would I consider calling it?
Any help is much appreciated, thanks for your help and generosity reading my question in advance :)
Note: Please don't mention anything about 'eating' events, nor calling 'Use' when I 'used the event', I'll happily downvote and delete your answer on the spot :) j/k
Answer by HarshadK · May 21, 2015 at 08:59 AM
1) What does 'Use' actually do?
Consider the code snippet below:
void Processing()
{
bool resourceConsumed = false;
// Process #1
if(!resourceConsumed)
{
// Consume resource for process #1
resourceConsumed = true; // This is equivalent to Event.Use()
}
// Process #2
if(!resourceConsumed)
{
// Consume resource for process #2
resourceConsumed = true; // This is equivalent to Event.Use()
}
// Process #3
if(!resourceConsumed)
{
// Consume resource for process #3
resourceConsumed = true; // This is equivalent to Event.Use()
}
}
In above case, the moment we consume the resource and set it to be consumed, following processes will not perform their processing since no resource is available to them. But even if we consume the resource and do not set resourceConsumed then following process can still consume the resource.
Now setting resourceConsumed = true
does in above case to true is what Event.Use() does in case of Event. It just sets that event as used so that no other GUI element will process it. But if you do not set it to be used then other GUI elements can still access that event and use it for their processing.
2) When and why would I consider calling it?
Now in your code snippet
var e = Event.current;
if (e.type == EventType.MouseDown && e.button == 0)
// do LMB stuff
if you use Event.Use() after processing LMB no other GUI element will process that input like a button will not get clicked and so on. I know it might sound useless with this example but there might be cases like when two buttons are overlapping and you don't want both of them to get clicked and only one at the top to do so.
Now in another example of yours.
if (e.type == EventType.MouseDrag && rect.Contains(e.mousePosition))
{
rect.x += e.delta.x;
rect.y += e.delta.y;
}
If you are moving the window which is over some other GUI element, say another node Window then not using Event.Use() in your code snippet will cause both these GUI elements to process that input which I believe is undesired. But if you call the e.Use()
at the end of your if block above then only this window will process this input (if it is the first one to receive that event and event is still available for it to process), which I guess is desired effect.
Recently while developing a quest system based off Node Editor I used navigation keys for panning the window containing nodes. Now in my case I did not want any GUI element to process the navigation keys since I wanted to use it to pan so after performing the panning action I just used Event.Use() to avoid certain glitches that were causing because other GUI elements trying to process those keys, which wan unintended for me.
Hope this clears things for you.
Note: I have tried my best to steer clear of the prohibited words and phrases. ;-)
Thanks that was pretty metal \m/ I guess it just takes some practice and getting used to. I still have some questions, although you perfectly answered me.
In your
if (!resourceConsumed)
I guess that maps to my queries on the event? From what I understood from you, it might not be necessary to consume an event once you've done a query on it, it just needs some thinking about it.I guess
Event.current
get updated per OnGUI call?I see some people ignoring or only acting in Repaint or Layout phases, why would you want to do that? (I guess you could ignore Layout phase if you're only doing stuff via 'GUI'?)
@Harshad$$anonymous$$ also what about, say if I 'Use'd an event, and then accessed its mousePosition
afterwards, will I not get proper mouse coords? or is it that 'Use'ing an event doesn't affect the data that's in it, but just marks it so that other controls ignore it, a used condom basically lol
Yes.
if (!resourceConsumed)
is an equivalent of how Unity might be checking internally if it should process an event or not for the GUI element. Yes, you do not need to set an event as used if you are just querying it. It is like checking if the resource is available or not, whether to consume it or not is totally different story. You only set it to be used if you actually perform something using that event and now you don't want some other GUI element to process it.Yes. Actually it is OnGUI that gets called per Event Update so in each OnGUI you have a new event to process in the
Event.current
.Repaint event is called after all the other GUI elements have completed their processing. This allows you to not accidentally setting an event as used which was actually required by an another GUI element. With layout event it is exactly opposite. It gets called before anything. So you can intercept the event here and let it not propogate ahead. Also Repaint is called once per frame whereas OnGUI might get called multiple times per frame. And since OnGUI works as a state machine here is your chance to let some elements process the event if it requires and then get that event to process for yourself and not allow any other following GUI elements to not process it.
And yes, the data is still accessible but the event is just ignored.
And that is an analogy I'm never gonna forget!!!