Esempio n. 1
0
        private IEnumerator <Null> RefreshAssetSet(PolySetType type)
        {
            List <AssetDetails> models = new List <AssetDetails>();

            // When the list is empty, make it the actual list acted upon so that results start
            // showing up immediately.
            if (m_AssetSetByType[type].m_Models.Count == 0)
            {
                m_AssetSetByType[type].m_Models = models;
            }
            AssetLister lister = VrAssetService.m_Instance.ListAssets(type);

            while (lister.HasMore || models.Count == 0)
            {
                using (var cr = lister.NextPage(models, m_ThumbnailSuffix))
                {
                    while (true)
                    {
                        try
                        {
                            if (!cr.MoveNext())
                            {
                                break;
                            }
                        }
                        catch (VrAssetServiceException e)
                        {
                            ControllerConsoleScript.m_Instance.AddNewLine(e.Message);
                            Debug.LogException(e);
                            yield break;
                        }
                        yield return(cr.Current);
                    }
                }
                if (models.Count == 0)
                {
                    break;
                }
            }
            // As the assets may already have models loaded into them, just add any new models and
            // remove old ones.
            var newIds = new HashSet <string>(models.Select(m => m.AssetId));
            var oldIds = new HashSet <string>(m_AssetSetByType[type].m_Models.Select(m => m.AssetId));
            // These must be reified; if they are left as lazy IEnumerables, O(n^2) behavior results
            HashSet <string> toAdd    = SetMinus(newIds, oldIds);
            HashSet <string> toRemove = SetMinus(oldIds, newIds);

            m_AssetSetByType[type].m_Models.RemoveAll(m => toRemove.Contains(m.AssetId));
            m_AssetSetByType[type].m_Models.InsertRange(0, models.Where(m => toAdd.Contains(m.AssetId)));
            if (CatalogChanged != null)
            {
                CatalogChanged();
            }
        }
