示例#1
0
    /// <summary>
    /// Set GIF data
    /// </summary>
    /// <param name="gifBytes">GIF byte data</param>
    /// <param name="gifData">ref GIF data</param>
    /// <param name="debugLog">Debug log flag</param>
    /// <returns>Result</returns>
    private static bool SetGifData(byte[] gifBytes, ref GifData gifData, bool debugLog)
    {
        if (debugLog)
        {
            Debug.Log("SetGifData Start.");
        }

        if (gifBytes == null || gifBytes.Length <= 0)
        {
            Debug.LogError("bytes is nothing.");
            return(false);
        }

        int byteIndex = 0;

        if (SetGifHeader(gifBytes, ref byteIndex, ref gifData) == false)
        {
            Debug.LogError("GIF header set error.");
            return(false);
        }

        if (SetGifBlock(gifBytes, ref byteIndex, ref gifData) == false)
        {
            Debug.LogError("GIF block set error.");
            return(false);
        }

        if (debugLog)
        {
            gifData.Dump();
            Debug.Log("SetGifData Finish.");
        }
        return(true);
    }
示例#2
0
    /// <summary>
    /// Restores the material values
    /// </summary>
    /// <param name="m">Material</param>
    /// <param name="values">Set of values</param>
    public void SetValues(Material m, IEnumerable <StoredValue> values)
    {
        foreach (var v in values)
        {
            switch (v.property.type)
            {
            case MaterialProperty.PropertyType.Color:
                m.SetColor(v.property.name, (Color)v.value[0]);
                break;

            case MaterialProperty.PropertyType.Float:
                m.SetFloat(v.property.name, (float)v.value[0]);
                break;

            case MaterialProperty.PropertyType.Range:
                m.SetFloat(v.property.name, (float)v.value[0]);
                break;

            case MaterialProperty.PropertyType.TexEnv:
                m.SetTexture(v.property.name, (Texture)v.value[0]);
                m.SetTextureOffset(v.property.name, (Vector2)v.value[1]);
                m.SetTextureScale(v.property.name, (Vector2)v.value[2]);
                break;

            case MaterialProperty.PropertyType.Vector:
                m.SetVector(v.property.name, (Vector4)v.value[0]);
                break;

            default:
                Debug.LogError("Unsupported type: " + v.property.type.ToString());
                break;
            }
        }
    }
示例#3
0
    /// <summary>
    /// Get GIF texture list (This is a possibility of lock up)
    /// </summary>
    /// <param name="bytes">GIF file byte data</param>
    /// <param name="loopCount">out Animation loop count</param>
    /// <param name="width">out GIF image width (px)</param>
    /// <param name="height">out GIF image height (px)</param>
    /// <param name="filterMode">Textures filter mode</param>
    /// <param name="wrapMode">Textures wrap mode</param>
    /// <param name="debugLog">Debug Log Flag</param>
    /// <returns>GIF texture list</returns>
    public static List <GifTexture> GetTextureList(byte[] bytes, out int loopCount, out int width, out int height,
                                                   FilterMode filterMode = FilterMode.Bilinear, TextureWrapMode wrapMode = TextureWrapMode.Clamp, bool debugLog = false)
    {
        loopCount = -1;
        width     = 0;
        height    = 0;

        // Set GIF data
        var gifData = new GifData();

        if (SetGifData(bytes, ref gifData, debugLog) == false)
        {
            Debug.LogError("GIF file data set error.");
            return(null);
        }

        // Decode to textures from GIF data
        var gifTexList = new List <GifTexture>();

        if (DecodeTexture(gifData, gifTexList, filterMode, wrapMode) == false)
        {
            Debug.LogError("GIF texture decode error.");
            return(null);
        }

        loopCount = gifData.appEx.loopCount;
        width     = gifData.logicalScreenWidth;
        height    = gifData.logicalScreenHeight;
        return(gifTexList);
    }
