//------------------------------------------------------------------------/ // Routines //------------------------------------------------------------------------/ bool ScanForInteractables() { Collider[] castResults = Physics.OverlapSphere(this.scanPosition, this.range); var interactions = new List <InteractionQuery>(); bool foundInteractions = false; // The scan event that will be sent var scanEvent = new DetectionEvent(); scanEvent.sensor = this; if (castResults != null) { foreach (var hit in castResults) { // Check whether it can be detected, depending on the scanmode bool detected = Detect(hit.transform); if (!detected) { continue; } // Check whether it is an interactable var interactable = hit.transform.gameObject.GetComponent <Interactable>(); if (interactable == null) { continue; } // Scan it interactable.gameObject.Dispatch <DetectionEvent>(scanEvent); // Create a query object, filling with scanned data var query = new InteractionQuery(); query.data = scanEvent.scanData; query.distance = Vector3.Distance(root.position, hit.transform.position); query.interactable = interactable; // Now store the interaction interactions.Add(query); // Note that we have scanned something foundInteractions = true; } } // Sort the interactions by the closest one interactions.Sort((a, b) => a.distance.CompareTo(b.distance)); // Save the current interactions interactivesInRange = interactions.ToArray(); // Now inform the agent of the current results var scanResult = new DetectionResultEvent(); scanResult.hasFoundInteractions = foundInteractions; this.gameObject.Dispatch <DetectionResultEvent>(scanResult); return(foundInteractions); }
private void HandleQuery(InteractionQuery query) { // NOTE: this method is called from a worker thread, so it must not access any game objects. try { // The mechanism that we use for getting the window ID assumes that the game window is on top // when the scripts start running. It usually does the right thing, but not always. // So adjust if necessary. var queryWindowIdEnum = query.WindowIds.GetEnumerator(); if (queryWindowIdEnum.MoveNext()) { if (queryWindowIdEnum.Current != ScreenHelpers.Instance.GameWindowId) { print(string.Format("Window ID mismatch: queried for {0}, expected {1}. Adjusting.", queryWindowIdEnum.Current, ScreenHelpers.Instance.GameWindowId)); ScreenHelpers.Instance.GameWindowId = queryWindowIdEnum.Current; _gameWindowPosition = new Vector2(float.NaN, float.NaN); } } if (float.IsNaN(_gameWindowPosition.x)) { // We don't have a valid game window position, so we cannot respond to any queries at this time. return; } // Get query bounds and map them to GUI coordinates. double boundsX, boundsY, boundsWidth, boundsHeight; query.Bounds.TryGetRectangularData(out boundsX, out boundsY, out boundsWidth, out boundsHeight); var queryRectInGuiCoordinates = new Rect( (float)(boundsX - _gameWindowPosition.x), (float)(boundsY - _gameWindowPosition.y), (float)boundsWidth, (float)boundsHeight); // Make a copy of the collection of interactors to avoid race conditions. List<EyeXInteractor> interactorsCopy; lock (_lock) { interactorsCopy = new List<EyeXInteractor>(_interactors.Values); } // Create the snapshot and add the interactors that intersect with the query bounds. var snapshot = _context.CreateSnapshotWithQueryBounds(query); snapshot.AddWindowId(ScreenHelpers.Instance.GameWindowId); foreach (var interactor in interactorsCopy) { if (interactor.IntersectsWith(queryRectInGuiCoordinates)) { interactor.AddToSnapshot(snapshot, ScreenHelpers.Instance.GameWindowId, _gameWindowPosition); } } // Commit the snapshot. snapshot.CommitAsync(null); } catch (InteractionApiException ex) { print("EyeX query handler failed: " + ex.Message); } }
/// <summary> /// Handles a query from the EyeX Engine. /// Note that this method is called from a worker thread, so it may not access any WPF Window objects. /// </summary> /// <param name="query">Query.</param> private void HandleQuery(InteractionQuery query) { var queryBounds = query.Bounds; double x, y, w, h; if (queryBounds.TryGetRectangularData(out x, out y, out w, out h)) { // marshal the query to the UI thread, where WPF objects may be accessed. System.Windows.Rect r = new System.Windows.Rect((int)x, (int)y, (int)w, (int)h); this.Dispatcher.BeginInvoke(new Action<System.Windows.Rect>(HandleQueryOnUiThread), r); } }