Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: UI click detection  (Read 2245 times)

0 Members and 1 Guest are viewing this topic.

Athenian Hoplite

  • Newbie
  • *
  • Posts: 19
  • Nenikikamen !
    • View Profile
UI click detection
« on: May 26, 2020, 12:09:29 am »
Hey,

In implementing my UI I have come to a standstill.
Right now to detect which UI element is being being focused I simply transverse my UI layers top to bottom and check to see if the mouse position is inside the UI elements rect. If it is I check to see if it also is inside one of its children's rect, that way I can always focus the deepest-in-the-hierarchy element.

Consider this simple hierarchy:
- Panel
    - TextBox

If my textbox is actually placed outside of the rect of its parent (either the whole textbox or even a part of it) then I will never be able to focus it since I always check from top to bottom in the UI hierarchy. This could be fixed if I forced child UI elements to be inside their parent's rect but I don't like that restriction since it takes away too much flexibility.

Now to solve this I could change my system to use a quad tree in which I would place my UI elements and not only would the whole process be probably much faster but I would get around this last issue. However it would bring about the new issue where I could no longer guarantee that the focused UI element is the deepest in the hierarchy, and this would put me at the mercy of clicking in a text box inside a panel and having the system return me the panel as the focused element instead of the text box.

Any ideas ?

Thanks in advance,
AH
"By will of the Athenian People be it resolved:
If anyone rises up against the people for tyranny or join in establishing the tyranny or overthrow the People of the Athenians and the democracy in Athens, whoever kills him who does these things shall be blameless." - Athenian Law 337 BC

unlight

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: UI click detection
« Reply #1 on: May 26, 2020, 04:31:38 am »
Quote
If my textbox is actually placed outside of the rect of its parent (either the whole textbox or even a part of it) then I will never be able to focus it since I always check from top to bottom in the UI hierarchy. This could be fixed if I forced child UI elements to be inside their parent's rect but I don't like that restriction since it takes away too much flexibility.

Might be an overly simplistic solution here, but what if you resized a parent elements "mouse-click-detection" bounding box to include the bounds of its children? If the parent element needs to be resized due to a child being added or removed then it could propegate the event up the tree so all parents could be adjusted accordingly.

Athenian Hoplite

  • Newbie
  • *
  • Posts: 19
  • Nenikikamen !
    • View Profile
Re: UI click detection
« Reply #2 on: May 26, 2020, 11:40:26 am »
Although that does make sense I have no way of concatenating the child's bounds into the parent just like that since I'm using a simple sf::Rect as the bounding box. My worst case scenario solution is to change the isWithinBounds(pos) function of my UIElement class that I use to search and return true if it is within its own bounds or one of its children since that would certainly fix it but that is already O(n) complexity just for that. I'd end up with O(n^2) complexity UI mouse detection and that jiggles my nerves. That is basically my last option if I don't get any better ideas
"By will of the Athenian People be it resolved:
If anyone rises up against the people for tyranny or join in establishing the tyranny or overthrow the People of the Athenians and the democracy in Athens, whoever kills him who does these things shall be blameless." - Athenian Law 337 BC

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: UI click detection
« Reply #3 on: May 26, 2020, 12:53:38 pm »
I thought it was more common to go a "bottom-up" approach. That you detect the clicks on whatever elements are shown to the user and then each UI element can be configured to consume or propagate the event to their parent. Then again most UI frameworks I've used only allow parent-child relations when the parent fully surrounds the child, so the child being outside of the parent rectangle could never happen...
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Athenian Hoplite

  • Newbie
  • *
  • Posts: 19
  • Nenikikamen !
    • View Profile
Re: UI click detection
« Reply #4 on: May 26, 2020, 02:08:36 pm »
I thought it was more common to go a "bottom-up" approach. That you detect the clicks on whatever elements are shown to the user and then each UI element can be configured to consume or propagate the event to their parent.

That is indeed what I do. When a UI element has subscribed to a certain event he gets notified and then can choose to either consume or propagate upwards. My event system is indeed "bottom-up". When I was talking from top to bottom I was referring to how to detect which UI element is being directly manipulated, in which case my system behaves as a sort of tree where I only go down one level if mouse position is within bounds of the Rect of that node int the tree (UI element) and as such I find always the deepest-in-the-hierarchy element. Which is exactly my issue since I want to be able to place elements outside the bounds of their parents.

Edit: I also do realize that I could simply ignore this and do these checks in the relevant event functions themselves but then if I have 50 subscribers to "onClick" I will run 50 on event functions for If I'm lucky only 1 of them to actually fire (the element over which the mouse was at the time of clicking).
« Last Edit: May 26, 2020, 02:11:05 pm by Athenian Hoplite »
"By will of the Athenian People be it resolved:
If anyone rises up against the people for tyranny or join in establishing the tyranny or overthrow the People of the Athenians and the democracy in Athens, whoever kills him who does these things shall be blameless." - Athenian Law 337 BC