示例#4
0
    // Writes mesh to an array of bytes.
    public static byte[] WriteMesh(Mesh mesh, bool saveTangents)
    {
        if (mesh == null)
        {
            Debug.LogError("No mesh given!");
            return(null);
        }

        var verts    = mesh.vertices;
        var normals  = mesh.normals;
        var tangents = mesh.tangents;
        var uvs      = mesh.uv;
        var tris     = mesh.triangles;

        // figure out vertex format
        byte format = 1;

        if (normals.Length > 0)
        {
            format |= 2;
        }
        if (saveTangents && tangents.Length > 0)
        {
            format |= 4;
        }
        if (uvs.Length > 0)
        {
            format |= 8;
        }

        var stream = new MemoryStream();
        var buf    = new BinaryWriter(stream);

        // write header
        var vertCount = (ushort)verts.Length;
        var triCount  = (ushort)(tris.Length / 3);

        buf.Write(vertCount);
        buf.Write(triCount);
        buf.Write(format);
        // vertex components
        WriteVector3Array16Bit(verts, buf);
        WriteVector3ArrayBytes(normals, buf);
        if (saveTangents)
        {
            WriteVector4ArrayBytes(tangents, buf);
        }
        WriteVector2Array16Bit(uvs, buf);
        // triangle indices
        foreach (var idx in tris)
        {
            var idx16 = (ushort)idx;
            buf.Write(idx16);
        }
        buf.Close();

        return(stream.ToArray());
    }
示例#5
0
    /// <summary>
    /// Set texture pixel row
    /// </summary>
    private static void SetTexturePixelRow(Texture2D tex, int y, ImageBlock imgBlock, byte[] decodedData, ref int dataIndex, List <byte[]> colorTable, Color32?bgColor, int transparentIndex, bool useBeforeTex)
    {
        // Row no (0~)
        int row = tex.height - 1 - y;

        for (int x = 0; x < tex.width; x++)
        {
            // Line no (0~)
            int line = x;

            // Out of image blocks
            if (row < imgBlock.imageTopPosition ||
                row >= imgBlock.imageTopPosition + imgBlock.imageHeight ||
                line < imgBlock.imageLeftPosition ||
                line >= imgBlock.imageLeftPosition + imgBlock.imageWidth)
            {
                if (useBeforeTex == false && bgColor != null)
                {
                    tex.SetPixel(x, y, bgColor.Value);
                }
                continue;
            }

            // Out of decoded data
            if (dataIndex >= decodedData.Length)
            {
                tex.SetPixel(x, y, Color.black);
                // Debug.LogError ("dataIndex exceeded the size of decodedData. dataIndex:" + dataIndex + " decodedData.Length:" + decodedData.Length + " y:" + y + " x:" + x);
                dataIndex++;
                continue;
            }

            // Get pixel color from color table
            byte colorIndex = decodedData[dataIndex];
            if (colorTable == null || colorTable.Count <= colorIndex)
            {
                Debug.LogError("colorIndex exceeded the size of colorTable. colorTable.Count:" + colorTable.Count + " colorIndex:" + colorIndex);
                dataIndex++;
                continue;
            }
            byte[] rgb = colorTable[colorIndex];

            // Set alpha
            byte alpha = transparentIndex >= 0 && transparentIndex == colorIndex ? (byte)0 : (byte)255;

            if (alpha != 0 || useBeforeTex == false)
            {
                Color32 col = new Color32(rgb[0], rgb[1], rgb[2], alpha);
                tex.SetPixel(x, y, col);
            }

            dataIndex++;
        }
    }
