static void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) { var menuBounds = menu.localBounds; if (menuBounds.extents == Vector3.zero) { return; } Array.Clear(k_ColliderOverlaps, 0, k_ColliderOverlaps.Length); var hoveringCollider = false; var menuTransform = menu.menuContent.transform; var menuRotation = menuTransform.rotation; var viewerScale = Viewer.GetViewerScale(); var center = menuTransform.position + menuRotation * menuBounds.center * viewerScale; if (Physics.OverlapBoxNonAlloc(center, menuBounds.extents * viewerScale, k_ColliderOverlaps, menuRotation) > 0) { foreach (var overlap in k_ColliderOverlaps) { if (overlap) { k_WorkspaceComponents.Clear(); overlap.GetComponents(k_WorkspaceComponents); if (k_WorkspaceComponents.Count > 0) { hoveringCollider = true; } if (menu is MainMenu) { k_ButtonComponents.Clear(); overlap.GetComponents(k_ButtonComponents); if (k_ButtonComponents.Count > 0) { hoveringCollider = true; } } } } } // Only set if hidden--value is reset every frame if (hoveringCollider) { menuHideData.hideFlags |= MenuHideFlags.OverWorkspace; } }
static void AddAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) { foreach (var device in evr.m_DeviceData) { if (device.rayOrigin != rayOrigin) { continue; } device.alternateMenus.Add(alternateMenu); var menuHideData = new MenuHideData(); device.menuHideData[alternateMenu] = menuHideData; // Alternate menus must be visible the first frame or they are ignored in the priority list menuHideData.hideFlags = 0; break; } }
internal void UpdateMenuVisibilities() { k_ActiveDeviceData.Clear(); Rays.ForEachProxyDevice(deviceData => { k_ActiveDeviceData.Add(deviceData); }); foreach (var deviceData in k_ActiveDeviceData) { foreach (var kvp in deviceData.menuHideData) { kvp.Value.hideFlags &= ~MenuHideFlags.Temporary; } } foreach (var deviceData in k_ActiveDeviceData) { IAlternateMenu alternateMenu = null; var menuHideData = deviceData.menuHideData; // Always display the highest-priority alternate menu, and hide all others. var alternateMenus = deviceData.alternateMenus; foreach (var menu in alternateMenus) { var hideData = menuHideData[menu]; if ((hideData.hideFlags & MenuHideFlags.Hidden) == 0 && (alternateMenu == null || menu.priority >= alternateMenu.priority)) { alternateMenu = menu; } hideData.hideFlags |= MenuHideFlags.OtherMenu; } deviceData.alternateMenu = alternateMenu; menuHideData[alternateMenu].hideFlags = 0; var mainMenu = deviceData.mainMenu; var customMenu = deviceData.customMenu; MenuHideData customMenuHideData = null; var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); var alternateMenuData = menuHideData[alternateMenu]; var alternateMenuVisible = alternateMenuData.hideFlags == 0; var customMenuVisible = false; if (customMenu != null) { customMenuHideData = menuHideData[customMenu]; customMenuVisible = customMenuHideData.hideFlags == 0; } // Temporarily hide customMenu if other menus are visible or should be if (customMenuVisible && (mainMenuVisible || mainMenuSupressed)) { customMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; } // Temporarily hide alternateMenu if other menus are visible if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) { alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; } // Kick the alternate menu to the other hand if a main menu or custom menu is visible if (alternateMenuVisible && (mainMenuVisible || customMenuVisible) && alternateMenu is RadialMenu) { foreach (var otherDeviceData in k_ActiveDeviceData) { if (otherDeviceData == deviceData) { continue; } SetAlternateMenuVisibility(otherDeviceData.rayOrigin, true); break; } } // Check if menu bounds overlap with any workspace colliders foreach (var kvp in menuHideData) { CheckMenuColliderOverlaps(kvp.Key, kvp.Value); } // Check if there are currently any held objects, or if the other hand is in proximity for scaling CheckDirectSelection(deviceData, menuHideData, alternateMenuVisible); } // Set show/hide timings foreach (var deviceData in k_ActiveDeviceData) { foreach (var kvp in deviceData.menuHideData) { var hideFlags = kvp.Value.hideFlags; if ((hideFlags & ~MenuHideFlags.Hidden & ~MenuHideFlags.OtherMenu) == 0) { kvp.Value.autoHideTime = Time.time; } if (hideFlags != 0) { var menuHideData = kvp.Value; menuHideData.lastHideFlags = menuHideData.hideFlags; kvp.Value.autoShowTime = Time.time; } } } // Apply MenuHideFlags to UI visibility foreach (var deviceData in k_ActiveDeviceData) { var mainMenu = deviceData.mainMenu; var mainMenuHideData = deviceData.menuHideData[mainMenu]; var mainMenuHideFlags = mainMenuHideData.hideFlags; var lastMainMenuHideFlags = mainMenuHideData.lastHideFlags; var permanentlyHidden = (mainMenuHideFlags & MenuHideFlags.Hidden) != 0; var wasPermanentlyHidden = (lastMainMenuHideFlags & MenuHideFlags.Hidden) != 0; //Temporary states take effect after a delay var temporarilyHidden = (mainMenuHideFlags & MenuHideFlags.Temporary) != 0 && Time.time > mainMenuHideData.autoHideTime + k_MainMenuAutoHideDelay; var wasTemporarilyHidden = (lastMainMenuHideFlags & MenuHideFlags.Temporary) != 0 && Time.time > mainMenuHideData.autoShowTime + k_MainMenuAutoShowDelay; // If the menu is focused, only hide if Hidden is set (e.g. not temporary) in order to hide the selected tool if (permanentlyHidden || wasPermanentlyHidden || !mainMenu.focus && (temporarilyHidden || wasTemporarilyHidden)) { mainMenu.menuHideFlags = mainMenuHideFlags; } // Disable the main menu activator if any temporary states are set deviceData.toolsMenu.mainMenuActivatorInteractable = (mainMenuHideFlags & MenuHideFlags.Temporary) == 0; // Show/hide custom menu, if it exists var customMenu = deviceData.customMenu; if (customMenu != null) { customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; } var alternateMenus = deviceData.alternateMenus; foreach (var menu in alternateMenus) { menu.menuHideFlags = deviceData.menuHideData[menu].hideFlags; } UpdateAlternateMenuForDevice(deviceData); Rays.UpdateRayForDevice(deviceData, deviceData.rayOrigin); } evr.GetModule <DeviceInputModule>().UpdatePlayerHandleMaps(); }