/// <inheritdoc/> protected override void OnLoad() { Texture2D?.Dispose(); Texture2D = null; _monoGameContent?.Dispose(); _monoGameContent = null; // TODO: Asynchronously load textures. string fileName = Uri.LocalPath; string extension = Path.GetExtension(fileName); bool isXnb = string.Compare(extension, ".XNB", StringComparison.OrdinalIgnoreCase) == 0; if (isXnb) { try { string directoryName = Path.GetDirectoryName(fileName); _monoGameContent = _monoGameService.LoadXnb(directoryName, fileName, cacheResult: false); Texture2D = (Texture2D)_monoGameContent.Asset; } catch { Texture2D?.Dispose(); Texture2D = null; _monoGameContent?.Dispose(); _monoGameContent = null; throw; } } else { Texture2D = TextureHelper.LoadTexture(_graphicsService, Uri.LocalPath); } UpdateProperties(); }
private async Task LoadAsync(string fileName, bool recreateModelAndMaterialFiles) { Debug.Assert(_tempDirectoryHelper == null); Debug.Assert(_monoGameContent == null); Debug.Assert(ModelNode == null); Debug.Assert(Model == null); Debug.Assert(_assimpScene == null); Debug.Assert(State == ModelDocumentState.Loading); string extension = Path.GetExtension(fileName); IsXnb = string.Compare(extension, ".XNB", StringComparison.OrdinalIgnoreCase) == 0; // ----- Build XNB string directoryName; try { if (IsXnb) { // Get the folder that contains the XNB. directoryName = Path.GetDirectoryName(fileName); } else if (GameContentBuilder.IsSupportedModelFileExtension(extension)) { // Build the XNB and get the output folder. var buildResult = await Task.Run(() => BuildXnb(Editor.Services, Editor.ApplicationName, fileName, UseDigitalRuneGraphics, recreateModelAndMaterialFiles)); directoryName = buildResult.Item1; _tempDirectoryHelper = buildResult.Item2; } else { throw new EditorException(Invariant($"Unsupported 3D model file format (file extension \"{extension}\").")); } } catch (Exception) { if (IsDisposed) { // Document was closed during loading. Reset(); return; } State = ModelDocumentState.Error; UpdateProperties(); UpdateOutline(); // The GameContentBuilder logs to the output service. _outputService.Show(); throw; } if (IsDisposed) { // Document was closed during loading. Reset(); return; } Debug.Assert(directoryName != null); // ----- Load XNB try { // Get asset name for use with ContentManager. XNBs and unprocessed models // use different folder hierarchies. string assetFileName; if (IsXnb) { // Use absolute path. assetFileName = fileName; } else { // The asset is built relative to the root folder (e.g. "C:\"). The folder // hierarchy (from root to asset) is rebuilt in the temporary output folder. // Make file name relative to root. assetFileName = DRPath.GetRelativePath(Path.GetPathRoot(fileName), fileName); // Get absolute file name relative to temporary output folder. assetFileName = Path.Combine(directoryName, assetFileName); // Change extension. .fbx --> .xnb assetFileName = Path.ChangeExtension(assetFileName, "xnb"); } _monoGameContent = await Task.Run(() => _monoGameService.LoadXnb(directoryName, assetFileName, cacheResult: false)); if (_monoGameContent.Asset is ModelNode) { ModelNode = (ModelNode)_monoGameContent.Asset; UseDigitalRuneGraphics = true; HasAnimations = ModelNode.GetDescendants() .OfType <MeshNode>() .FirstOrDefault()? .Mesh? .Animations? .Count > 0; } else if (_monoGameContent.Asset is Model) { Model = (Model)_monoGameContent.Asset; UseDigitalRuneGraphics = false; HasAnimations = false; // Enable default lighting. var effects = Model.Meshes .SelectMany(m => m.Effects) .OfType <IEffectLights>(); foreach (var effect in effects) { effect.EnableDefaultLighting(); } } else { throw new EditorException("XNB does not contain ModelNode or Model."); } } catch (Exception exception) { Reset(); if (IsDisposed) { return; } State = ModelDocumentState.Error; Logger.Error(exception, "XNB could not be loaded."); // Let LoadAsync return and fail, then show message box. WindowsHelper.BeginInvokeOnUI(() => { var message = Invariant($"XNB could not be loaded:\n\n\"{exception.Message}\""); MessageBox.Show(message, Editor.ApplicationName, MessageBoxButton.OK, MessageBoxImage.Error); }); throw; } if (IsDisposed) { // Document was closed during loading. Reset(); return; } // ----- Load Assimp scene try { if (!IsXnb) { _assimpScene = await Task.Run(() => LoadAssimp(fileName)); } } catch (Exception exception) { Logger.Warn(exception, "Assimp could not read model file."); } if (IsDisposed) { // Document was closed during loading. Reset(); return; } State = ModelDocumentState.Loaded; // ----- Validate model ValidateModelNode(); // TODO: Validate MonoGame Model. // If there are errors or warnings, show Output and Errors window. // (Drawback: This steals focus from the document.) //if (_errors.Count > 0) //{ // _outputService?.Show(); // _errorService?.Show(); //} // ----- Update outline and properties UpdateOutline(); UpdateProperties(); }