示例#6
0
    /// <summary>
    /// Get GIF texture list Coroutine (Avoid lock up but more slow)
    /// </summary>
    /// <param name="mb">MonoBehaviour to start the coroutine</param>
    /// <param name="bytes">GIF file byte data</param>
    /// <param name="cb">Callback method(param is GIF texture list, Animation loop count, GIF image width (px), GIF image height (px))</param>
    /// <param name="filterMode">Textures filter mode</param>
    /// <param name="wrapMode">Textures wrap mode</param>
    /// <param name="debugLog">Debug Log Flag</param>
    /// <returns>IEnumerator</returns>
    public static IEnumerator GetTextureListCoroutine(MonoBehaviour mb, byte[] bytes, Action <List <GifTexture>, int, int, int> cb,
                                                      FilterMode filterMode = FilterMode.Bilinear, TextureWrapMode wrapMode = TextureWrapMode.Clamp, bool debugLog = false)
    {
        int loopCount = -1;
        int width     = 0;
        int height    = 0;

        // Set GIF data
        var gifData = new GifData();

        if (SetGifData(bytes, ref gifData, debugLog) == false)
        {
            Debug.LogError("GIF file data set error.");
            if (cb != null)
            {
                cb(null, loopCount, width, height);
            }
            yield break;
        }

        // avoid lock up
        yield return(0);

        // Decode to textures from GIF data
        List <GifTexture> gifTexList = null;

        yield return(mb.StartCoroutine(UniGif.DecodeTextureCoroutine(gifData, gtList =>
        {
            gifTexList = gtList;
        }, filterMode, wrapMode)));

        if (gifTexList == null)
        {
            Debug.LogError("GIF texture decode error.");
            if (cb != null)
            {
                cb(null, loopCount, width, height);
            }
            yield break;
        }

        loopCount = gifData.appEx.loopCount;
        width     = gifData.logicalScreenWidth;
        height    = gifData.logicalScreenHeight;

        if (cb != null)
        {
            cb(gifTexList, loopCount, width, height);
        }
    }
示例#7
0
    /// <summary>
    /// Gets the values given a material
    /// </summary>
    /// <param name="m">The material</param>
    /// <returns>A StoredValue containing value and type information</returns>
    public List <StoredValue> GetValues(Material m)
    {
        var list   = GetShaderProperties(m);
        var output = new List <StoredValue>();

        foreach (var p in list)
        {
            var o = new StoredValue
            {
                property = p
            };
            output.Add(o);
            switch (p.type)
            {
            case MaterialProperty.PropertyType.Color:
                o.value    = new object[1];
                o.value[0] = m.GetColor(p.name);
                break;

            case MaterialProperty.PropertyType.Float:
                o.value    = new object[1];
                o.value[0] = m.GetFloat(p.name);
                break;

            case MaterialProperty.PropertyType.Range:
                o.value    = new object[1];
                o.value[0] = m.GetFloat(p.name);
                break;

            case MaterialProperty.PropertyType.TexEnv:
                o.value    = new object[3];
                o.value[0] = m.GetTexture(p.name);
                o.value[1] = m.GetTextureOffset(p.name);
                o.value[2] = m.GetTextureScale(p.name);
                break;

            case MaterialProperty.PropertyType.Vector:
                o.value    = new object[1];
                o.value[0] = m.GetVector(p.name);
                break;

            default:
                Debug.LogError("Unsupported type: " + p.type.ToString());
                break;
            }
        }
        return(output);
    }
示例#8
0
    /// <summary>
    /// Convert BitArray to int
    /// </summary>
    /// <returns>Converted int</returns>
    public static int ToNumeral(this BitArray array)
    {
        if (array == null)
        {
            Debug.LogError("array is nothing.");
            return(0);
        }
        if (array.Length > 32)
        {
            Debug.LogError("must be at most 32 bits long.");
            return(0);
        }

        var result = new int[1];

        array.CopyTo(result, 0);
        return(result[0]);
    }
