/// <summary>
 /// Copies built asset bundles to the StreamingAssets folder.
 /// </summary>
 public static void CopyToStreamingAssets()
 {
     if (!string.IsNullOrEmpty(DistDirectory))
     {
         try
         {
             string   srcDirectory = DistDirectory;
             string[] files        = Directory.GetFiles(srcDirectory);
             if (srcDirectory.StartsWith("./"))
             {
                 srcDirectory = srcDirectory.Substring(2);                         // makes entire string indifferent to absolute and relative paths
             }
             foreach (string sourceFilename in files)
             {
                 string destFileName = Builder.TARGET_IN_STREAMING_ASSETS + sourceFilename.Substring(sourceFilename.IndexOf(srcDirectory) + srcDirectory.Length);
                 ETUtils.CreateDirectoryForFile(destFileName);
                 File.Copy(sourceFilename, destFileName, true);
             }
         }
         catch (Exception e)
         {
             // TODO: introduce logger like in the Builder
             // - to replace all Console.Write*;
             // - to inform TeamCity about the error (otherwise throw an exception).
             Console.WriteLine("Caught exception, while copying files to StreamingAssets: " + e.ToString());
         }
         AssetDatabase.Refresh();                 // makes sure asset bundles would be included in the build
     }
     else
     {
         Console.WriteLine("WARNING. Can't copy artifacts, because nothing has been built by use of BuilderHelper.");
     }
 }
        /// <summary>
        /// Separate bundles into two folders: compressed and uncompressed
        /// </summary>
        public static void SeparateBundles()
        {
            if (!string.IsNullOrEmpty(DistDirectory))
            {
                try
                {
                    string   srcDirectory = DistDirectory;
                    string[] files        = Directory.GetFiles(srcDirectory);
                    if (srcDirectory.StartsWith("./"))
                    {
                        srcDirectory = srcDirectory.Substring(2); // makes entire string indifferent to absolute and relative paths
                    }

                    string destUnCompressedDir = srcDirectory + "/Uncompressed";

                    string destCompressedDir = srcDirectory + "/Compressed";

                    foreach (string sourceFilename in files)
                    {
                        string destFileName;
                        string srcFileName = Path.GetFileName(sourceFilename);
                        Console.WriteLine("Source file name = " + srcFileName);
                        if (Builder.uncompressedBundleList.Contains(srcFileName))
                        {
                            destFileName = Path.Combine(destUnCompressedDir, srcFileName);
                        }
                        else
                        {
                            destFileName = Path.Combine(destCompressedDir, srcFileName);
                        }

                        //index files are not in list, but they must exist in both folders.
                        if (srcFileName.StartsWith("index"))
                        {
                            string fn = Path.Combine(destUnCompressedDir, srcFileName);
                            ETUtils.CreateDirectoryForFile(fn);
                            File.Copy(sourceFilename, fn);
                        }

                        ETUtils.CreateDirectoryForFile(destFileName);
                        File.Move(sourceFilename, destFileName);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Caught exception, while copying files to StreamingAssets: " + e.Message);
                }
                AssetDatabase.Refresh(); // makes sure asset bundles would be included in the build
            }
            else
            {
                Console.WriteLine("WARNING. Can't copy artifacts, because nothing has been built by use of BuilderHelper.");
            }
        }
        // TODO: comment it: computes hash of the asset bundle based on the specified assets
        public static string ComputeAssetBundleHashDependingOnProvidedDistribution(Index index, Index.AssetBundle assetBundle)
        {
            Index.AssetBundle userAssetBundle = assetBundle;
            Index.AssetBundle realAssetBundle = null;
            foreach (Index.AssetBundle ab in index.m_assetBundles)
            {
                if (ab.m_filename.Equals(userAssetBundle.m_filename))
                {
                    realAssetBundle = ab;
                    break;
                }
            }
            Assertion.Check(realAssetBundle != null);             // SANITY CHECK

            // create a list contained user-defined assets (they could become just references)
            List <string> references = new List <string>();

            foreach (Index.AssetBundle.Asset asset in userAssetBundle.m_assets)
            {
                references.Add(asset.m_filename);
            }

            // now compute hash for the asset bundle
            string ret = "";

            foreach (Index.AssetBundle.Asset asset in realAssetBundle.m_assets)
            {
                string hash = File.Exists(asset.m_filename) ? ETUtils.CreateHashForAsset(asset.m_filename) : null;                 // hash of the content
                ret = ETUtils.HashXorHash(ret, hash);
            }
            foreach (string assetFilepath in references)
            {
                string hash = ETUtils.CreateHashForString(assetFilepath);                 // hash of explicit asset name
                ret = ETUtils.HashXorHash(ret, hash);
            }
            return(ret);            // return null to compute hashes with base (incorrent) algorithm
        }
 /// <summary>
 /// Cleans the StreamingAssets folder from generated asset bundles.
 /// </summary>
 public static void CleanStreamingAssets()
 {
     ETUtils.DeleteDirectory(Builder.TARGET_IN_STREAMING_ASSETS);
     ETUtils.CreateDirectory(Builder.TARGET_IN_STREAMING_ASSETS);
     AssetDatabase.Refresh();
 }
        /// <summary>
        /// Builds asset bundles.
        /// </summary>
        public static void Build(
            ref List <string> scenesToBuild,
            ref BuildTarget buildTarget,
            ref BuildOptions buildOptions,
            IBuildConfig buildConfig,
            string originalIndexFilename,
            string producedIndexFilename,
            bool?compressAssetBundles)
        {
            // set output folder
            Assertion.Check(buildConfig != null, "BuildConfig must be specified!");
            InitDistDirectory(buildConfig);

            // configure builder
            Index index = Builder.index;

            Builder.index = null;             // means, build all found indices
            if (!string.IsNullOrEmpty(originalIndexFilename))
            {
                bool    found   = false;
                Index[] indices = Builder.GetIndexInstances();
                Builder.index = index;                 // restores original value
                foreach (Index i in indices)
                {
                    if (i.m_filename.ToLower().Equals(originalIndexFilename.ToLower()))
                    {
                        Builder.index = i;
                        found         = true;
                        break;
                    }
                }
                Assertion.Check(found, "Index \"{0}\" has not been found!", originalIndexFilename);
                if (!found)
                {
                    throw new NotSupportedException(string.Format("Index \"{0}\" has not been found. No asset bundles will be built.", originalIndexFilename));
                }
            }
            Index.m_overridenFilenameMask = producedIndexFilename;
            bool buildReadableIndex = Builder.BuildReadableIndex;

            Builder.BuildReadableIndex = ETUtils.IsUnityInBatchMode();             // means, on buildmachines only
            Builder.AssetBundlesCompressionOverriding overrideAssetBundlesCompression = Builder.OverrideAssetBundlesCompression;
            if ((compressAssetBundles != null) && compressAssetBundles.HasValue)
            {
                Builder.OverrideAssetBundlesCompression = compressAssetBundles.Value ? Builder.AssetBundlesCompressionOverriding.Compressed : Builder.AssetBundlesCompressionOverriding.Uncompressed;
            }
            else
            {
                Builder.OverrideAssetBundlesCompression = Builder.AssetBundlesCompressionOverriding.DoNotOverride;
            }

            // produce bundles
            UpdateScenes(ref scenesToBuild);
            Builder.BuildAssetBundles(DistDirectory, buildTarget, buildOptions);

            // restore builder
            Builder.index = index;
            Index.m_overridenFilenameMask           = null;
            Builder.BuildReadableIndex              = buildReadableIndex;
            Builder.OverrideAssetBundlesCompression = overrideAssetBundlesCompression;
        }
        // TODO: comment it: gets distribution (which assets in which bundles) in reality
        public static Index ReorganizeDistribution(Index index)
        {
            Dictionary <string, Index.AssetBundle> userAssetsToBundles = GetUserDistribution(index);
            Dictionary <string, Index.AssetBundle> realAssetsToBundles = GetRealDistribution(userAssetsToBundles);
            Dictionary <string, List <string> >    dist = new Dictionary <string, List <string> >();

            foreach (KeyValuePair <string, Index.AssetBundle> kvp in realAssetsToBundles)
            {
                if (!dist.ContainsKey(kvp.Value.m_filename))
                {
                    dist.Add(kvp.Value.m_filename, new List <string>());
                }
                dist[kvp.Value.m_filename].Add(kvp.Key);
            }
            index = Index.DuplicateInstance(index);
            HashSet <Index.AssetBundle>       checkedAssetBundles = new HashSet <Index.AssetBundle>();
            HashSet <Index.AssetBundle.Asset> checkedAssets       = new HashSet <Index.AssetBundle.Asset>();

            foreach (KeyValuePair <string, List <string> > kvp in dist)
            {
                Index.AssetBundle assetBundle = null;
                foreach (Index.AssetBundle ab in index.m_assetBundles)
                {
                    if (ab.m_filename.Equals(kvp.Key))
                    {
                        assetBundle = ab;
                        break;
                    }
                }
                Assertion.Check(assetBundle != null);
                if (assetBundle != null)
                {
                    foreach (string val in kvp.Value)
                    {
                        Index.AssetBundle.Asset asset = null;
                        foreach (Index.AssetBundle.Asset a in assetBundle.m_assets)
                        {
                            if (a.m_filename.Equals(val))
                            {
                                asset = a;
                                break;
                            }
                        }
                        if (asset == null)
                        {
                            asset            = new Index.AssetBundle.Asset();
                            asset.m_filename = val;
                            asset.m_guid     = AssetDatabase.AssetPathToGUID(asset.m_filename);
                            assetBundle.m_assets.Add(asset);
                        }
                        asset.m_hash = File.Exists(asset.m_filename) ? ETUtils.CreateHashForAsset(asset.m_filename) : null;
                        checkedAssets.Add(asset);
                    }
                    checkedAssetBundles.Add(assetBundle);
                }
            }
            foreach (Index.AssetBundle assetBundle in index.m_assetBundles)
            {
                if (checkedAssetBundles.Contains(assetBundle))
                {
                    for (int idx = assetBundle.m_assets.Count - 1; idx >= 0; --idx)
                    {
                        if (!checkedAssets.Contains(assetBundle.m_assets[idx]))
                        {
                            assetBundle.m_assets.RemoveAt(idx);
                        }
                    }
                }
                else
                {
                    assetBundle.m_assets.Clear();
                }
            }
            return(index);
        }