I’m looking to bind mouseover events to a given widget, which works, but when you add a sibling ui::Widget
that visually overlaps, I can’t figure out how to check to make sure that when you mouseover it, that there isn’t another widget in the way.
Say a scene is:
Node @root_node
\-> ui::Button @close_btn
\-> ui::Layout @fullscreen_layout
Where both close_btn
and fullscreen_layout
are added to root_node
, and fullscreen_layout
blocks the entire view (for the sake of example, its not fullscreen in every case. purely to explain that the close button is not visible whatsoever).
If you attach a EventMouseListener, there doesn’t seem to be a way to check that when you’re mousing over close_btn
, to determine that fullscreen_layout
isn’t blocking it.
ui::Widget::hitTest()
checks that the camera can see the object’s rect, not so much that it’s blocked by anything else. ui::Widget::isClippingParentContainsPoint
works for ancestors up the tree, but not non-ancestors.
How do you attach EventMouseListener?
Here’s my helper, I do things the standard way (I think). VoidFunc
is std::function<void()>
.
void bind_mouseover_to_widget(cocos2d::ui::Widget* hovered_widget, VoidFunc on_hover_func, VoidFunc on_lose_hover_func)
{
hovered_widget->setTouchEnabled(true);
auto event_mouse_listener = cocos2d::EventListenerMouse::create();
bool was_touched = false;
event_mouse_listener->onMouseMove = [hovered_widget, was_touched, on_hover_func, on_lose_hover_func](cocos2d::EventMouse* evt) mutable {
// TODO: figure out a way to check if the mouse is being blocked by something, things get weird
auto is_touching = mouse_evt_touches_widget(evt, hovered_widget);
bool widget_is_usable = hovered_widget->isEnabled() && hovered_widget->isTouchEnabled() && hovered_widget->isVisible();
if (is_touching && was_touched == false && widget_is_usable) {
was_touched = true;
} else if (is_touching == false && was_touched) {
was_touched = false;
on_lose_hover_func();
set_custom_cursor_normal();
}
if (widget_is_usable) {
try_set_highlighted(hovered_widget, is_touching);
if (is_touching) {
on_hover_func();
set_custom_cursor_hover();
//stop propagation so any widgets behind this one can't receive mouse hover too
// EDIT: except this broke hovers in the location buttons (and stops multiple things being bound to the same widget)
//evt->stopPropagation();
}
}
};
hovered_widget->getEventDispatcher()->addEventListenerWithSceneGraphPriority(event_mouse_listener, hovered_widget);
}