示例#9
0
    private static bool SetGifHeader(byte[] gifBytes, ref int byteIndex, ref GifData gifData)
    {
        // Signature(3 Bytes)
        // 0x47 0x49 0x46 (GIF)
        if (gifBytes[0] != 'G' || gifBytes[1] != 'I' || gifBytes[2] != 'F')
        {
            Debug.LogError("This is not GIF image.");
            return(false);
        }
        gifData.sig0 = gifBytes[0];
        gifData.sig1 = gifBytes[1];
        gifData.sig2 = gifBytes[2];

        // Version(3 Bytes)
        // 0x38 0x37 0x61 (87a) or 0x38 0x39 0x61 (89a)
        if ((gifBytes[3] != '8' || gifBytes[4] != '7' || gifBytes[5] != 'a') &&
            (gifBytes[3] != '8' || gifBytes[4] != '9' || gifBytes[5] != 'a'))
        {
            Debug.LogError("GIF version error.\nSupported only GIF87a or GIF89a.");
            return(false);
        }
        gifData.ver0 = gifBytes[3];
        gifData.ver1 = gifBytes[4];
        gifData.ver2 = gifBytes[5];

        // Logical Screen Width(2 Bytes)
        gifData.logicalScreenWidth = BitConverter.ToUInt16(gifBytes, 6);

        // Logical Screen Height(2 Bytes)
        gifData.logicalScreenHeight = BitConverter.ToUInt16(gifBytes, 8);

        // 1 Byte
        {
            // Global Color Table Flag(1 Bit)
            gifData.globalColorTableFlag = (gifBytes[10] & 128) == 128; // 0b10000000

            // Color Resolution(3 Bits)
            switch (gifBytes[10] & 112)
            {
            case 112:     // 0b01110000
                gifData.colorResolution = 8;
                break;

            case 96:     // 0b01100000
                gifData.colorResolution = 7;
                break;

            case 80:     // 0b01010000
                gifData.colorResolution = 6;
                break;

            case 64:     // 0b01000000
                gifData.colorResolution = 5;
                break;

            case 48:     // 0b00110000
                gifData.colorResolution = 4;
                break;

            case 32:     // 0b00100000
                gifData.colorResolution = 3;
                break;

            case 16:     // 0b00010000
                gifData.colorResolution = 2;
                break;

            default:
                gifData.colorResolution = 1;
                break;
            }

            // Sort Flag(1 Bit)
            gifData.sortFlag = (gifBytes[10] & 8) == 8; // 0b00001000

            // Size of Global Color Table(3 Bits)
            int val = (gifBytes[10] & 7) + 1;
            gifData.sizeOfGlobalColorTable = (int)Math.Pow(2, val);
        }

        // Background Color Index(1 Byte)
        gifData.bgColorIndex = gifBytes[11];

        // Pixel Aspect Ratio(1 Byte)
        gifData.pixelAspectRatio = gifBytes[12];

        byteIndex = 13;
        if (gifData.globalColorTableFlag)
        {
            // Global Color Table(0~255×3 Bytes)
            gifData.globalColorTable = new List <byte[]>();
            for (int i = byteIndex; i < byteIndex + (gifData.sizeOfGlobalColorTable * 3); i += 3)
            {
                gifData.globalColorTable.Add(new byte[] { gifBytes[i], gifBytes[i + 1], gifBytes[i + 2] });
            }
            byteIndex = byteIndex + (gifData.sizeOfGlobalColorTable * 3);
        }

        return(true);
    }
