Esempio n. 1
0
        private void ExpandAll(Expander selectedExpander)
        {
            _isManualCollapseOrExpand = true;

            try
            {
                // Expand all expanders.
                foreach (var expander in _listBox.GetVisualDescendants().OfType <Expander>())
                {
                    expander.IsExpanded = true;

                    // When an expander is expanded, only its properties should get focus.
                    expander.Focusable = false;
                }

                // Move focus to first property of the selected expander.
                var listBoxItem = selectedExpander?.GetVisualDescendants().OfType <ListBoxItem>().FirstOrDefault();
                if (listBoxItem != null)
                {
                    WindowsHelper.BeginInvokeOnUI(() =>
                    {
                        listBoxItem.Focus();
                        listBoxItem.BringIntoView();
                    });
                }
            }
            finally
            {
                _isManualCollapseOrExpand = false;
            }
        }
Esempio n. 2
0
        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();
        }