2.9.16
Coherent GT
A modern user interface library for games
Detecting mouse position

Coherent GT provides very precise information about whether the mouse is over the UI and if it is what element is under it.

Transparency queries

In the case of view used as a HUD, the view may occupy the entire window of the game, but only non transparent (above a predefined threshold) parts are considered part of the view. For opaque views the query will always return false.

Implementing proper click through for a HUD view consists of the following steps:

  1. As early as possible in the frame use Coherent::UIGT::ViewRenderer::IssueMouseOnUIQuery with the current mouse position. Note that this is a method of the ViewRenderer class and thus must be called in the rendering thread of the client application. Mouse queries use rendering resources. It is the responsibility of the client application to propagate the latest mouse position to the rendering thread (if there is one) to be used in the query.
  2. As late as possible use Coherent::UIGT::ViewRenderer::FetchMouseOnUIQuery to wait for the result of the query. This is a blocking call, therefore it is important to have as many as possible draw calls between the two calls.
  3. Use Coherent::UIGT::View::IsMouseOnView to get whether the mouse is on part of the view with alpha above the currently set alpha threshold. This call will always return the result of the most recent query. Note that this is a method of the View and must be called in the main client UI thread.

To change the alpha threshold use Coherent::UIGT::View::SetClickThroughAlphaThreshold.

In order to minimize the impact on the performance of client's application, all mouse queries are asynchronous in Coherent GT and use the GPU. Strive to put as many calls between the calls to Coherent::UIGT::ViewRenderer::IssueMouseOnUIQuery and Coherent::UIGT::ViewRenderer::FetchMouseOnUIQuery as possible. In this way the overhead of the call can become virtually zero. Calling Coherent::UIGT::View::IsMouseOnView while a query is in-flight produces a warning and the result returned in undefined. Every valid call to Coherent::UIGT::View::IsMouseOnView returns the result of the last successful query. The result of the query is relative to the last drawn frame (a call to Coherent::UIGT::ViewRenderer::Paint).

This feature is implemented in the Renoir backend through GPU queries. Your backend must support the "click-through" methods in order for the feature to work correctly.

Input Group Queries

Besides knowing whether the mouse is over a transparent part of the view, it's sometimes useful to know what kind of HTML element the mouse is hovering. For example, you might need to disable input over certain parts of your UI or only allow some input.

This is done in two steps.

  1. Add the data-input-group attribute to any element you need to tag.
  2. Call Coherent::UIGT::View::GetInputGroupUnderCoordinates with any coordinates you need (usually the mouse position). The method will return the value of the attribute of the hovered element or the first ancestor of the element that has the attribute.

Here's an example - assume you want to disable right clicks over a collection of elements:

<div data-input-group="disable-right-click">
<button></button>
</div>
<div id="my-other-elements">
...
</div>
MyMouseEventData mouseData;
if (mouseData.IsRightButtonDown)
{
if (view->GetInputGroupUnderCoordinates(mouseData.X, mouseData.Y) != "disable-right-click")
{
view->HandleMouseEvent(...);
}
}

This method is on the View and is synchronous (unlike Coherent::UIGT::ViewRenderer::IssueMouseOnUIQuery). It should be called on the main UI thread. The cost of calling it is the same as sending a mouse down event to the view.