示例#10
0
    private static bool SetGifBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData)
    {
        try
        {
            int lastIndex = 0;
            while (true)
            {
                int nowIndex = byteIndex;

                if (gifBytes[nowIndex] == 0x2c)
                {
                    // Image Block(0x2c)
                    SetImageBlock(gifBytes, ref byteIndex, ref gifData);
                }
                else if (gifBytes[nowIndex] == 0x21)
                {
                    // Extension
                    switch (gifBytes[nowIndex + 1])
                    {
                    case 0xf9:
                        // Graphic Control Extension(0x21 0xf9)
                        SetGraphicControlExtension(gifBytes, ref byteIndex, ref gifData);
                        break;

                    case 0xfe:
                        // Comment Extension(0x21 0xfe)
                        SetCommentExtension(gifBytes, ref byteIndex, ref gifData);
                        break;

                    case 0x01:
                        // Plain Text Extension(0x21 0x01)
                        SetPlainTextExtension(gifBytes, ref byteIndex, ref gifData);
                        break;

                    case 0xff:
                        // Application Extension(0x21 0xff)
                        SetApplicationExtension(gifBytes, ref byteIndex, ref gifData);
                        break;

                    default:
                        break;
                    }
                }
                else if (gifBytes[nowIndex] == 0x3b)
                {
                    // Trailer(1 Byte)
                    gifData.trailer = gifBytes[byteIndex];
                    byteIndex++;
                    break;
                }

                if (lastIndex == nowIndex)
                {
                    Debug.LogError("Infinite loop error.");
                    return(false);
                }

                lastIndex = nowIndex;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.Message);
            return(false);
        }

        return(true);
    }
