public int BakeFinish(OnFinishedUpdate onUpdate)
        {
            VertexBakerLib.Assert(this != null && !m_run, "BakeFinished called but bake is still in process");

            string outputPath = BakeData.DataPath;

            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            if (m_result != 0)
            {
                string error = VertexBakerLib.Instance.GetLastError();
                VertexBakerLib.LogError(error);
            }
            else if (!m_cancel && m_outBasis0[0] != IntPtr.Zero && m_outBasis1[0] != IntPtr.Zero && m_outBasis2[0] != IntPtr.Zero)
            {
                string bakeSetId = BakeData.Instance().GetBakeSettings().SelectedBakeSet.m_settingsId;

                BakeSets      bakeSets      = BakeData.Instance().GetBakeSets();
                MeshContainer meshContainer = BakeData.Instance().GetMeshContainer(bakeSetId);

                EditorUtility.SetDirty(meshContainer);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();

                AssetDatabase.StartAssetEditing();
                try
                {
                    int ptrOffset  = 0;
                    int meshOffset = 0;
                    for (int m = 0; m < m_meshes.Count; ++m)
                    {
                        int count      = m_vertCounts[m];
                        int floatCount = count * 3;

                        // the ID used to look up this mesh later
                        string objectId = "" + m_lightBakers[m].GetUniqueId();

                        m_lightBakers[m].m_currentContainer = meshContainer;


                        Mesh outputMesh = meshContainer.m_list.Find(delegate(Mesh mesh)
                        {
                            if (mesh != null)
                            {
                                return(mesh.name == bakeSetId + "_" + objectId);
                            }
                            return(false);
                        });

                        if (outputMesh == null)
                        {
                            if (m_lightBakers[m].VertexLighting != null)
                            {
                                // if we are here than the mesh name may have changed, try and remove the stale data
                                string oldName = m_lightBakers[m].VertexLighting.name;
                                Mesh   found   = meshContainer.m_list.Find(delegate(Mesh mesh)
                                {
                                    // remove the old reference
                                    if (mesh != null)
                                    {
                                        return(mesh.name == oldName);
                                    }
                                    // remove null mesh
                                    return(false);
                                });

                                if (found != null)
                                {
                                    GameObject.DestroyImmediate(found, true);
                                }
                            }

                            // if no mesh exists for this target create it here
                            outputMesh = new Mesh();

                            BakeData.Instance().AddToMeshContainer(meshContainer, outputMesh);

                            //meshContainer.m_list.Add(outputMesh);
                            //// add to the container asset
                            //string outputFileName = bakeSetId + "_lighting";
                            //AssetDatabase.AddObjectToAsset(outputMesh, outputPath + "/" + outputFileName + ".asset");
                        }

                        outputMesh.name = bakeSetId + "_" + objectId;

                        // HACK: Work around to make Unity happy. If vertices are not found the additional vertex stream fails
                        //outMeshes[m].vertices = m_meshes[m].sharedMesh.vertices;
                        outputMesh.vertices = m_meshes[m].sharedMesh.vertices;

                        // 3 floats per vector
                        float[] rawData0 = new float[floatCount];
                        float[] rawData1 = new float[floatCount];
                        float[] rawData2 = new float[floatCount];

                        // offset pointer to next mesh
                        IntPtr basis0 = new IntPtr(m_outBasis0[0].ToInt64() + ptrOffset * SIZE_FLOAT);
                        IntPtr basis1 = new IntPtr(m_outBasis1[0].ToInt64() + ptrOffset * SIZE_FLOAT);
                        IntPtr basis2 = new IntPtr(m_outBasis2[0].ToInt64() + ptrOffset * SIZE_FLOAT);
                        ptrOffset += floatCount;

                        // marshal data into float arrays
                        Marshal.Copy(basis0, rawData0, 0, floatCount);
                        Marshal.Copy(basis1, rawData1, 0, floatCount);
                        Marshal.Copy(basis2, rawData2, 0, floatCount);

                        // lists to hold output vectors
                        List <Color> colorList0 = new List <Color>();
                        colorList0.Resize(count, Color.black);
                        List <Vector3> colorList1 = new List <Vector3>();
                        colorList1.Resize(count, Vector3.zero);
                        List <Vector3> colorList2 = new List <Vector3>();
                        colorList2.Resize(count, Vector3.zero);

                        // copy float arrays into mesh data
                        for (int i = 0; i < count; ++i)
                        {
                            int idx = i * 3;
                            colorList0[i] = new Color(rawData0[idx], rawData0[idx + 1], rawData0[idx + 2], 1.0f);
                            colorList1[i] = new Vector3(rawData1[idx], rawData1[idx + 1], rawData1[idx + 2]);
                            colorList2[i] = new Vector3(rawData2[idx], rawData2[idx + 1], rawData2[idx + 2]);
                        }

                        // this offset is target uv sets 1, 2, and 3 for data destination
                        const int uvOffset = 1;

                        outputMesh.SetColors(colorList0);
                        outputMesh.SetUVs(uvOffset + 1, colorList1);
                        outputMesh.SetUVs(uvOffset + 2, colorList2);
                        //outputMesh.UploadMeshData(true);
                        meshOffset += count;

                        EditorUtility.SetDirty(meshContainer);
                        m_meshRenderers[m].additionalVertexStreams = outputMesh;
                        m_lightBakers[m].m_bakeSets     = bakeSets;
                        m_lightBakers[m].VertexLighting = outputMesh;
                        m_lightBakers[m].m_bakeId       = objectId;

                        EditorUtility.SetDirty(m_lightBakers[m]);

                        onUpdate("Uploading Mesh Data", m_meshCount / (float)m);
                    }

                    // remove any null slots
                    meshContainer.m_list.RemoveAll(delegate(Mesh m)
                    {
                        return(m == null);
                    });

                    // aggregate containers under one super container
                    int existingIdx = bakeSets.m_containers.FindIndex(delegate(MeshContainer mc) { return(mc.name == meshContainer.name); });
                    if (existingIdx != -1)
                    {
                        // replace existing entry
                        bakeSets.m_containers[existingIdx] = meshContainer;
                    }
                    else
                    {
                        bakeSets.m_containers.Add(meshContainer);
                    }

                    BakeSetsInspector.CleanupStaleReferences(bakeSets);
                    EditorUtility.SetDirty(bakeSets);
                    AssetDatabase.SaveAssets();
                }
                finally
                {
                    onUpdate("Uploading Mesh Data", 1f);
                    AssetDatabase.StopAssetEditing();
                }
            }
            else
            {
                VertexBakerLib.LogWarning("Bake completed successfully but there was no output data available");
            }

            // free data
            FreeContext(true);

            // since basis memory was allocated in one chunk
            // freeing this handle frees all basis memory
            VertexBakerLib.Instance.Free(m_outBasis0[0]);

            EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
            EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());

            VertexBakerLib.Log("Bake time: " + (DateTime.Now - m_bakeStart).TotalSeconds + " seconds");

            while (VertexBakerLib.Instance.GetErrorCount() > 0)
            {
                string err = VertexBakerLib.Instance.GetLastError();
                VertexBakerLib.LogError(err);
            }

            GC.Collect();

            return(m_result);
        }