public AssetContentValueChangeOperation(IAssetNode node, ContentChangeType changeType, NodeIndex index, object oldValue, object newValue, OverrideType previousOverride, OverrideType newOverride, ItemId itemId, IEnumerable <IDirtiable> dirtiables)
     : base(node, changeType, index, oldValue, newValue, dirtiables)
 {
     this.previousOverride = previousOverride;
     this.itemId           = itemId;
     this.newOverride      = newOverride;
 }
        public void ReconcileWithBase(IAssetNode rootNode)
        {
            var visitor = CreateReconcilierVisitor();

            visitor.Visiting += (node, path) => ReconcileWithBaseNode(node as AssetMemberNode);
            visitor.Visit(rootNode);
        }
        /// <summary>
        /// Resets the overrides attached to the given node and its descendants, recursively.
        /// </summary>
        /// <param name="rootNode">The node for which to reset overrides.</param>
        /// <param name="indexToReset">The index of the override to reset in this node, if relevant.</param>
        public void ResetOverride(IAssetNode rootNode, Index indexToReset)
        {
            var visitor = CreateReconcilierVisitor();

            visitor.SkipRootNode = true;
            visitor.Visiting    += (node, path) =>
            {
                var childNode = node as AssetMemberNode;
                if (childNode == null)
                {
                    return;
                }

                childNode.OverrideContent(false);
                foreach (var overrideItem in childNode.GetOverriddenItemIndices())
                {
                    childNode.OverrideItem(false, overrideItem);
                }
                foreach (var overrideKey in childNode.GetOverriddenKeyIndices())
                {
                    childNode.OverrideKey(false, overrideKey);
                }
            };
            visitor.Visit(rootNode);

            ReconcileWithBase(rootNode);
        }
Esempio n. 4
0
        protected virtual object CloneObjectForGameSide(object assetSideObject, IAssetNode assetNode, IGraphNode gameSideNode)
        {
            // Null references, they will be handled by the editor asset loader
            var gameSideValue = AssetCloner.Clone(assetSideObject, AssetClonerFlags.ReferenceAsNull);

            return(gameSideValue);
        }
        /// <inheritdoc/>
        protected override bool CanUpdate(IAssetNode node, ContentChangeType changeType, NodeIndex index, object value)
        {
            // Check if we are in the component collection of an entity (where we actually add new components)
            if (IsComponentForComponentCollection(node, value) && changeType == ContentChangeType.CollectionAdd)
            {
                var componentType       = value.GetType();
                var attributes          = EntityComponentAttributes.Get(componentType);
                var onlySingleComponent = !attributes.AllowMultipleComponents;
                var collection          = (EntityComponentCollection)node.Retrieve();

                foreach (var existingItem in collection)
                {
                    if (ReferenceEquals(existingItem, value))
                    {
                        return(false);
                    }

                    if (onlySingleComponent && componentType == existingItem.GetType())
                    {
                        return(false);
                    }
                }
            }

            return(base.CanUpdate(node, changeType, index, value));
        }
        protected override object CloneObjectForGameSide(object assetSideObject, IAssetNode assetNode, IGraphNode gameSideNode)
        {
            // TODO: this is very similar to what AssetPropertyGraph.CloneValueFromBase is doing, except that the base cloner is different. Try to factorize!
            if (gameSideNode.Type == typeof(EntityComponentCollection) && assetSideObject is TransformComponent)
            {
                // We never clone TransformComponent, we cannot replace them. Instead, return the existing one.
                var transformComponent = (TransformComponent)gameSideNode.Retrieve(new NodeIndex(0));
                // We still reset the Entity to null to make sure it works nicely with reconcilation, etc.
                transformComponent.Entity = null;
                return(transformComponent);
            }

            var gameSideValue = base.CloneObjectForGameSide(assetSideObject, assetNode, gameSideNode);

            // Important: In case of component, because of the Entitycomponent serializer is serializing the entity (with all its components)
            // We are clearing the entity of the component, so that this object can be added to the game side part.
            var entityComponent = gameSideValue as EntityComponent;

            if (entityComponent != null)
            {
                entityComponent.Entity = null;
            }

            return(gameSideValue);
        }
Esempio n. 7
0
        public void RegisterBaseToDerived(IAssetNode baseNode, IAssetNode derivedNode)
        {
            var ownerPart  = derivedNode.GetContent(NodesToOwnerPartVisitor.OwnerPartContentName);
            var instanceId = (ownerPart?.Retrieve() as IAssetPartDesign)?.Base?.InstanceId ?? Guid.Empty;
            AssetBaseToDerivedRegistry derivedRegistry;

            if (!baseToInstances.TryGetValue(instanceId, out derivedRegistry))
            {
                baseToInstances[instanceId] = derivedRegistry = new AssetBaseToDerivedRegistry(propertyGraph);
            }

            derivedRegistry.RegisterBaseToDerived(baseNode, derivedNode);
        }
