/// <summary>Fires an event into the scene of the camera.</summary> internal void FireIntoScene(UIEvent e) { if (e == null) { return; } // Get coords relative to the element. These are non-standard convenience properties: float localX = e.localX; float localY = e.localY; // Flip Y because Unity is upside down relative to input coords: localY = ScreenInfo.ScreenY - 1 - localY; // Fire off an input event at that point: RaycastHit worldUIHit; if (Physics.Raycast(Camera.ScreenPointToRay(new Vector2(localX, localY)), out worldUIHit)) { // Did it hit a worldUI? WorldUI worldUI = WorldUI.Find(worldUIHit); if (worldUI == null) { // Nope! return; } // Resolve the hit into a -0.5 to +0.5 point: float x; float y; worldUI.ResolvePoint(worldUIHit, out x, out y); // Map it from a relative point to a 'real' one: Vector2 point = worldUI.RelativePoint(x, y); // Apply to x/y: x = point.x; y = point.y; // Pull an element from that worldUI: Element el = worldUI.document.elementFromPointOnScreen(x, y); if (el != null) { // Fire the event for that element: el.dispatchEvent(e); } } }
/// <summary>Finds an EventTarget from the given screen location. /// This fires a ray into the scene if the point isn't on the main UI and caches the hit in the given pointer. /// X and Y are updated with the document-relative point if it's on a WorldUI/ on the Unity UI.</summary> public static EventTarget TargetFromPoint(ref float x,ref float y,InputPointer pointer){ Element result=null; if(UI.document!=null){ // Test the main UI: result=UI.document.elementFromPointOnScreen(x,y); if(result!=null){ // Is it transparent or not html/body? if(AcceptsInput(result)){ // Great, we're done! if(pointer!=null){ pointer.LatestHitSuccess=false; } return result; } } } // Handle a Unity UI if needed. Vector2 point; #if HANDLE_UNITY_UI if(UnityUICaster!=null){ // Try hitting the Unity UI first. point=new Vector2(x,ScreenInfo.ScreenY-1-y); HtmlDocument panelDoc=MapToUIPanel(ref point); if(panelDoc!=null){ // Test for an element there: result=panelDoc.elementFromPointOnScreen(point.x,point.y); if(result!=null){ // Is it transparent? // We're still checking a UI so we might still pass "through" it. if(AcceptsInput(result)){ // Got a hit! Update x/y: x=point.x; y=point.y; if(pointer!=null){ pointer.LatestHitSuccess=false; } return result; } } } } #endif // Go after WorldUI's next. RaycastHit worldUIHit; Camera cam=CameraFor3DInput; if(cam==null){ // No camera! if(pointer!=null){ pointer.LatestHitSuccess=false; } return null; } Vector2 screenPoint = new Vector2(x,ScreenInfo.ScreenY-1-y); if(pointer == null){ // Cast into the scene now: Ray ray=cam.ScreenPointToRay(screenPoint); if(!Physics.Raycast(ray,out worldUIHit)){ // Nothing hit. return null; } }else if(!pointer.Raycast(out worldUIHit,cam,screenPoint)){ // Nothing hit. pointer.LatestHitSuccess=false; return null; } // Cache it: if(pointer!=null){ pointer.LatestHit=worldUIHit; pointer.LatestHitSuccess=true; } // Did it hit a worldUI? WorldUI worldUI=WorldUI.Find(worldUIHit); if(worldUI==null){ // Nope! Get the eventTarget for the gameObject: #if Enable3DInput return worldUIHit.transform.gameObject.getEventTarget(); #else return null; #endif } // Resolve the hit into a -0.5 to +0.5 point: // (we're ok to reuse x/y here): worldUI.ResolvePoint(worldUIHit,out x,out y); // Map it from a relative point to a 'real' one: point=worldUI.RelativePoint(x,y); // Apply to x/y: x=point.x; y=point.y; // Pull an element from that worldUI: return worldUI.document.elementFromPointOnScreen(x,y); }