/// <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)); }
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); } } } } }
/// <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 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); } }