Esempio n. 8
0
        private void RelinkToOwnerPart([NotNull] IAssetNode node, object newValue)
        {
            var partDesign = (TAssetPartDesign)node.GetContent(NodesToOwnerPartVisitor.OwnerPartContentName)?.Retrieve();

            if (partDesign != null)
            {
                // A property of a part has changed
                LinkToOwnerPart(node, partDesign);
            }
            else if (node.Type == typeof(AssetPartCollection <TAssetPartDesign, TAssetPart>) && newValue is TAssetPartDesign)
            {
                // A new part has been added
                partDesign = (TAssetPartDesign)newValue;
                LinkToOwnerPart(Container.NodeContainer.GetNode(partDesign.Part), partDesign);
            }
        }
Esempio n. 9
0
        public IIdentifiable ResolveFromBase(object baseObjectReference, IAssetNode derivedReferencerNode)
        {
            if (derivedReferencerNode == null)
            {
                throw new ArgumentNullException(nameof(derivedReferencerNode));
            }
            if (baseObjectReference == null)
            {
                return(null);
            }

            var        baseNode = (IAssetNode)propertyGraph.Container.NodeContainer.GetNode(baseObjectReference);
            IAssetNode derivedNode;

            baseToDerived.TryGetValue(baseNode, out derivedNode);
            return(derivedNode?.Retrieve() as IIdentifiable);
        }
Esempio n. 10
0
        public IIdentifiable ResolveFromBase(object baseObjectReference, IAssetNode derivedReferencerNode)
        {
            if (derivedReferencerNode == null)
            {
                throw new ArgumentNullException(nameof(derivedReferencerNode));
            }
            var ownerPart  = derivedReferencerNode.GetContent(NodesToOwnerPartVisitor.OwnerPartContentName);
            var instanceId = (ownerPart?.Retrieve() as IAssetPartDesign)?.Base?.InstanceId ?? Guid.Empty;
            AssetBaseToDerivedRegistry derivedRegistry;

            if (!baseToInstances.TryGetValue(instanceId, out derivedRegistry))
            {
                return(null);
            }

            return(derivedRegistry.ResolveFromBase(baseObjectReference, derivedReferencerNode));
        }
Esempio n. 11
0
        public void RegisterBaseToDerived(IAssetNode baseNode, IAssetNode derivedNode)
        {
            var baseValue = baseNode?.Retrieve();

            if (baseValue == null)
            {
                return;
            }

            if (baseValue is IIdentifiable)
            {
                baseToDerived[baseNode] = derivedNode;
                var baseMemberNode = baseNode as IAssetMemberNode;
                if (baseMemberNode?.Target != null && !propertyGraph.Definition.IsMemberTargetObjectReference(baseMemberNode, baseValue))
                {
                    baseToDerived[baseMemberNode.Target] = ((IAssetMemberNode)derivedNode).Target;
                }
            }

            var derivedObjectNode = derivedNode as IObjectNode;
            var baseObjectNode    = baseNode as IObjectNode;

            if (derivedObjectNode?.ItemReferences != null && baseObjectNode?.ItemReferences != null)
            {
                foreach (var reference in derivedObjectNode.ItemReferences)
                {
                    var target = propertyGraph.baseLinker.FindTargetReference(derivedNode, baseNode, reference);
                    if (target == null)
                    {
                        continue;
                    }

                    baseValue = target.TargetNode?.Retrieve();
                    if (!propertyGraph.Definition.IsTargetItemObjectReference(baseObjectNode, target.Index, baseNode.Retrieve(target.Index)))
                    {
                        if (baseValue is IIdentifiable)
                        {
                            baseToDerived[(IAssetNode)target.TargetNode] = (IAssetNode)derivedObjectNode.IndexedTarget(reference.Index);
                        }
                    }
                }
            }
        }
Esempio n. 12
0
        protected internal override object CloneValueFromBase(object value, IAssetNode node)
        {
            var part = value as TAssetPart;

            // Part reference
            if (part != null)
            {
                // We need to find out for which entity we are cloning this (other) entity
                var owner = (TAssetPartDesign)node?.GetContent(NodesToOwnerPartVisitor.OwnerPartContentName).Retrieve();
                if (owner != null)
                {
                    // Then instead of creating a clone, we just return the corresponding part in this asset (in term of base and base instance)
                    var partInDerived = AssetHierarchy.Hierarchy.Parts.FirstOrDefault(x => x.Base?.BasePartId == part.Id && x.Base?.InstanceId == owner.Base?.InstanceId);
                    return(partInDerived?.Part);
                }
            }

            var result = base.CloneValueFromBase(value, node);

            return(result);
        }
        /// <inheritdoc/>
        protected override object CloneValueFromBase(object value, IAssetNode node)
        {
            // TODO: check CloneObjectForGameSide if modifying this method, the logic should be factorized at some point.
            if (IsComponentForComponentCollection(node, value) && value is TransformComponent)
            {
                // We never clone TransformComponent, we cannot replace them. Instead, return the existing one.
                var transformComponent = (TransformComponent)node.Retrieve(new Index(0));
                // We still reset the Entity to null to make sure it works nicely with reconcilation, etc.
                transformComponent.Entity = null;
                return transformComponent;
            }

            var clone = base.CloneValueFromBase(value, node);
            var component = clone as EntityComponent;
            if (component != null)
            {
                // Components need their Entity to be cleared first because subsequent actions will try to restore it and safeguards might throw if it's not null beforehand
                component.Entity = null;
            }
            return clone;
        }
        public static void ApplyOverrides(IAssetNode rootNode, IDictionary <YamlAssetPath, OverrideType> overrides)
        {
            if (rootNode == null)
            {
                throw new ArgumentNullException(nameof(rootNode));
            }

            if (overrides == null)
            {
                return;
            }

            foreach (var overrideInfo in overrides)
            {
                Index index;
                bool  overrideOnKey;
                var   node = ResolveObjectPath(rootNode, overrideInfo.Key, out index, out overrideOnKey) as AssetMemberNode;
                // The node is unreachable, skip this override.
                if (node == null)
                {
                    continue;
                }

                if (index == Index.Empty)
                {
                    node.SetContentOverride(overrideInfo.Value);
                }
                else if (!overrideOnKey)
                {
                    node.SetItemOverride(overrideInfo.Value, index);
                }
                else
                {
                    node.SetKeyOverride(overrideInfo.Value, index);
                }
            }
        }
