/// <summary> /// Begins loading routines for the specified fileReference, which is expected to point to a valid model. /// This function takes a delegate which will correctly load the file pointed to by the FileReference, /// and another delegate which will create a correct <see cref="IRenderable"/> object from the resulting /// object. /// </summary> /// <param name="fileReference">A <see cref="FileReference"/> which points to the desired file.</param> /// <param name="referenceLoadingRoutine">A delegate which correctly loads the desired file, returning a generic type T.</param> /// <param name="createRenderableDelegate">A delegate which accepts a generic type T and returns a renderable object.</param> /// <param name="associatedControlPage">The control page which the file is associated with, that is, the one with relevant controls.</param> /// <typeparam name="T">The type of model to load.</typeparam> private void BeginLoadingFile <T>( FileReference fileReference, DataLoadingDelegates.LoadReferenceDelegate <T> referenceLoadingRoutine, DataLoadingDelegates.CreateRenderableDelegate <T> createRenderableDelegate, ControlPage associatedControlPage) { Log.Info($"Loading \"{fileReference.FilePath}\"."); this.StatusSpinner.Active = true; string modelName = fileReference.Filename; uint modelStatusMessageContextID = this.MainStatusBar.GetContextId($"itemLoad_{modelName}"); uint modelStatusMessageID = this.MainStatusBar.Push(modelStatusMessageContextID, $"Loading \"{modelName}\"..."); Task.Factory.StartNew(() => referenceLoadingRoutine(fileReference)) .ContinueWith(modelLoadTask => createRenderableDelegate(modelLoadTask.Result, fileReference), this.UIThreadScheduler) .ContinueWith(createRenderableTask => this.RenderingEngine.SetRenderTarget(createRenderableTask.Result), this.UIThreadScheduler) .ContinueWith ( result => { this.StatusSpinner.Active = false; this.MainStatusBar.Remove(modelStatusMessageContextID, modelStatusMessageID); EnableControlPage(associatedControlPage); }, this.UIThreadScheduler ); }
/// <summary> /// Loads and displays the specified fileReference in the UI, which is expected to point to a valid object. /// This function takes a delegate which will correctly load the file pointed to by the FileReference, /// and another delegate which will create a correct <see cref="IRenderable"/> object from the resulting /// object. /// </summary> /// <param name="gamePage">The game page that the renderable originated from.</param> /// <param name="fileReference">A <see cref="FileReference"/> which points to the desired file.</param> /// <param name="referenceLoadingRoutine">A delegate which correctly loads the desired file, returning a generic type T.</param> /// <param name="createRenderableDelegate">A delegate which accepts a generic type T and returns a renderable object.</param> /// <param name="associatedControlPage">The control page which the file is associated with, that is, the one with relevant controls.</param> /// <param name="ct">A cancellation token for this operation.</param> /// <typeparam name="T">The type of object to load.</typeparam> private async Task DisplayRenderableFile <T>( GamePage gamePage, FileReference fileReference, DataLoadingDelegates.LoadReferenceDelegate <T> referenceLoadingRoutine, DataLoadingDelegates.CreateRenderableDelegate <T> createRenderableDelegate, ControlPage associatedControlPage, CancellationToken ct) { if (fileReference == null) { throw new ArgumentNullException(nameof(fileReference)); } Log.Info($"Loading \"{fileReference.FilePath}\"."); this.StatusSpinner.Active = true; string modelName = fileReference.Filename; uint modelStatusMessageContextID = this.MainStatusBar.GetContextId($"itemLoad_{modelName}"); uint modelStatusMessageID = this.MainStatusBar.Push ( modelStatusMessageContextID, $"Loading \"{modelName}\"..." ); try { T item = await Task.Run ( () => referenceLoadingRoutine(fileReference), ct ); IRenderable renderable = await Task.Factory.StartNew ( () => createRenderableDelegate(item, fileReference, gamePage.Version), ct, TaskCreationOptions.None, this.UiThreadScheduler ); if (renderable != null) { ct.ThrowIfCancellationRequested(); // Replace the renderable on the UI thread await Task.Factory.StartNew ( () => this.RenderingEngine.SetRenderTarget(renderable), ct, TaskCreationOptions.None, this.UiThreadScheduler ); EnableControlPage(associatedControlPage); } } catch (OperationCanceledException) { Log.Info($"Cancelled loading of {fileReference.Filename}"); } finally { this.StatusSpinner.Active = false; this.MainStatusBar.Remove(modelStatusMessageContextID, modelStatusMessageID); } }