Exemplo n.º 1
0
        /// <inheritdoc/>
        /// <remarks>
        /// Derived class should override this method, implement specific cleanup and then call the base implementation.
        /// </remarks>
        public virtual void Destroy()
        {
            EnsureNotDestroyed();
            if (IsDestroying)
            {
                return;
            }

            Loader.Dispose();
            EditorDebugTools.UnregisterDebugPage(debugPage);
            UnregisterFromDragDropEvents();
            GameForm?.Host?.Dispose();
            IsDestroying = true;

            // Clean after everything
            PostTask(async x =>
            {
                if (serviceRegistry != null)
                {
                    await serviceRegistry.DisposeAsync();
                }
                Game.Exit();
                GameForm?.Dispose();
            }, int.MaxValue)
            // Ensure the properties are correctly set, even in case of a failure (default continuation)
            .ContinueWith(t =>
            {
                Asset.Dispatcher.Invoke(() =>
                {
                    IsDestroyed  = true;
                    IsDestroying = false;
                });
            });
            GameSideNodeContainer.Clear();
        }
Exemplo n.º 2
0
        /// <inheritdoc />
        public override Task RemovePart([NotNull] EntityHierarchyElementViewModel parent, Entity assetSidePart)
        {
            EnsureAssetAccess();

            return(InvokeAsync(() =>
            {
                Logger.Debug($"Removing entity {assetSidePart.Id} from game-side scene");
                var partId = new AbsoluteId(AssetId.Empty, assetSidePart.Id);
                var part = (Entity)FindPart(partId);
                if (part == null)
                {
                    throw new InvalidOperationException($"The given {nameof(assetSidePart.Id)} does not correspond to any existing part.");
                }

                if (parent is PrefabRootViewModel)
                {
                    Game.UnloadEntity(part);
                }
                else
                {
                    var parentEntity = (Entity)FindPart(parent.Id);
                    if (parentEntity == null)
                    {
                        throw new InvalidOperationException($"The given {nameof(parent.Id)} does not correspond to any existing part.");
                    }

                    var i = parentEntity.Transform.Children.IndexOf(part.Transform);
                    GameSideNodeContainer.GetNode(parentEntity.Transform.Children).Remove(part.Transform, new NodeIndex(i));
                }
            }));
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public override Task AddPart([NotNull] EntityHierarchyElementViewModel parent, Entity assetSidePart)
        {
            EnsureAssetAccess();

            var gameSidePart = ClonePartForGameSide(parent.Asset.Asset, assetSidePart);

            return(InvokeAsync(() =>
            {
                Logger.Debug($"Adding entity {assetSidePart.Id} to game-side scene");
                if (parent is PrefabRootViewModel)
                {
                    Game.LoadEntity(gameSidePart);
                }
                else
                {
                    var parentEntity = (Entity)FindPart(parent.Id);
                    if (parentEntity == null)
                    {
                        throw new InvalidOperationException($"The given {nameof(parent.Id)} does not correspond to any existing part.");
                    }

                    GameSideNodeContainer.GetNode(parentEntity.Transform.Children).Add(gameSidePart.Transform);
                }
            }));
        }
Exemplo n.º 4
0
        /// <inheritdoc/>
        protected override Dictionary <Guid, IIdentifiable> CollectIdentifiableObjects()
        {
            var allElements         = RootElements.Values.BreadthFirst(x => x.VisualChildren);
            var definition          = AssetQuantumRegistry.GetDefinition(Asset.Asset.GetType());
            var identifiableObjects = new Dictionary <Guid, IIdentifiable>();

            foreach (var entityNode in allElements.Select(x => GameSideNodeContainer.GetOrCreateNode(x)))
            {
                foreach (var identifiable in IdentifiableObjectCollector.Collect(definition, entityNode))
                {
                    identifiableObjects.Add(identifiable.Key, identifiable.Value);
                }
            }
            return(identifiableObjects);
        }
        /// <inheritdoc/>
        protected override Dictionary <Guid, IIdentifiable> CollectIdentifiableObjects()
        {
            var allEntities         = Game.ContentScene.Yield().BreadthFirst(x => x.Children).SelectMany(x => x.Entities).BreadthFirst(x => x.Transform.Children.Select(y => y.Entity));
            var definition          = AssetQuantumRegistry.GetDefinition(Asset.Asset.GetType());
            var identifiableObjects = new Dictionary <Guid, IIdentifiable>();

            foreach (var entityNode in allEntities.Select(x => GameSideNodeContainer.GetOrCreateNode(x)))
            {
                foreach (var identifiable in IdentifiableObjectCollector.Collect(definition, entityNode))
                {
                    identifiableObjects.Add(identifiable.Key, identifiable.Value);
                }
            }
            return(identifiableObjects);
        }
Exemplo n.º 6
0
        /// <inheritdoc />
        public override Task RemovePart([NotNull] UIHierarchyItemViewModel parent, UIElement assetSidePart)
        {
            EnsureAssetAccess();

            return(InvokeAsync(() =>
            {
                Logger.Debug($"Removing element {assetSidePart.Id} from game-side scene");
                var partId = new AbsoluteId(AssetId.Empty, assetSidePart.Id);
                var part = (UIElement)FindPart(partId);
                if (part == null)
                {
                    throw new InvalidOperationException($"The given {nameof(assetSidePart.Id)} does not correspond to any existing part.");
                }

                var parentId = (parent as UIElementViewModel)?.Id;
                if (parentId == null)
                {
                    RootElements.Remove(assetSidePart.Id);
                }
                else
                {
                    var parentElement = (UIElement)FindPart(parentId.Value);
                    if (parentElement == null)
                    {
                        throw new InvalidOperationException($"The given {nameof(parentId)} does not correspond to any existing part.");
                    }

                    var panel = parentElement as Panel;
                    var contentControl = parentElement as ContentControl;
                    if (panel != null)
                    {
                        var i = panel.Children.IndexOf(part);
                        GameSideNodeContainer.GetNode(panel.Children).Remove(part, new NodeIndex(i));
                    }
                    else if (contentControl != null)
                    {
                        if (contentControl.Content != null)
                        {
                            throw new InvalidOperationException($"The control corresponding to the given {nameof(parentId)} is a ContentControl that already has a Content.");
                        }
                        GameSideNodeContainer.GetNode(contentControl)[nameof(contentControl.Content)].Update(null);
                    }
                }
            }));
        }
Exemplo n.º 7
0
        /// <inheritdoc />
        public override Task AddPart([NotNull] UIHierarchyItemViewModel parent, UIElement assetSidePart)
        {
            EnsureAssetAccess();

            var gameSidePart = ClonePartForGameSide(parent.Asset.Asset, assetSidePart);

            return(InvokeAsync(() =>
            {
                Logger.Debug($"Adding element {assetSidePart.Id} to game-side scene");

                var parentId = (parent as UIElementViewModel)?.Id;
                if (parentId == null)
                {
                    RootElements[assetSidePart.Id] = gameSidePart;
                }
                else
                {
                    var parentElement = (UIElement)FindPart(parentId.Value);
                    if (parentElement == null)
                    {
                        throw new InvalidOperationException($"The given {nameof(parentId)} does not correspond to any existing part.");
                    }

                    var panel = parentElement as Panel;
                    var contentControl = parentElement as ContentControl;
                    if (panel != null)
                    {
                        GameSideNodeContainer.GetNode(panel.Children).Add(gameSidePart);
                    }
                    else if (contentControl != null)
                    {
                        if (contentControl.Content != null)
                        {
                            throw new InvalidOperationException($"The control corresponding to the given {nameof(parentId)} is a ContentControl that already has a Content.");
                        }
                        GameSideNodeContainer.GetNode(contentControl)[nameof(contentControl.Content)].Update(gameSidePart);
                    }
                }
            }));
        }
Exemplo n.º 8
0
        protected IEnumerable <TAssetPart> ClonePartsForGameSide([NotNull] AssetCompositeHierarchy <TAssetPartDesign, TAssetPart> asset, [NotNull] IEnumerable <TAssetPart> parts)
        {
            var flags           = SubHierarchyCloneFlags.RemoveOverrides;
            var sourceContainer = Asset.PropertyGraph.Container.NodeContainer;
            var targetContainer = GameSideNodeContainer;
            var clone           = AssetCompositeHierarchyPropertyGraph <TAssetPartDesign, TAssetPart> .CloneSubHierarchies(sourceContainer, targetContainer, asset, parts.Select(p => p.Id), flags, out _);

            // Collect external references after cloning, we need to fix them up!
            var rootNode             = GameSideNodeContainer.GetOrCreateNode(clone);
            var definition           = AssetQuantumRegistry.GetDefinition(asset.GetType());
            var unresolvedReferences = ExternalReferenceCollector.GetExternalReferenceAccessors(definition, rootNode);

            // Retrieve all available game-side identifiable objects, so we can try to resolve external references with items from this collection.
            var identifiableObjects = CollectIdentifiableObjects();

            foreach (var reference in unresolvedReferences)
            {
                if (identifiableObjects.TryGetValue(reference.Key.Id, out var realObject))
                {
                    // Target object found, let's update the reference with the real game-side object.
                    foreach (var accessor in reference.Value)
                    {
                        accessor.UpdateValue(realObject);
                    }
                }
                else
                {
                    // Target object not found, let's clear the reference since the currently set object could be asset-side, or a temporary proxy, etc.
                    foreach (var accessor in reference.Value)
                    {
                        accessor.UpdateValue(null);
                    }
                }
            }
            return(clone.RootParts);
        }