Esempio n. 15
0
 public void Visit([NotNull] IAssetNode node, NodeIndex index)
 {
     if (index == NodeIndex.Empty)
     {
         // Normal case, no index
         Visit(node);
     }
     else if (node.IsReference)
     {
         // We have an index, and our collection is a collection of reference types, then start visit from the target item
         var target = ((IObjectNode)node).IndexedTarget(index);
         if (target != null)
         {
             Visit(target);
         }
     }
     else if (AssetRegistry.IsContentType(node.Descriptor.GetInnerCollectionType()))
     {
         // We have an index, and our collection is directly a collection of content type. Let's just collect the corresponding item.
         var gameContent = node.GetContent("Game");
         var id          = AttachedReferenceManager.GetAttachedReference(node.Retrieve(index))?.Id ?? AssetId.Empty;
         CollectContentReference(id, gameContent, index);
     }
 }
Esempio n. 16
0
 /// <inheritdoc/>
 public override void RefreshBase(IAssetNode node, IAssetNode baseNode)
 {
     base.RefreshBase(node, baseNode);
     UpdateAssetPartBases();
 }
 protected internal virtual object CloneValueFromBase(object value, IAssetNode node)
 {
     return(CloneFromBase(value));
 }
 // TODO: this method is should be called in every scenario of ReconcileWithBase, it is not the case yet.
 protected virtual bool CanUpdate(IAssetNode node, ContentChangeType changeType, Index index, object value)
 {
     return(true);
 }
 // TODO: turn private
 public void LinkToBase(IAssetNode sourceRootNode, IAssetNode targetRootNode)
 {
     baseLinker.ShouldVisit = (member, node) => (node == sourceRootNode || !baseLinkedNodes.ContainsKey((IAssetNode)node)) && ShouldListenToTargetNode(member, node);
     baseLinker.LinkGraph(sourceRootNode, targetRootNode);
 }
 public static OverrideType GetKeyOverride(this IAssetNode node, Index index)
 {
     return(((IAssetObjectNodeInternal)node).GetKeyOverride(index));
 }
        public static IAssetNode ResolveObjectPath([NotNull] IAssetNode rootNode, [NotNull] YamlAssetPath path, out Index index, out bool overrideOnKey)
        {
            var currentNode = rootNode;

            index         = Index.Empty;
            overrideOnKey = false;
            for (var i = 0; i < path.Items.Count; i++)
            {
                var item = path.Items[i];
                switch (item.Type)
                {
                case YamlAssetPath.ItemType.Member:
                    index         = Index.Empty;
                    overrideOnKey = false;
                    if (currentNode.IsReference)
                    {
                        var memberNode = currentNode as IMemberNode;
                        if (memberNode == null)
                        {
                            throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
                        }
                        currentNode = (IAssetNode)memberNode.Target;
                    }
                    var objectNode = currentNode as IObjectNode;
                    if (objectNode == null)
                    {
                        throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                    }
                    var name = item.AsMember();
                    currentNode = (IAssetNode)objectNode.TryGetChild(name);
                    break;

                case YamlAssetPath.ItemType.Index:
                    index         = new Index(item.Value);
                    overrideOnKey = true;
                    if (currentNode.IsReference && i < path.Items.Count - 1)
                    {
                        currentNode = (IAssetNode)currentNode.IndexedTarget(new Index(item.Value));
                    }
                    break;

                case YamlAssetPath.ItemType.ItemId:
                    var ids = CollectionItemIdHelper.GetCollectionItemIds(currentNode.Retrieve());
                    var key = ids.GetKey(item.AsItemId());
                    index         = new Index(key);
                    overrideOnKey = false;
                    if (currentNode.IsReference && i < path.Items.Count - 1)
                    {
                        currentNode = (IAssetNode)currentNode.IndexedTarget(new Index(key));
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // Something wrong happen, the node is unreachable.
                if (currentNode == null)
                {
                    return(null);
                }
            }

            return(currentNode);
        }