/// <summary> /// Waits until the given object is visible. /// </summary> /// <param name="sceneObjects">The scene objects to check for.</param> /// <param name="viewInfo">The view on which to check for visibility.</param> /// <param name="cancelToken">The cancellation token.</param> public Task WaitUntilVisibleAsync(IEnumerable <SceneObject> sceneObjects, ViewInformation viewInfo, CancellationToken cancelToken = default) { sceneObjects.EnsureNotNull(nameof(sceneObjects)); viewInfo.EnsureNotNull(nameof(viewInfo)); var taskComplSource = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); // Define the poll action (polling is done inside scene update void PollAction() { if (this.AreAllObjectsVisible(sceneObjects, viewInfo)) { taskComplSource.SetResult(null); } else if (cancelToken.IsCancellationRequested) { taskComplSource.SetCanceled(); } else { _asyncInvokesBeforeUpdate.Enqueue(PollAction); } } // Register first call of the polling action _asyncInvokesBeforeUpdate.Enqueue(PollAction); return(taskComplSource.Task); }
/// <summary> /// Registers the given view on this scene object. /// This method is meant to be called by RenderLoop class. /// </summary> /// <param name="viewInformation">The view to register.</param> internal void RegisterView(ViewInformation viewInformation) { viewInformation.EnsureNotNull(nameof(viewInformation)); var isFirstView = _registeredViews.Count == 0; this.InitializeResourceDictionaries(); // Register device on this scene if not done before // -> This registration is forever, no deregister is made! var givenDevice = viewInformation.Device; var resourceDictionary = _registeredResourceDicts[givenDevice !.DeviceIndex];
/// <summary> /// Ares all given scene objects visible currently? /// </summary> /// <param name="sceneObjects">The scene objects.</param> /// <param name="viewInfo">The view information.</param> public bool AreAllObjectsVisible(IEnumerable <SceneObject> sceneObjects, ViewInformation viewInfo) { sceneObjects.EnsureNotNull(nameof(sceneObjects)); viewInfo.EnsureNotNull(nameof(viewInfo)); foreach (var actObject in sceneObjects) { if (!actObject.IsVisible(viewInfo)) { return(false); } } return(true); }
/// <summary> /// Picks an object in 3D space. /// </summary> internal List <SceneObject> Pick(Vector3 rayStart, Vector3 rayDirection, ViewInformation viewInformation, PickingOptions pickingOptions) { rayDirection.EnsureNormalized(nameof(rayDirection)); viewInformation.EnsureNotNull(nameof(viewInformation)); pickingOptions.EnsureNotNull(nameof(pickingOptions)); // Query for all objects below the cursor var pickedObjects = new List <Tuple <SceneObject, float> >(); foreach (var actLayer in _sceneLayers) { foreach (var actObject in actLayer.Objects) { if (!actObject.IsVisible(viewInformation)) { continue; } if (!actObject.IsPickingTestVisible) { continue; } var actDistance = actObject.Pick(rayStart, rayDirection, viewInformation, pickingOptions); if (!float.IsNaN(actDistance)) { pickedObjects.Add(Tuple.Create(actObject, actDistance)); } } } // Return all picked object in correct order return(pickedObjects .OrderBy(actObject => actObject.Item2) .Convert(actObject => actObject.Item1) .ToList()); }