What Im doing: menu with options appearing at a click point
Short video: Screen capture - 1f64bddfbb0a2c99fccf4b17bdc139ce - Gyazo
I used to have a script on canvas which decides whenever its a click on classic UI or is a click on a world object:
private void Update()
{
HandleClickInput();
}
private void HandleClickInput()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("user click");
eventData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
graphicRaycaster.Raycast(eventData, results);
bool hitUIButton = false;
foreach (RaycastResult result in results)
{
if (result.gameObject.tag == "UIButton")
{
hitUIButton = true;
break;
};
}
if (hitUIButton)
{
//DO STUFF THAN CLOSE
Debug.Log("CLICK ON UI ELEMENT");
}
else
{
CloseMenus();
mousePositionGlobal = Input.mousePosition;
PositionContextMenu();
ShowActionOptions();
}
}
}
So it was raycasting through gameobjects and if clicked on any object in the world, it would trigger appearance of buttons with actions related to this object. e.g.:
-click on ground - show button with movement option
-click on unit - show button with attack or interact option
and if one of the raycast results is an UI button it was just doing whats bound to the button.
Now Im trying to achieve the same logic with UIDocument, I wrote some logic already for UXML and connected it with the above script:
public class ContextMenuUXML : MonoBehaviour
{
private VisualElement root;
private VisualElement contextMenu;
private UQueryBuilder<Button> buttons;
private void OnEnable()
{
UIDocument uiDoc = GetComponent<UIDocument>();
root = uiDoc.rootVisualElement;
contextMenu = root.Q<VisualElement>(name: "ContextMenu");
buttons = GetAllButtons();
RegisterButtonCallbacks();
}
public void PositionContainer(Vector2 mousePosition)
{
Debug.Log("position container ");
contextMenu.style.top = Screen.height - mousePosition.y;
contextMenu.style.left = mousePosition.x;
}
private void OnDisable()
{
UnregisterButtonCallbacks();
}
public void ShowButton(string buttonName)
{
Debug.Log("showing button");
contextMenu.Q(name: buttonName).style.display = DisplayStyle.Flex;
}
public void HideButtons()
{
buttons.ForEach((Button button) =>
{
button.style.display = DisplayStyle.None;
});
}
private void RegisterButtonCallbacks()
{
buttons.ForEach((Button button) =>
{
button.RegisterCallback<ClickEvent>(ButtonOnClick);
});
}
}
However i dont quite understand how to only trigger whats bound to UI button, and not trigger a world click in this case.
So the question in short:
How to prevent click event on world objects when a click on ui element occurs?
Thank you