public void Update() { if (!CommonScriptableObjects.rendererState.Get() || charCamera == null) { return; } IWorldState worldState = Environment.i.world.state; // We use Physics.Raycast() instead of our raycastHandler.Raycast() as that one is slower, sometimes 2x, because it fetches info we don't need here bool didHit = Physics.Raycast(GetRayFromCamera(), out hitInfo, Mathf.Infinity, PhysicsLayers.physicsCastLayerMaskWithoutCharacter); bool uiIsBlocking = false; string currentSceneId = worldState.currentSceneId; bool validCurrentSceneId = !string.IsNullOrEmpty(currentSceneId); bool validCurrentScene = validCurrentSceneId && worldState.loadedScenes.ContainsKey(currentSceneId); // NOTE: in case of a single scene loaded (preview or builder) sceneId is set to null when stepping outside if (didHit && validCurrentSceneId && validCurrentScene) { UIScreenSpace currentUIScreenSpace = worldState.loadedScenes[currentSceneId].GetSharedComponent <UIScreenSpace>(); GraphicRaycaster raycaster = currentUIScreenSpace?.graphicRaycaster; if (raycaster) { uiGraphicRaycastPointerEventData.position = new Vector2(Screen.width / 2, Screen.height / 2); uiGraphicRaycastResults.Clear(); raycaster.Raycast(uiGraphicRaycastPointerEventData, uiGraphicRaycastResults); uiIsBlocking = uiGraphicRaycastResults.Count > 0; } } if (!didHit || uiIsBlocking) { clickHandler = null; UnhoverLastHoveredObject(hoverController); return; } var raycastHandlerTarget = hitInfo.collider.GetComponent <IRaycastPointerHandler>(); if (raycastHandlerTarget != null) { ResolveGenericRaycastHandlers(raycastHandlerTarget); UnhoverLastHoveredObject(hoverController); return; } if (CollidersManager.i.GetColliderInfo(hitInfo.collider, out ColliderInfo info)) { newHoveredEvent = info.entity.gameObject.GetComponentInChildren <IPointerEvent>(); } else { newHoveredEvent = hitInfo.collider.GetComponentInChildren <IPointerEvent>(); } clickHandler = null; if (!EventObjectCanBeHovered(info, hitInfo.distance)) { UnhoverLastHoveredObject(hoverController); return; } newHoveredGO = newHoveredEvent.GetTransform().gameObject; if (newHoveredGO != lastHoveredObject) { UnhoverLastHoveredObject(hoverController); lastHoveredObject = newHoveredGO; lastHoveredEventList = newHoveredGO.GetComponents <IPointerEvent>(); OnPointerHoverStarts?.Invoke(); } // OnPointerDown/OnClick and OnPointerUp should display their hover feedback at different moments if (lastHoveredEventList != null && lastHoveredEventList.Length > 0) { for (int i = 0; i < lastHoveredEventList.Length; i++) { IPointerEvent e = lastHoveredEventList[i]; bool eventButtonIsPressed = InputController_Legacy.i.IsPressed(e.GetActionButton()); bool isClick = e.GetEventType() == PointerEventType.CLICK; bool isDown = e.GetEventType() == PointerEventType.DOWN; bool isUp = e.GetEventType() == PointerEventType.UP; if (isUp && eventButtonIsPressed) { e.SetHoverState(true); } else if ((isDown || isClick) && !eventButtonIsPressed) { e.SetHoverState(true); } else { e.SetHoverState(false); } } } newHoveredGO = null; newHoveredEvent = null; }
private void ProcessButtonDown(WebInterface.ACTION_BUTTON buttonId, bool useRaycast, LayerMask pointerEventLayer, int globalLayer) { IWorldState worldState = Environment.i.world.state; RaycastHitInfo raycastGlobalLayerHitInfo; Ray ray = GetRayFromCamera(); // Raycast for pointer event components RaycastResultInfo raycastInfoPointerEventLayer = raycastHandler.Raycast(ray, charCamera.farClipPlane, pointerEventLayer, worldState.loadedScenes[worldState.currentSceneId]); // Raycast for global pointer events RaycastResultInfo raycastInfoGlobalLayer = raycastHandler.Raycast(ray, charCamera.farClipPlane, globalLayer, worldState.loadedScenes[worldState.currentSceneId]); raycastGlobalLayerHitInfo = raycastInfoGlobalLayer.hitInfo; bool isOnClickComponentBlocked = IsBlockingOnClick(raycastInfoPointerEventLayer.hitInfo, raycastGlobalLayerHitInfo); if (!isOnClickComponentBlocked && raycastInfoPointerEventLayer.hitInfo.hit.collider) { Collider collider = raycastInfoPointerEventLayer.hitInfo.hit.collider; GameObject hitGameObject; if (CollidersManager.i.GetColliderInfo(collider, out ColliderInfo info)) { hitGameObject = info.entity.gameObject; } else { hitGameObject = collider.gameObject; } var events = hitGameObject.GetComponentsInChildren <IPointerEvent>(); for (var i = 0; i < events.Length; i++) { IPointerEvent e = events[i]; bool areSameEntity = AreSameEntity(e, info); switch (e.GetEventType()) { case PointerEventType.CLICK: if (areSameEntity) { e.Report(buttonId, ray, raycastInfoPointerEventLayer.hitInfo.hit); } break; case PointerEventType.DOWN: if (areSameEntity) { e.Report(buttonId, ray, raycastInfoPointerEventLayer.hitInfo.hit); } break; case PointerEventType.UP: if (areSameEntity) { pointerUpEvent = e; } else { pointerUpEvent = null; } break; } } lastPointerDownEventHitInfo = raycastInfoPointerEventLayer.hitInfo; } ReportGlobalPointerDownEvent(buttonId, useRaycast, raycastGlobalLayerHitInfo, raycastInfoGlobalLayer, worldState.currentSceneId); // Raycast for global pointer events (for each PE scene) List <string> currentPortableExperienceIds = WorldStateUtils.GetActivePortableExperienceIds(); for (int i = 0; i < currentPortableExperienceIds.Count; i++) { raycastInfoGlobalLayer = raycastHandler.Raycast(ray, charCamera.farClipPlane, globalLayer, worldState.loadedScenes[currentPortableExperienceIds[i]]); raycastGlobalLayerHitInfo = raycastInfoGlobalLayer.hitInfo; ReportGlobalPointerDownEvent(buttonId, useRaycast, raycastGlobalLayerHitInfo, raycastInfoGlobalLayer, currentPortableExperienceIds[i]); } }