Esempio n. 2
0
        // Fetch asset metadata from server and populate m_Sketches
        private IEnumerator PopulateSketchesCoroutine()
        {
            // Replacement data structures that will be populated with incoming data.  These
            // temporary structures will be copied to the "live" structures in chunks, so
            // beware of modifications that may reference incomplete data.
            List <PolySketch> sketches = new List <PolySketch>();
            Dictionary <string, PolySketch> assetIds = new Dictionary <string, PolySketch>();

            bool fromEmpty       = m_AssetIds.Count == 0;
            int  loadSketchCount = 0;

            AssetLister lister             = null;
            List <PolySceneFileInfo> infos = new List <PolySceneFileInfo>();

            // If we don't have a connection to Poly and we're querying the Showcase, use
            // the json metadatas stored in resources, instead of trying to get them from Poly.
            if (VrAssetService.m_Instance.NoConnection && m_Type == SketchSetType.Curated)
            {
                TextAsset[] textAssets =
                    Resources.LoadAll <TextAsset>(SketchCatalog.kDefaultShowcaseSketchesFolder);
                for (int i = 0; i < textAssets.Length; ++i)
                {
                    JObject jo = JObject.Parse(textAssets[i].text);
                    infos.Add(new PolySceneFileInfo(jo));
                }
            }
            else
            {
                lister = m_AssetService.ListAssets(Type);
            }

            bool changed      = false;
            int  pagesFetched = 0;

            while (lister == null || lister.HasMore || assetIds.Count == 0)
            {
                if (sketches.Count >= 180)
                {
                    break; // Don't allow the sketchbook to become too big.
                }

                // lister will be null if we can't connect to Poly and we've pre-populated infos
                // with data from Resources.
                if (lister != null)
                {
                    using (var cr = lister.NextPage(infos))
                    {
                        while (true)
                        {
                            try
                            {
                                if (!cr.MoveNext())
                                {
                                    break;
                                }
                            }
                            catch (VrAssetServiceException e)
                            {
                                ControllerConsoleScript.m_Instance.AddNewLine(e.UserFriendly);
                                Debug.LogException(e);
                                yield break;
                            }
                            yield return(cr.Current);
                        }
                    }
                }
                if (infos.Count == 0)
                {
                    break;
                }
                if (m_CacheDir == null)
                {
                    yield break;
                }
                // Only cull the curated sketches.  If a user likes a sketch that's very high poly count,
                // there's no feedback to tell them why it didn't show up in their list.  b/123649719
                if (m_Type == SketchSetType.Curated)
                {
                    infos = infos.Where(x => x.GltfTriangleCount < m_MaximumSceneTriangles).ToList();
                }
                if (m_Type == SketchSetType.Curated && !assetIds.Keys.Contains(kIntroSketchAssetId))
                {
                    yield return(VrAssetService.m_Instance.InsertSketchInfo(
                                     kIntroSketchAssetId, kIntroSketchIndex, infos));
                }
                for (int i = 0; i < infos.Count; i++)
                {
                    PolySceneFileInfo info = infos[i];
                    PolySketch        sketch;
                    if (m_AssetIds.TryGetValue(info.AssetId, out sketch))
                    {
                        // We already have this sketch
                    }
                    else
                    {
                        sketch = new PolySketch(info);
                        sketch.m_DownloadIndex = loadSketchCount++;
                        // Set local paths
                        info.TiltPath = Path.Combine(m_CacheDir, String.Format("{0}.tilt", info.AssetId));
                        info.IconPath = Path.Combine(m_CacheDir, String.Format("{0}.png", info.AssetId));
                        changed       = true;
                    }
                    if (assetIds.ContainsKey(info.AssetId))
                    {
                        Debug.LogErrorFormat("VR Asset Service has returned two objects with asset id '{0}'.",
                                             info.AssetId);
                    }
                    else
                    {
                        sketches.Add(sketch);
                        assetIds.Add(info.AssetId, sketch);
                    }
                }
                infos.Clear();

                // Only download the files with every other page, otherwise the sketch pages change too often,
                // Which results in a bad user experience.
                if ((++pagesFetched & 1) == 0 || lister == null || !lister.HasMore)
                {
                    if (Type == SketchSetType.Curated)
                    {
                        sketches.Sort(CompareSketchesByTriangleCountAndDownloadIndex);
                    }

                    // If populating the set from new then show stuff as it comes in.
                    // (We don't have to worry about anything being removed)
                    if (fromEmpty)
                    {
                        yield return(DownloadFilesCoroutine(sketches));

                        RemoveFailedDownloads(sketches);
                        // Copying sketches to m_Sketches before sketches has completed populating is a bit
                        // dangerous, but as long as they're copied and then listeners are notified
                        // immediately afterward with OnChanged(), there data should be stable.
                        m_TotalCount = sketches.Count;
                        m_Sketches   = new List <PolySketch>(sketches);
                        m_AssetIds   = assetIds;
                        m_Ready      = true;
                        OnChanged();
                    }
                }
            }

            if (!fromEmpty)
            {
                // Find anything that was removed
                int removed = m_Sketches.Count(s => !assetIds.ContainsKey(s.PolySceneFileInfo.AssetId));
                if (removed > 0)
                {
                    changed = true;
                }

                // Download new files before we notify our listeners that we've got new stuff for them.
                if (changed)
                {
                    yield return(DownloadFilesCoroutine(sketches));

                    RemoveFailedDownloads(sketches);
                }

                // DeleteOldSketchesCoroutine relies on m_AssetIds being up to date, so set these before
                // we try to cull the herd.
                m_AssetIds = assetIds;
                if (changed)
                {
                    yield return(DeleteOldSketchesCoroutine());
                }

                // Set new data live
                m_TotalCount = sketches.Count;
                m_Sketches   = new List <PolySketch>(sketches);
                m_Ready      = true;
                if (changed)
                {
                    OnChanged();
                }
            }
            else
            {
                // On first run populate, take the time to clean out any cobwebs.
                // Note that this is particularly important for the curated sketches, which do not have
                // a periodic refresh, meaning old sketches will never been deleted in the other path.
                yield return(DeleteOldSketchesCoroutine());

                OnChanged();
            }
        }