示例#11
0
    public IEnumerator Load(int numberOfFrames, float timeScale = 0)
    {
        if (Data == null)
        {
            Debug.LogWarning("There was a problem loading Object Data!");
        }

        ++loadingCount;
        //var oldFixedTime = Time.fixedDeltaTime;
        //if (Application.isPlaying)
        //    Time.fixedDeltaTime = 9;
        //Need to wait while the base level is prepared, it takes 2 frames
        while (numberOfFrames-- > 0)
        {
            yield return(new WaitForEndOfFrame());
        }

        if (LevelSerializer.ShouldCollect && timeScale == 0)
        {
            GC.Collect();
        }

        LevelSerializer.RaiseProgress("Initializing", 0);
        if (Data != null && Data.rootObject != null)
        {
            Debug.Log(Data.StoredObjectNames.Any(sn => sn.Name == Data.rootObject) ? "Located " + Data.rootObject : "Not found " + Data.rootObject);
        }
        //Check if we should be deleting missing items
        if (!DontDelete)
        {
            //First step is to remove any items that should not exist according to the saved scene
            if (Data != null)
            {
                foreach (var go in
                         UniqueIdentifier.AllIdentifiers.Where(n => Data.StoredObjectNames.All(sn => sn.Name != n.Id)).ToList())
                {
                    try
                    {
                        var cancel = false;
                        OnDestroyObject(go.gameObject, ref cancel);
                        if (!cancel)
                        {
                            Destroy(go.gameObject);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogWarning("Problem destroying object " + go.name + " " + e.ToString());
                    }
                }
            }
        }

        var flaggedObjects = new List <UniqueIdentifier>();

        if (Data != null)
        {
            flaggedObjects.AddRange(Data.StoredObjectNames.Select(c => UniqueIdentifier.GetByName(c.Name)).Where(c => c != null).Select(c => c.GetComponent <UniqueIdentifier>()));
        }

        LevelSerializer.RaiseProgress("Initializing", 0.25f);

        var position = new Vector3(0, 2000, 2000);

        //Next we need to instantiate any items that are needed by the stored scene
        if (Data != null)
        {
            foreach (var sto in
                     Data.StoredObjectNames.Where(c => UniqueIdentifier.GetByName(c.Name) == null))
            {
                try
                {
                    if (sto.createEmptyObject || sto.ClassId == null || !LevelSerializer.AllPrefabs.ContainsKey(sto.ClassId))
                    {
                        sto.GameObject = new GameObject("CreatedObject");
                        sto.GameObject.transform.position = position;
                        var emptyObjectMarker = sto.GameObject.AddComponent <EmptyObjectIdentifier>();
                        sto.GameObject.AddComponent <StoreMesh>();
                        emptyObjectMarker.IsDeserializing = true;
                        emptyObjectMarker.Id = sto.Name;
                        if (emptyObjectMarker.Id == Data.rootObject)
                        {
                            Debug.Log("Set the root object on an empty");
                        }
                        flaggedObjects.Add(emptyObjectMarker);
                    }
                    else
                    {
                        var pf     = LevelSerializer.AllPrefabs[sto.ClassId];
                        var cancel = false;
                        CreateGameObject(pf, ref cancel);
                        if (cancel)
                        {
                            Debug.LogWarning("Cancelled");
                            continue;
                        }
                        var uis = pf.GetComponentsInChildren <UniqueIdentifier>();
                        foreach (var ui in uis)
                        {
                            ui.IsDeserializing = true;
                        }
                        sto.GameObject = Instantiate(pf, position, Quaternion.identity) as GameObject;
                        sto.GameObject.GetComponent <UniqueIdentifier>().Id = sto.Name;
                        if (sto.GameObject.GetComponent <UniqueIdentifier>().Id == Data.rootObject)
                        {
                            Debug.Log("Set the root object on a prefab");
                        }
                        foreach (var ui in uis)
                        {
                            ui.IsDeserializing = false;
                        }
                        flaggedObjects.AddRange(sto.GameObject.GetComponentsInChildren <UniqueIdentifier>());
                    }

                    position += Vector3.right * 50;
                    sto.GameObject.GetComponent <UniqueIdentifier>().Id = sto.Name;
                    sto.GameObject.name = sto.GameObjectName;
                    if (sto.ChildIds.Count > 0)
                    {
                        var list = sto.GameObject.GetComponentsInChildren <UniqueIdentifier>().ToList();
                        for (var i = 0; i < list.Count && i < sto.ChildIds.Count; i++)
                        {
                            list[i].Id = sto.ChildIds[i];
                        }
                    }
                    if (sto.Children.Count > 0)
                    {
                        var list = LevelSerializer.GetComponentsInChildrenWithClause(sto.GameObject);
                        _indexDictionary.Clear();
                        foreach (var c in list)
                        {
                            if (!sto.Children.ContainsKey(c.ClassId))
                            {
                                continue;
                            }
                            if (!_indexDictionary.ContainsKey(c.ClassId))
                            {
                                _indexDictionary[c.ClassId] = 0;
                            }
                            c.Id = sto.Children[c.ClassId][_indexDictionary[c.ClassId]];
                            _indexDictionary[c.ClassId] = _indexDictionary[c.ClassId] + 1;
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                    Debug.LogWarning("Problem creating an object " + sto.GameObjectName + " with classID " + sto.ClassId + " " + e);
                }
            }
        }
        var loadedGameObjects = new HashSet <GameObject>();

        LevelSerializer.RaiseProgress("Initializing", 0.75f);

        if (Data != null)
        {
            foreach (var so in Data.StoredObjectNames)
            {
                var go = UniqueIdentifier.GetByName(so.Name);
                if (go != null)
                {
                    loadedGameObjects.Add(go);
                    if (so.Components != null && so.Components.Count > 0)
                    {
                        var all = go.GetComponents <Component>().Where(c => !typeof(UniqueIdentifier).IsAssignableFrom(c.GetType())).ToList();
                        foreach (var comp in all)
                        {
                            if (!so.Components.ContainsKey(comp.GetType().FullName))
                            {
                                if (Application.isPlaying)
                                {
                                    Destroy(comp);
                                }
                                else
                                {
                                    DestroyImmediate(comp);
                                }
                            }
                        }
                    }
                    SetActive(go, so.Active);
                    if (so.setExtraData)
                    {
                        go.layer = so.layer;
                        go.tag   = so.tag;
                    }
                }
                else
                {
                    Debug.LogError("Could not find " + so.GameObjectName + " " + so.Name);
                }
            }
        }

        LevelSerializer.RaiseProgress("Initializing", 0.85f);

        if (Data != null && rootObject != null)
        {
            if (UniqueIdentifier.GetByName(Data.rootObject) == null)
            {
                Debug.Log("No root object has been configured");
            }
        }

        foreach (var go in Data.StoredObjectNames.Where(c => !string.IsNullOrEmpty(c.ParentName)))
        {
            var parent = UniqueIdentifier.GetByName(go.ParentName);
            var item   = UniqueIdentifier.GetByName(go.Name);
            if (item != null && parent != null)
            {
                item.SetParent(parent);
            }
        }

        LevelSerializer.RaiseProgress("Initializing", 1f);

        var currentProgress = 0;

        UnitySerializer.FinalProcess process;

        if (Data != null)
        {
            using (new UnitySerializer.SerializationSplitScope())
            {
                using (new UnitySerializer.SerializationScope())
                {
                    //Now we restore the data for the items
                    foreach (var item in
                             Data.StoredItems.GroupBy(i => i.Name,
                                                      (name, cps) => new
                    {
                        Name = name,
                        Components = cps.Where(cp => cp.Name == name).GroupBy(cp => cp.Type,
                                                                              (type, components) => new
                        {
                            Type = type,
                            List = components.ToList()
                        }).ToList()
                    }))
                    {
                        Debug.LogFormat("\n*****************\n{0}\n********START**********\n", item.Name);
                        var go = UniqueIdentifier.GetByName(item.Name);
                        if (go == null)
                        {
                            Debug.LogWarning(item.Name + " was null");
                            continue;
                        }

                        foreach (var cp in item.Components)
                        {
                            try
                            {
                                LevelSerializer.RaiseProgress("Loading", (float)++currentProgress / (float)Data.StoredItems.Count);
                                var type = UnitySerializer.GetTypeEx(cp.Type);
                                if (type == null)
                                {
                                    continue;
                                }
                                Last = go;
                                var cancel = false;
                                LoadData(go, ref cancel);
                                LoadComponent(go, type.Name, ref cancel);
                                if (cancel)
                                {
                                    continue;
                                }

                                Debug.LogFormat("<{0}>\n", type.FullName);

                                var list = go.GetComponents(type).Where(c => c.GetType() == type).ToList();
                                //Make sure the lists are the same length
                                while (list.Count > cp.List.Count)
                                {
                                    DestroyImmediate(list.Last());
                                    list.Remove(list.Last());
                                }
                                if (type == typeof(NavMeshAgent))
                                {
                                    var    cp1     = cp;
                                    var    item1   = item;
                                    Action perform = () =>
                                    {
                                        var comp  = cp1;
                                        var tp    = type;
                                        var tname = item1.Name;
                                        UnitySerializer.AddFinalAction(() =>
                                        {
                                            var g     = UniqueIdentifier.GetByName(tname);
                                            var nlist = g.GetComponents(tp).Where(c => c.GetType() == tp).ToList();
                                            while (nlist.Count < comp.List.Count)
                                            {
                                                try
                                                {
                                                    nlist.Add(g.AddComponent(tp));
                                                }
                                                catch
                                                {
                                                }
                                            }
                                            list = list.Where(l => l != null).ToList();
                                            //Now deserialize the items back in
                                            for (var i = 0; i < nlist.Count; i++)
                                            {
                                                if (LevelSerializer.CustomSerializers.ContainsKey(tp))
                                                {
                                                    LevelSerializer.CustomSerializers[tp].Deserialize((byte[])comp.List[i].Data, nlist[i]);
                                                }
                                                else
                                                {
                                                    UnitySerializer.DeserializeInto(comp.List[i].Data, nlist[i]);
                                                }
                                                LoadedComponent(nlist[i]);
                                            }
                                        });
                                    };
                                    perform();
                                }
                                else
                                {
                                    while (list.Count < cp.List.Count)
                                    {
                                        try
                                        {
                                            Debug.Log("Adding component of type " + type.ToString());
                                            // Try to resolve [RequireComponent] attributes by iteratively adding the components that
                                            // don't have any requirements first
                                            var requirements = new List <Type>()
                                            {
                                                type
                                            };
                                            bool updated = false;
                                            do
                                            {
                                                int before = requirements.Count();
                                                var r      = requirements.SelectMany(it => it.GetCustomAttributes(typeof(RequireComponent), true).
                                                                                     Select(itm => new[] { ((RequireComponent)itm).m_Type0, ((RequireComponent)itm).m_Type1, ((RequireComponent)itm).m_Type2 }).SelectMany(itm => itm).Where(itm => itm != null).Distinct()).ToList();

                                                requirements.AddRange(r.Where(a => !requirements.Contains(a)));
                                                updated = before != requirements.Count();
                                            } while (updated);
                                            requirements.RemoveAt(0);

                                            foreach (var req in requirements)
                                            {
                                                go.AddComponent(UnitySerializer.GetTypeEx(item.Components.FirstOrDefault(a => req.IsAssignableFrom(UnitySerializer.GetTypeEx(a.Type))).Type));
                                            }

                                            list.Add(go.AddComponent(type));
                                        }
                                        catch { }
                                    }
                                    list = list.Where(l => l != null).ToList();
                                    //Now deserialize the items back in
                                    for (var i = 0; i < list.Count; i++)
                                    {
                                        Debug.Log(string.Format("Deserializing {0} for {1}", type.Name, go.GetFullName()));
                                        if (LevelSerializer.CustomSerializers.ContainsKey(type))
                                        {
                                            LevelSerializer.CustomSerializers[type].Deserialize(cp.List[i].Data, list[i]);
                                        }
                                        else
                                        {
                                            UnitySerializer.DeserializeInto(cp.List[i].Data, list[i]);
                                        }
                                        LoadedComponent(list[i]);
                                    }
                                }
                                Debug.LogFormat("</{0}>", type.FullName);
                            }
                            catch (Exception e)
                            {
                                Debug.LogWarning("Problem deserializing " + cp.Type + " for " + go.name + " " + e.ToString());
                            }
                        }
                        Debug.LogFormat("\n*****************\n{0}\n********END**********\n\n", item.Name);
                    }
                    process = UnitySerializer.TakeOwnershipOfFinalization();
                }

                UnitySerializer.RunDeferredActions(process);

                if (LevelSerializer.ShouldCollect && timeScale == 0)
                {
                    Resources.UnloadUnusedAssets();
                    GC.Collect();
                }

                PluginsHelper.Add(Last);

                UnitySerializer.InformDeserializedObjects(process);

                //Tell the world that the level has been loaded
                if (Data != null && Data.rootObject != null)
                {
                    rootObject = UniqueIdentifier.GetByName(Data.rootObject);
                }
                else
                {
                    rootObject = null;
                }

                if (rootObject == null && Data.rootObject != null)
                {
                    Debug.LogError("Could not find the root object");
                    Debug.Log(Data.rootObject + " not found " + (!Data.StoredObjectNames.Any(n => n.Name == Data.rootObject) ? "not in the stored names" : "was in the stored names"));
                }

                //Flag that we aren't deserializing
                foreach (var obj in flaggedObjects)
                {
                    obj.IsDeserializing = false;
                    obj.SendMessage("OnDeserialized", SendMessageOptions.DontRequireReceiver);
                }

                LevelSerializer.IsDeserializing = false;
                _loading = false;
                RoomManager.loadingRoom = false;
                whenCompleted(rootObject, loadedGameObjects.ToList());

                if (Application.isEditor)
                {
                    Last.hideFlags = HideFlags.HideAndDontSave;
                    Last.GetComponent <MeshRenderer>().enabled = false;
                }

                //Get rid of the current object that is holding this level loader, it was
                //created solely for the purpose of running this script
                if (Application.isPlaying)
                {
                    Destroy(gameObject, 0.1f);
                }
                else
                {
                    DestroyImmediate(gameObject);
                }
            }
        }
    }