protected override object ResolveReference(object partReference) { var entityComponentReference = partReference as EntityComponent; if (entityComponentReference != null) { var containingEntity = entityComponentReference.Entity; if (containingEntity == null) { throw new InvalidOperationException("Found a reference to a component which doesn't have any entity"); } var realEntity = (Entity)base.ResolveReference(containingEntity); if (realEntity == null) { return(null); } var componentId = IdentifiableHelper.GetId(entityComponentReference); var realComponent = realEntity.Components.FirstOrDefault(c => IdentifiableHelper.GetId(c) == componentId); return(realComponent); } return(base.ResolveReference(partReference)); }
private static void FixupEntityReferences(object rootToVisit, EntityHierarchyData entityHierarchy) { var entityAnalysisResult = Visit(rootToVisit); // Reverse the list, so that we can still properly update everything // (i.e. if we have a[0], a[1], a[1].Test, we have to do it from back to front to be valid at each step) entityAnalysisResult.EntityReferences.Reverse(); // Updates Entity/EntityComponent references foreach (var entityLink in entityAnalysisResult.EntityReferences) { object obj = null; if (entityLink.EntityComponent != null) { var containingEntity = entityLink.EntityComponent.Entity; if (containingEntity == null) { throw new InvalidOperationException("Found a reference to a component which doesn't have any entity"); } EntityDesign realEntity; if (entityHierarchy.Entities.TryGetValue(containingEntity.Id, out realEntity)) { var componentId = IdentifiableHelper.GetId(entityLink.EntityComponent); obj = realEntity.Entity.Components.FirstOrDefault(c => IdentifiableHelper.GetId(c) == componentId); if (obj == entityLink.EntityComponent) { continue; } } } else { EntityDesign realEntity; if (entityHierarchy.Entities.TryGetValue(entityLink.Entity.Id, out realEntity)) { obj = realEntity.Entity; // If we already have the proper item, let's skip if (obj == entityLink.Entity) { continue; } } } if (obj != null) { // We could find the referenced item, let's use it entityLink.Path.Apply(rootToVisit, MemberPathAction.ValueSet, obj); } else { // Item could not be found, let's null it entityLink.Path.Apply(rootToVisit, MemberPathAction.ValueClear, null); } } }
public EntityComponentReference(EntityComponent entityComponent) { this.Entity = new EntityReference() { Id = entityComponent.Entity.Id }; this.Id = IdentifiableHelper.GetId(entityComponent); this.Value = entityComponent; }
public void FillFromPart(object assetPart) { var component = (EntityComponent)assetPart; Entity = new EntityReference { Id = component.Entity.Id }; Id = IdentifiableHelper.GetId(component); }
public override string ConvertTo(ref ObjectContext objectContext) { var attachedReference = AttachedReferenceManager.GetAttachedReference(objectContext.Instance); if (attachedReference == null) { throw new YamlException($"Unable to extract asset reference from object [{objectContext.Instance}]"); } var referenceId = IdentifiableHelper.GetId(objectContext.Instance); return($"{referenceId}/{attachedReference.Id}:{attachedReference.Url}"); }
private void DiffValue(Diff3Node diff3, ref NodeDescription baseNodeDesc, ref NodeDescription asset1NodeDesc, ref NodeDescription asset2NodeDesc) { var node = diff3.Asset1Node ?? diff3.Asset2Node ?? diff3.BaseNode; var dataVisitMember = node as DataVisitMember; if (dataVisitMember != null) { var diffMember = dataVisitMember.MemberDescriptor.GetCustomAttributes <DiffMemberAttribute>(true).FirstOrDefault(); if (diffMember != null) { if (diffMember.PreferredChange.HasValue) { diff3.ChangeType = diffMember.PreferredChange.Value; } diff3.Weight = diffMember.Weight; } } var instanceType = asset1NodeDesc.Instance?.GetType() ?? asset2NodeDesc.Instance?.GetType(); object baseInstance = baseNodeDesc.Instance; object asset1Instance = asset1NodeDesc.Instance; object asset2Instance = asset2NodeDesc.Instance; // If this is an identifiable type (but we are for example not visiting its member), compare only the Ids instead if (UseOverrideMode && instanceType != null && IdentifiableHelper.IsIdentifiable(instanceType)) { baseInstance = IdentifiableHelper.GetId(baseInstance); asset1Instance = IdentifiableHelper.GetId(asset1Instance); asset2Instance = IdentifiableHelper.GetId(asset2Instance); } var baseAsset1Equals = Equals(baseInstance, asset1Instance); var baseAsset2Equals = Equals(baseInstance, asset2Instance); var asset1And2Equals = Equals(asset1Instance, asset2Instance); diff3.ChangeType = baseAsset1Equals && baseAsset2Equals ? Diff3ChangeType.None : baseAsset2Equals ? Diff3ChangeType.MergeFromAsset1 : baseAsset1Equals ? Diff3ChangeType.MergeFromAsset2 : asset1And2Equals ? Diff3ChangeType.MergeFromAsset1And2 : Diff3ChangeType.Conflict; }
/// <inheritdoc/> protected override void TransformObjectAfterRead(ref ObjectContext objectContext) { if (!AreCollectionItemsIdentifiable(ref objectContext)) { base.TransformObjectAfterRead(ref objectContext); return; } var info = (InstanceInfo)objectContext.Properties[InstanceInfoKey]; // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item if (info.Instance != null) { ICollection <ItemId> deletedItems; objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems); TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, info.Instance, deletedItems); } objectContext.Instance = info.Instance; var enumerable = objectContext.Instance as IEnumerable; if (enumerable != null) { var ids = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance); var descriptor = (DictionaryDescriptor)info.Descriptor; foreach (var item in descriptor.GetEnumerator(objectContext.Instance)) { ItemId id; if (ids.TryGet(item.Key, out id) && id != ItemId.Empty) { continue; } var guid = item.Value != null?IdentifiableHelper.GetId(item.Value) : Guid.NewGuid(); ids[item.Key] = guid != Guid.Empty ? new ItemId(guid.ToByteArray()) : ItemId.New(); } } base.TransformObjectAfterRead(ref objectContext); }
public override void Serialize(ref MaterialNull obj, ArchiveMode mode, SerializationStream stream) { if (stream.Context.SerializerSelector.HasProfile("AssetClone")) { // At design time, when performing a clone, we keep the associated id of this instance. if (mode == ArchiveMode.Serialize) { var id = IdentifiableHelper.GetId(obj); stream.Write(id); } else { var id = stream.Read <Guid>(); obj = new MaterialNull(); IdentifiableHelper.SetId(obj, id); } } else { // For runtime serialization, a MaterialNull becomes null obj = null; } }
/// <inheritdoc/> protected override void TransformObjectAfterRead(ref ObjectContext objectContext) { InstanceInfo info; if (!objectContext.Properties.TryGetValue(InstanceInfoKey, out info)) { base.TransformObjectAfterRead(ref objectContext); if (AreCollectionItemsIdentifiable(ref objectContext)) { // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item var enumerable = objectContext.Instance as IEnumerable; if (enumerable != null) { var ids = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance); var i = 0; foreach (var item in enumerable) { var id = item != null?IdentifiableHelper.GetId(item) : Guid.NewGuid(); ids[i] = id != Guid.Empty ? new ItemId(id.ToByteArray()) : ItemId.New(); ++i; } } } return; } var instance = info.Instance ?? objectContext.SerializerContext.ObjectFactory.Create(info.Descriptor.Type); ICollection <ItemId> deletedItems; objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems); TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, instance, deletedItems); objectContext.Instance = instance; base.TransformObjectAfterRead(ref objectContext); }
public override object ConvertFrom(ref ObjectContext context, Scalar fromScalar) { Guid guid; UFile location; Guid referenceId; if (!AssetReference.TryParse(fromScalar.Value, out referenceId, out guid, out location)) { throw new YamlException(fromScalar.Start, fromScalar.End, "Unable to decode asset reference [{0}]. Expecting format GUID:LOCATION".ToFormat(fromScalar.Value)); } var instance = AttachedReferenceManager.CreateProxyObject(context.Descriptor.Type, guid, location); // If the referenceId is empty, force its creation, else attach it to the reference if (referenceId == Guid.Empty) { IdentifiableHelper.GetId(instance); } else { IdentifiableHelper.SetId(instance, referenceId); } return(instance); }
public void TestIdentifierHelper() { // Has IdentifierHelper is using ShadowObject, we will test it here ShadowObject.Enable = true; var obj = new object(); var id = IdentifiableHelper.GetId(obj); Assert.AreNotEqual(Guid.Empty, id); var id1 = IdentifiableHelper.GetId(obj); Assert.AreEqual(id, id1); // We should not get an id for a collection var idCollection = IdentifiableHelper.GetId(new List <object>()); Assert.AreEqual(Guid.Empty, idCollection); // We should not get an id for a dictionary var idDict = IdentifiableHelper.GetId(new MyDictionary()); Assert.AreEqual(Guid.Empty, idDict); }
public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value) { base.VisitObjectMember(container, containerDescriptor, member, value); var assetReference = value as AssetReference; var assetBase = value as AssetBase; var attachedReference = AttachedReferenceManager.GetAttachedReference(value); if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(member.Type, guid ?? assetReference.Id, location); member.Set(container, newValue); return(newValue); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); member.Set(container, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateProxyObject(member.Type, guid.Value, location) : null; if (newValue != null) { IdentifiableHelper.SetId(newValue, IdentifiableHelper.GetId(value)); } member.Set(container, newValue); return(newValue); }); } else if (value is UFile) { AddLink(value, (guid, location) => { var newValue = new UFile(location); member.Set(container, newValue); return(newValue); }); } else if (value is UDirectory) { AddLink(value, (guid, location) => { var newValue = new UDirectory(location); member.Set(container, newValue); return(newValue); }); } }
public override object Get(object thisObject) { return(IdentifiableHelper.GetId(thisObject)); }
private void FixReferencesToEntities(EntityDesign newEntityDesign, Dictionary <GroupPartKey, Guid> mapBaseIdToNewId) { var newEntity = newEntityDesign.Entity; // We need to visit all references to entities/components in order to fix references // (e.g entities removed, entity added from base referencing an entity from base that we have to redirect to the new child entity...) // Suppose for example that: // // base newBase newAsset // EA EA EA' // EB EB EB' // EC EC EC' // ED (+link to EA via script or whather) ED' + link to EA' (we need to change from EA to EA') // // So in the example above, when merging ED into newAsset, all references to entities declared in newBase are not automatically // remapped to the new entities in newAsset. This is the purpose of this whole method var entityVisitor = new SingleLevelVisitor(typeof(Entity), true); var entityComponentVisitor = new SingleLevelVisitor(typeof(EntityComponent), true); DataVisitNodeBuilder.Run(TypeDescriptorFactory.Default, newEntity, new List <IDataCustomVisitor>() { entityVisitor, entityComponentVisitor }); // Fix Entity and EntityComponent references foreach (var idNodes in entityVisitor.References.Concat(entityComponentVisitor.References)) { var id = idNodes.Key; var nodes = idNodes.Value; // If entity id is not in the current list, it is more likely that it was a link to a base entity if (!newAsset.Hierarchy.Parts.ContainsKey(id)) { var groupKey = new GroupPartKey(newEntityDesign.BasePartInstanceId, id); // We are trying to remap the base id to the new id from known entities from newAsset Guid newId; if (mapBaseIdToNewId.TryGetValue(groupKey, out newId)) { var linkedEntity = newAsset.Hierarchy.Parts[newId].Entity; foreach (var node in nodes) { var entityComponent = node.Instance as EntityComponent; if (entityComponent != null) { var entityComponentId = IdentifiableHelper.GetId(entityComponent); // TODO: In case of a DataVisitMember node, we need to set an OverrideType to New if we are actually removing a base value var newEntityComponent = (EntityComponent)linkedEntity.Components.FirstOrDefault(t => IdentifiableHelper.GetId(t) == entityComponentId); node.SetValue(newEntityComponent); } else { // TODO: In case of a DataVisitMember node, we need to set an OverrideType to New if we are actually removing a base value // Else the node applies to an entity node.SetValue(linkedEntity); } } } else { // TODO: In case of a DataVisitMember node, we need to set an OverrideType to New if we are actually removing a base value // If we are trying to link to an entity/component that was removed, we need to remove it foreach (var node in nodes) { node.RemoveValue(); } } } } }
public override string ConvertTo(ref ObjectContext objectContext) { var materialNull = ((MaterialNull)objectContext.Instance); return(IdentifiableHelper.GetId(materialNull).ToString()); }
public override void VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitArrayItem(array, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var assetBase = item as AssetBase; var attachedReference = AttachedReferenceManager.GetAttachedReference(item); if (assetReference != null) { AddLink(item, (guid, location) => { var newValue = AssetReference.New(descriptor.ElementType, guid ?? assetReference.Id, location); array.SetValue(newValue, index); return(newValue); }); } else if (assetBase != null) { AddLink(item, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); array.SetValue(newValue, index); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null; if (newValue != null) { IdentifiableHelper.SetId(newValue, IdentifiableHelper.GetId(item)); } array.SetValue(newValue, index); return(newValue); }); } else if (item is UFile) { AddLink(item, (guid, location) => { var newValue = new UFile(location); array.SetValue(newValue, index); return(newValue); }); } else if (item is UDirectory) { AddLink(item, (guid, location) => { var newValue = new UFile(location); array.SetValue(newValue, index); return(newValue); }); } }
public void Test() { var prefab = new PrefabAsset(); var modelComponent = new ModelComponent(); var entity = new Entity() { modelComponent }; prefab.Hierarchy.Parts.Add(new EntityDesign(entity)); prefab.Hierarchy.RootPartIds.Add(entity.Id); var material1 = new MaterialNull(); IdentifiableHelper.SetId(material1, new Guid("39E2B226-8752-4678-8E93-76FFBFBA337B")); var material2 = new MaterialNull(); IdentifiableHelper.SetId(material2, new Guid("CC4F1B31-FBB7-4360-A3E7-060BDFDA0695")); modelComponent.Materials.Add(material1); modelComponent.Materials.Add(material2); Action <PrefabAsset> checkPrefab = (newPrefab) => { var previousEntityDesign = newPrefab.Hierarchy.Parts.FirstOrDefault(); Assert.NotNull(previousEntityDesign); var previousEntity = previousEntityDesign.Entity; var component = previousEntity.Get <ModelComponent>(); Assert.NotNull(component); Assert.AreEqual(2, component.Materials.Count); var newMaterial1 = component.Materials[0]; Assert.AreEqual(IdentifiableHelper.GetId(material1), IdentifiableHelper.GetId(newMaterial1)); var newMaterial2 = component.Materials[1]; Assert.AreEqual(IdentifiableHelper.GetId(material2), IdentifiableHelper.GetId(newMaterial2)); }; // Test yaml serialization { using (var stream = new MemoryStream()) { AssetSerializer.Save(stream, prefab); stream.Position = 0; var serializedVersion = Encoding.UTF8.GetString(stream.ToArray()); Console.WriteLine(serializedVersion); stream.Position = 0; var newPrefab = (PrefabAsset)AssetSerializer.Load(stream, "myentity"); checkPrefab(newPrefab); } } // Test cloning var newPrefabClone = (PrefabAsset)AssetCloner.Clone(prefab); checkPrefab(newPrefabClone); // Test runtime serialization (runtime serialization is removing MaterialNull and replacing it by a null) { var stream = new MemoryStream(); var writer = new BinarySerializationWriter(stream) { Context = { SerializerSelector = SerializerSelector.AssetWithReuse } }; writer.SerializeExtended(entity, ArchiveMode.Serialize); writer.Flush(); stream.Position = 0; var reader = new BinarySerializationReader(stream) { Context = { SerializerSelector = SerializerSelector.AssetWithReuse } }; Entity newEntity = null; reader.SerializeExtended(ref newEntity, ArchiveMode.Deserialize); Assert.NotNull(newEntity); var component = newEntity.Get <ModelComponent>(); Assert.NotNull(component); Assert.AreEqual(2, component.Materials.Count); Assert.Null(component.Materials[0]); Assert.Null(component.Materials[1]); } }
public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var assetBase = item as AssetBase; var attachedReference = AttachedReferenceManager.GetAttachedReference(item); // We cannot set links if we do not have indexer accessor if (!descriptor.HasIndexerAccessors) { return; } if (assetReference != null) { AddLink(assetReference, (guid, location) => { var link = AssetReference.New(descriptor.ElementType, guid ?? assetReference.Id, location); descriptor.SetValue(collection, index, link); return(link); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var link = new AssetBase(location, assetBase.Asset); descriptor.SetValue(collection, index, link); return(link); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { var link = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null; if (link != null) { IdentifiableHelper.SetId(link, IdentifiableHelper.GetId(item)); } descriptor.SetValue(collection, index, link); return(link); }); } else if (item is UFile) { AddLink(item, (guid, location) => { var link = new UFile(location); descriptor.SetValue(collection, index, link); return(link); }); } else if (item is UDirectory) { AddLink(item, (guid, location) => { var link = new UDirectory(location); descriptor.SetValue(collection, index, link); return(link); }); } }
public override void VisitDictionaryKeyValue(object dictionaryObj, DictionaryDescriptor descriptor, object key, ITypeDescriptor keyDescriptor, object value, ITypeDescriptor valueDescriptor) { base.VisitDictionaryKeyValue(dictionaryObj, descriptor, key, keyDescriptor, value, valueDescriptor); var assetReference = value as AssetReference; var assetBase = value as AssetBase; var attachedReference = AttachedReferenceManager.GetAttachedReference(value); if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(descriptor.ValueType, guid ?? assetReference.Id, location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ValueType, guid.Value, location) : null; if (newValue != null) { IdentifiableHelper.SetId(newValue, IdentifiableHelper.GetId(value)); } descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (value is UFile) { AddLink(value, (guid, location) => { var newValue = new UFile(location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (value is UDirectory) { AddLink(value, (guid, location) => { var newValue = new UDirectory(location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } }