Beispiel #1
0
        static object CloneManagedComponent(object obj)
        {
            if (obj == null)
            {
                return(null);
            }
            else
            {
#if !NET_DOTS
                var type   = obj.GetType();
                var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp);
                var writer = new PropertiesBinaryWriter(&buffer);
                BoxedProperties.WriteBoxedType(obj, writer);

                var    readBuffer = buffer.AsReader();
                var    r2         = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable());
                object newObj     = BoxedProperties.ReadBoxedClass(type, r2);
                buffer.Dispose();
                return(newObj);
#else
                // Until DOTS Runtime supports Properties just reuse the same instance
                return(obj);
#endif
            }
        }
    public unsafe void UnsafeAppendBuffer_AddAndPop()
    {
        var buffer = new UnsafeAppendBuffer(0, 8, Allocator.Temp);

        buffer.Add <int>(123);
        buffer.Add <int>(234);
        buffer.Add <int>(345);

        {
            var array = new NativeArray <int>(3, Allocator.Temp);
            buffer.Pop(array.GetUnsafePtr(), 3 * UnsafeUtility.SizeOf <int>());
            CollectionAssert.AreEqual(new[] { 123, 234, 345 }, array);
        }

        {
            var array = new NativeArray <int>(4, Allocator.Temp);
            array.CopyFrom(new[] { 987, 876, 765, 654 });
            buffer.Add(array.GetUnsafePtr(), 4 * UnsafeUtility.SizeOf <int>());
        }

        Assert.AreEqual(654, buffer.Pop <int>());
        Assert.AreEqual(765, buffer.Pop <int>());
        Assert.AreEqual(876, buffer.Pop <int>());
        Assert.AreEqual(987, buffer.Pop <int>());

        buffer.Dispose();
    }
Beispiel #3
0
    unsafe public void ReadWriteBoxedWithStringArrayWithOneElement()
    {
        var srcData = new ComponentWithStringArray()
        {
            StringArray = new string[] { "One" }
        };

        // Write to stream
        var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent);
        var writer = new ManagedObjectBinaryWriter(&buffer);

        var boxedSrcData = (object)srcData;

        writer.WriteObject(boxedSrcData);

        var objectTable = writer.GetUnityObjects();

        // Read from stream
        var readStream = buffer.AsReader();
        var reader     = new ManagedObjectBinaryReader(&readStream, objectTable);

        var boxedRead = reader.ReadObject(typeof(ComponentWithStringArray));

        // Check same
        ComponentWithStringArray.AreEqual(srcData, (ComponentWithStringArray)boxedRead);

        buffer.Dispose();
    }
Beispiel #4
0
    unsafe public void ReadWriteBoxed()
    {
        var srcData = ConfigureStruct();

        // Write to stream
        var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent);
        var writer = new ManagedObjectBinaryWriter(&buffer);

        var boxedSrcData = (object)srcData;

        writer.WriteObject(boxedSrcData);

        var objectTable = writer.GetUnityObjects();

        // Read from stream
        var readStream = buffer.AsReader();
        var reader     = new ManagedObjectBinaryReader(&readStream, objectTable);

        var boxedRead = reader.ReadObject(typeof(TestStruct));

        // Check same
        TestStruct.AreEqual(srcData, (TestStruct)boxedRead);

        buffer.Dispose();
    }
Beispiel #5
0
    unsafe public void ReadWriteBoxedWithStringArrayWithOneElement()
    {
        var srcData = new ComponentWithStringArray()
        {
            StringArray = new string[] { "One" }
        };

        // Write to stream
        var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent);
        var writer = new PropertiesBinaryWriter(&buffer);

        var boxedSrcData = (object)srcData;

        BoxedProperties.WriteBoxedType(boxedSrcData, writer);

        var objectTable = writer.GetObjectTable();

        // Read from stream
        var readStream = writer.Buffer.AsReader();
        var reader     = new PropertiesBinaryReader(&readStream, objectTable);

        var boxedRead = BoxedProperties.ReadBoxedClass(typeof(ComponentWithStringArray), reader);

        // Check same
        ComponentWithStringArray.AreEqual(srcData, (ComponentWithStringArray)boxedRead);

        buffer.Dispose();
    }
Beispiel #6
0
    unsafe public void ReadWriteObjectTableIndex()
    {
        var srcData = ConfigureStruct();

        // Write to stream
        var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent);
        var writer = new PropertiesBinaryWriter(&buffer);

        PropertyContainer.Visit(ref srcData, writer);

        var objectTable = writer.GetObjectTable();

        // Read from stream
        var readStream = writer.Buffer.AsReader();
        var reader     = new PropertiesBinaryReader(&readStream, objectTable);

        var readData = new TestStruct();

        PropertyContainer.Visit(ref readData, reader);

        // Check same
        TestStruct.AreEqual(srcData, readData);

        buffer.Dispose();
    }
Beispiel #7
0
    unsafe public void ReadWriteBoxed()
    {
        var srcData = ConfigureStruct();

        // Write to stream
        var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent);
        var writer = new PropertiesBinaryWriter(&buffer);

        var boxedSrcData = (object)srcData;

        BoxedProperties.WriteBoxedType(boxedSrcData, writer);

        var objectTable = writer.GetObjectTable();

        // Read from stream
        var readStream = writer.Buffer.AsReader();
        var reader     = new PropertiesBinaryReader(&readStream, objectTable);

        var boxedRead = BoxedProperties.ReadBoxedStruct(typeof(TestStruct), reader);

        // Check same
        TestStruct.AreEqual(srcData, (TestStruct)boxedRead);

        buffer.Dispose();
    }
    public unsafe void UnsafeAppendBuffer_PushHeadersWithPackets()
    {
        var buffer         = new UnsafeAppendBuffer(0, 8, Allocator.Temp);
        var scratchPayload = stackalloc byte[1024];
        var expectedSize   = 0;

        for (int i = 0; i < 1024; i++)
        {
            var packeType  = i;
            var packetSize = i;

            buffer.Add(new TestHeader
            {
                Type        = packeType,
                PayloadSize = packetSize
            });
            expectedSize += UnsafeUtility.SizeOf <TestHeader>();

            buffer.Add(scratchPayload, i);
            expectedSize += i;
        }
        Assert.True(expectedSize == buffer.Length);

        buffer.Dispose();
    }
Beispiel #9
0
 public void Dispose()
 {
     splitterOutput.Dispose();
     vertices.Dispose();
     triangles.Dispose();
     solidVertices.Dispose();
     solidTriangles.Dispose();
 }
    unsafe public void UnsafeAppendBuffer_DisposeExternal()
    {
        var data   = stackalloc int[1];
        var buffer = new UnsafeAppendBuffer(data, sizeof(int));

        buffer.Add(5);
        buffer.Dispose();
        Assert.AreEqual(5, data[0]);
    }
        public byte[] ToMsg()
        {
            var buffer = new UnsafeAppendBuffer(0, 16, Allocator.TempJob);

            Serialize(ref buffer);
            var bytes = buffer.ToBytes();

            buffer.Dispose();
            return(bytes);
        }
 public void Dispose()
 {
     CreateChunks.Dispose();
     AddComponentToChunks.Dispose();
     RemoveComponentFromChunks.Dispose();
     AddComponentBatches.Dispose();
     RemoveComponentBatches.Dispose();
     ChunkScratch.Dispose();
     BatchScratch.Dispose();
 }
Beispiel #13
0
            unsafe public static void SerializeResourcePacket(EntityChangeSet entityChangeSet, ref UnsafeAppendBuffer buffer)
            {
                var changeSetBuffer = new UnsafeAppendBuffer(1024, 16, Allocator.TempJob);

                Serialize(entityChangeSet, &changeSetBuffer, out var globalObjectIds);

                buffer.Add(globalObjectIds);
                buffer.Add(changeSetBuffer.Ptr, changeSetBuffer.Length);

                changeSetBuffer.Dispose();
                globalObjectIds.Dispose();
            }
    public unsafe void UnsafeAppendBuffer_ReadNextArray()
    {
        var values = new NativeArray <int>(new[] { 123, 234, 345 }, Allocator.Temp);
        var buffer = new UnsafeAppendBuffer(0, 8, Allocator.Temp);

        buffer.Add(values);

        var array = (int *)buffer.AsReader().ReadNextArray <int>(out var count);

        Assert.AreEqual(values.Length, count);
        for (int i = 0; i < count; ++i)
        {
            Assert.AreEqual(values[i], array[i]);
        }

        values.Dispose();
        buffer.Dispose();
    }
Beispiel #15
0
        protected override T SerializeAndDeserialize <T>(T value, CommonSerializationParameters parameters = default)
        {
            var stream = new UnsafeAppendBuffer(16, 8, Allocator.Temp);

            var binarySerializationParameters = new BinarySerializationParameters
            {
                DisableSerializedReferences = parameters.DisableSerializedReferences
            };

            try
            {
                BinarySerialization.ToBinary(&stream, value, binarySerializationParameters);
                var reader = stream.AsReader();
                return(BinarySerialization.FromBinary <T>(&reader, binarySerializationParameters));
            }
            finally
            {
                stream.Dispose();
            }
        }
    public unsafe void UnsafeAppendBuffer_ReadHeadersWithPackets()
    {
        var buffer         = new UnsafeAppendBuffer(0, 8, Allocator.Temp);
        var scratchPayload = stackalloc byte[1024];

        for (int i = 0; i < 1024; i++)
        {
            var packeType  = i;
            var packetSize = i;

            buffer.Add(new TestHeader
            {
                Type        = packeType,
                PayloadSize = packetSize
            });

            UnsafeUtility.MemSet(scratchPayload, (byte)(i & 0xff), packetSize);

            buffer.Add(scratchPayload, i);
        }

        var reader = buffer.AsReader();

        for (int i = 0; i < 1024; i++)
        {
            var packetHeader = reader.ReadNext <TestHeader>();
            Assert.AreEqual(i, packetHeader.Type);
            Assert.AreEqual(i, packetHeader.PayloadSize);
            if (packetHeader.PayloadSize > 0)
            {
                var packetPayload = reader.ReadNext(packetHeader.PayloadSize);
                Assert.AreEqual((byte)(i & 0xff), *(byte *)packetPayload);
            }
        }
        Assert.True(reader.EndOfBuffer);

        buffer.Dispose();
    }
        public static void CopyManagedObjects(
            ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcStartIndex,
            ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstStartIndex, int count)
        {
            var srcI = 0;
            var dstI = 0;

            while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount)
            {
                if (srcArch->Types[srcI] < dstArch->Types[dstI])
                {
                    ++srcI;
                }
                else if (srcArch->Types[srcI] > dstArch->Types[dstI])
                {
                    ++dstI;
                }
                else
                {
                    if (srcArch->IsManaged(srcI))
                    {
                        var componentType = srcArch->Types[srcI];
                        var typeInfo      = TypeManager.GetTypeInfo(componentType.TypeIndex);
                        if (typeInfo.Category == TypeManager.TypeCategory.Class)
                        {
                            // If we are dealing with a Class/GameObject types just perform a shallow copy
                            for (var i = 0; i < count; ++i)
                            {
                                var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i);
                                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, obj);
                            }
                        }
                        else
                        {
#if NET_DOTS
                            for (var i = 0; i < count; ++i)
                            {
                                var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i);
                                // Until DOTS Runtime supports Properties just perform a simple shallow copy
                                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, obj);
                            }
#else
                            var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp);
                            for (var i = 0; i < count; ++i)
                            {
                                object newObj = null;
                                var    obj    = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i);

                                if (obj != null)
                                {
                                    // Unless we want to enforce managed components to implement an IDeepClonable interface
                                    // we instead generate a binary stream of an object and then use that to instantiate our new deep copy
                                    var writer = new PropertiesBinaryWriter(&buffer);
                                    BoxedProperties.WriteBoxedType(obj, writer);

                                    var readBuffer = buffer.AsReader();
                                    var reader     = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable());
                                    var type       = TypeManager.GetType(componentType.TypeIndex);
                                    newObj = BoxedProperties.ReadBoxedClass(type, reader);

                                    buffer.Reset();
                                }
                                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, newObj);
                            }
                            buffer.Dispose();
#endif
                        }
                    }

                    ++srcI;
                    ++dstI;
                }
            }
        }
Beispiel #18
0
 public void Dispose()
 {
     GlobalObjectIds.Dispose();
     ChangeSet.Dispose();
 }
Beispiel #19
0
        public void EventStreamerTest()
        {
            Debug.Log($"sizeof {nameof(Data11)} is {UnsafeUtility.SizeOf<Data11>()}");
            Debug.Log($"sizeof {nameof(Data11_Explicit)} is {UnsafeUtility.SizeOf<Data11_Explicit>()}");
            Debug.Log($"sizeof {nameof(OddData)} is {UnsafeUtility.SizeOf<OddData>()}");

            var registry = new EventDataTypes.EventTypeRegistry(Allocator.TempJob);
            var tid      = registry.NextUndefinedTypeID();

            Assert.AreEqual(0, tid);
            tid = registry.NextUndefinedTypeID();
            Assert.AreEqual(0, tid);
            var info = registry.RegisterEventType(tid)
                       .RegisterNextDataType <float>()
                       .RegisterNextDataType <float>()
                       .RegisterNextDataType <float>()
                       .RegisterNextDataType <float>()
                       .RegisterNextDataType <int>()
                       .RegisterNextDataType <int>()
                       .RegisterNextDataType <int>()
                       .RegisterNextDataType <int>();


            var streamer = new EventStreamer(Allocator.TempJob);

            //Write events---------------------------------------------------------------------------------------------------------------------------
            var w        = streamer.AsWriter();
            var evtHdrIn = new EventHeader(0);

            evtHdrIn.SetLocalDataAt <float>(0, 1.5f);
            evtHdrIn.SetLocalDataAt <float>(4, 2.5f);
            evtHdrIn.SetLocalDataAt <float>(8, 3.5f);
            evtHdrIn.SetLocalDataAt <float>(12, 4.5f);

            var handle = w.BeginBatch();

            //event 0
            handle.WriteHeader(evtHdrIn, 16).WriteExternalData <int>(3).WriteExternalData <int>(4).WriteExternalData <int>(5).WriteExternalData <int>(6);


            var buffer = handle.CreateEventBuffer();

            //event 1
            buffer.NewEvent(1)
            .AddData <int>(0).AddData <int>(1).AddData <int>(2).AddData <int>(3).AddData <int>(4).AddData <int>(5)
            .AddData <int>(6).AddData <int>(7).AddData <int>(8).AddData <int>(9).AddData <int>(10).AddData <int>(11)
            .Write();

            //event 2
            buffer.NewEvent(2)
            .AddData <OddData>(new OddData()
            {
                Data0 = 11, Data1 = 24, Data2 = 3
            })
            .AddData <OddData>(new OddData()
            {
                Data0 = 12, Data1 = 25, Data2 = 2
            })
            .AddData <OddData>(new OddData()
            {
                Data0 = 13, Data1 = 26, Data2 = 1
            })
            .Write();

            //event 3
            buffer.NewEvent(3).AddData <int>(0).Write();

            //event 4
            buffer.NewEvent(4).AddData <int>(-1).StartExternalData().AddData <int>(1).AddData <int>(2).AddData <int>(3).Write();

            //event 5
            buffer.NewEvent(5).AddData <SomeEventData>
            (
                new SomeEventData()
            {
                st = new SourceTargetPair()
                {
                    Source = new Entity()
                    {
                        Index = 10, Version = 11
                    },
                    Target = new Entity()
                    {
                        Index = 20, Version = 21
                    },
                },
                Damage     = 99,
                LargeData0 = 50,
                LargeData1 = 50,
                LargeData2 = 50,
                LargeData3 = 50,
            }
            ).Write();


            buffer.Dispose();
            //event 6,7
            handle.WriteEvent(6, 10);
            handle.WriteEvent(7, (ulong)32767, (ulong)65535);

            handle.EndBatch();

            //Read events---------------------------------------------------------------------------------------------------------------------------


            streamer.CollectElementsToRead(out var batch2Read, out var elementCount, Allocator.TempJob).Complete();
            Debug.Log($"Stream has {elementCount.Value} Items in {batch2Read.Length} batches, start Reading");

            var r                 = streamer.AsReader();
            var eventsOut         = new NativeArray <GenericEvent>(elementCount.Value, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            int totalExternalSize = 0;

            for (int b = 0, lenB = batch2Read.Length; b < lenB; b++)
            {
                var rh = r.BeginBatch(batch2Read[b]);
                for (int i = 0, lenE = rh.ElementCount; i < lenE; i++)
                {
                    var e = rh.ReadEvent();
                    totalExternalSize += e.SizeInfo.ExternalDataByteSize;
                    eventsOut[i]       = e;
                }
                rh.EndBatch();
            }
            elementCount.Dispose();
            batch2Read.Dispose();

            Debug.Log($"Stream has {streamer.CalculateEventCount()} Items in {streamer.CalculateBlockCount()} Blocks, after Reading");


            //Move Data from stream to buffer --------------------------------------------------------------------------------------------------------

            var externalCache = new UnsafeAppendBuffer(totalExternalSize, Unity.Jobs.LowLevel.Unsafe.JobsUtility.CacheLineSize, Allocator.TempJob);
            var checkSum      = 0;

            for (int i = 0, len = eventsOut.Length; i < len; i++)
            {
                var e = eventsOut[i];
                checkSum    += e.MoveExternalDataTo(ref externalCache);
                eventsOut[i] = e;
            }
            Assert.AreEqual(totalExternalSize, checkSum);

            //Release stream  memory ---------------------------------------
            streamer.Dispose();

            int     intData   = default;
            float   floatData = default;
            OddData oddData   = default;

            var evtOut = eventsOut[0];

            LogEventInfo(evtOut, 0);
            Assert.AreEqual(0, evtOut.TypeID);

            Debug.Log((floatData = info.GetData <float>(0, evtOut)).ToString());
            Assert.AreEqual(1.5f, floatData);
            Debug.Log((floatData = info.GetData <float>(1, evtOut)).ToString());
            Assert.AreEqual(2.5f, floatData);
            Debug.Log((floatData = info.GetData <float>(2, evtOut)).ToString());
            Assert.AreEqual(3.5f, floatData);
            Debug.Log((floatData = info.GetData <float>(3, evtOut)).ToString());
            Assert.AreEqual(4.5f, floatData);

            Debug.Log((intData = info.GetData <int>(4, evtOut)).ToString());
            Assert.AreEqual(3, intData);
            Debug.Log((intData = info.GetData <int>(5, evtOut)).ToString());
            Assert.AreEqual(4, intData);
            Debug.Log((intData = info.GetData <int>(6, evtOut)).ToString());
            Assert.AreEqual(5, intData);
            Debug.Log((intData = info.GetData <int>(7, evtOut)).ToString());
            Assert.AreEqual(6, intData);

            evtOut = eventsOut[1];
            LogEventInfo(evtOut, 1);
            Assert.AreEqual(1, evtOut.TypeID);
            for (int i = 0; i < 12; i++)
            {
                Debug.Log((intData = evtOut.GetDataAt <int>(i * 4)).ToString());
                Assert.AreEqual(i, intData);
            }
            Debug.Log((intData = evtOut.LocalDataAt <int>(12)).ToString());
            Assert.AreEqual(3, intData);
            Debug.Log((intData = evtOut.ExternalDataAt <int>(0)).ToString());
            Assert.AreEqual(4, intData);

            evtOut = eventsOut[2];
            LogEventInfo(evtOut, 2);
            Assert.AreEqual(2, evtOut.TypeID);
            var oddSize = UnsafeUtility.SizeOf <OddData>();

            for (int i = 0; i < 3; i++)
            {
                oddData = evtOut.GetDataAt <OddData>(i * oddSize);
                Debug.Log(oddData.Data0.ToString());
            }
            // Debug.Log((oddData = evtOut.LocalDataAt<OddData>(0)).Data0.ToString());
            // Debug.Log((oddData = evtOut.ExternalDataAt<OddData>(0)).Data0.ToString());

            evtOut = eventsOut[3];
            LogEventInfo(evtOut, 3);
            Assert.AreEqual(3, evtOut.TypeID);

            evtOut = eventsOut[4];
            LogEventInfo(evtOut, 4);
            Assert.AreEqual(4, evtOut.TypeID);
            Debug.Log((intData = evtOut.LocalDataAt <int>(0)).ToString());
            Assert.AreEqual(-1, intData);
            Debug.Log((intData = evtOut.ExternalDataAt <int>(0)).ToString());
            Assert.AreEqual(1, intData);
            Debug.Log((intData = evtOut.ExternalDataAt <int>(4)).ToString());
            Assert.AreEqual(2, intData);
            Debug.Log((intData = evtOut.ExternalDataAt <int>(8)).ToString());
            Assert.AreEqual(3, intData);

            evtOut = eventsOut[5];
            LogEventInfo(evtOut, 5);
            var sd = evtOut.ExternalDataAs <SomeEventData>();

            Debug.Log($"some data: source[{sd.st.Source.Entity.Index}:{sd.st.Source.Entity.Version}] target[{sd.st.Target.Entity.Index}:{sd.st.Target.Entity.Version}] Damage{sd.Damage}");
            Debug.Log($"some data: LargeData0[{sd.LargeData0}] LargeData1[{sd.LargeData1}] LargeData2[{sd.LargeData2}] LargeData3[{sd.LargeData3}]");

            evtOut = eventsOut[6];
            LogEventInfo(evtOut, 6);
            Debug.Log($"Local:{evtOut.LocalDataAs<int>()}");
            Assert.AreEqual(10, evtOut.LocalDataAs <int>());


            evtOut = eventsOut[7];
            LogEventInfo(evtOut, 7);
            Debug.Log($"Local:{evtOut.LocalDataAs<ulong>()} External:{evtOut.ExternalDataAs<ulong>()}");
            Assert.AreEqual(32767, evtOut.LocalDataAs <ulong>());
            Assert.AreEqual(65535, evtOut.ExternalDataAs <ulong>());

            // wh.WriteEvent(6, 10);
            // wh.WriteEvent(7, (ulong)32767, (ulong)65535);


            if (streamer.IsCreated)
            {
                streamer.Dispose();
            }
            if (eventsOut.IsCreated)
            {
                eventsOut.Dispose();
            }
            if (externalCache.IsCreated)
            {
                externalCache.Dispose();
            }
            if (registry.IsCreated)
            {
                registry.Dispose();
            }
        }
    public void UnsafeAppendBuffer_DisposeEmpty()
    {
        var buffer = new UnsafeAppendBuffer(0, 8, Allocator.Temp);

        buffer.Dispose();
    }
        public static void ReplicateManagedObjects(
            ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcIndex,
            ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstBaseIndex, int count, Entity srcEntity, NativeArray <Entity> dstEntities)
        {
            object[] companionGameObjectInstances = null;

            var srcI = 0;
            var dstI = 0;

            while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount)
            {
                if (srcArch->Types[srcI] < dstArch->Types[dstI])
                {
                    ++srcI;
                }
                else if (srcArch->Types[srcI] > dstArch->Types[dstI])
                {
                    ++dstI;
                }
                else
                {
                    if (srcArch->IsManaged(srcI))
                    {
                        var componentType = srcArch->Types[srcI];
                        var typeInfo      = TypeManager.GetTypeInfo(componentType.TypeIndex);
                        var obj           = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcIndex);

                        if (typeInfo.Category == TypeManager.TypeCategory.Class)
                        {
                            // If we're dealing with a class based type, we will defer the execution to InstantiateHybridComponent (if dependency injection was made), this method will
                            // - Determine if the object should be cloned (true is returned) or referenced (false is returned)
                            // - Clone the GameObject and its components (as many times as we have in 'count'), and make it a Companion Game Object by adding a CompanionLink component to it
                            // - Add the Cloned Hybrid Component to the instantiated entities (again 'count' times)
                            if (InstantiateHybridComponent == null || !InstantiateHybridComponent(obj, srcStore, dstArch, dstStore, dstManagedArrayIndex, dstChunkCapacity, srcEntity, dstEntities, dstI, dstBaseIndex, ref companionGameObjectInstances))
                            {
                                // We end up here if we have to reference the object and not cloning it
                                for (var i = 0; i < count; ++i)
                                {
                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                                }
                            }
                        }
                        else
                        {
#if NET_DOTS
                            for (var i = 0; i < count; ++i)
                            {
                                // Until DOTS Runtime supports Properties just perform a simple shallow copy
                                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                            }
#else
                            if (obj == null)
                            {
                                // If we are dealing with a Class/GameObject types just perform a shallow copy
                                for (var i = 0; i < count; ++i)
                                {
                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                                }
                            }
                            else
                            {
                                // Unless we want to enforce managed components to implement an IDeepClonable interface
                                // we instead generate a binary stream of an object and then use that to instantiate our new deep copy
                                var type   = TypeManager.GetType(componentType.TypeIndex);
                                var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp);
                                var writer = new PropertiesBinaryWriter(&buffer);
                                BoxedProperties.WriteBoxedType(obj, writer);

                                for (var i = 0; i < count; ++i)
                                {
                                    var    readBuffer = buffer.AsReader();
                                    var    reader     = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable());
                                    object newObj     = BoxedProperties.ReadBoxedClass(type, reader);

                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, newObj);
                                }
                                buffer.Dispose();
                            }
#endif
                        }
                    }

                    ++srcI;
                    ++dstI;
                }
            }
        }
Beispiel #22
0
 public void TearDown()
 {
     m_Stream.Dispose();
 }