Beispiel #1
0
        public IEnumerator <object> NextPage(List <PolySceneFileInfo> files)
        {
            string uri = m_PageToken == null ? m_Uri
                : String.Format("{0}&page_token={1}", m_Uri, m_PageToken);

            WebRequest request = new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET);

            using (var cr = request.SendAsync().AsIeNull())
            {
                while (!request.Done)
                {
                    try
                    {
                        cr.MoveNext();
                    }
                    catch (VrAssetServiceException e)
                    {
                        e.UserFriendly = m_ErrorMessage;
                        throw;
                    }
                    yield return(cr.Current);
                }
            }

            Future <JObject> f = new Future <JObject>(() => JObject.Parse(request.Result));
            JObject          json;

            while (!f.TryGetResult(out json))
            {
                yield return(null);
            }

            var assets = json["assets"];

            if (assets != null)
            {
                foreach (var asset in assets)
                {
                    var info = new PolySceneFileInfo(asset);
                    info.Author = asset["displayName"].ToString();
                    ;
                    files.Add(info);
                }
            }
            JToken jPageToken = json["nextPageToken"];

            m_PageToken = jPageToken != null?jPageToken.ToString() : null;
        }
Beispiel #2
0
        // Download tilt files and thumbnails (that we don't already have)
        private IEnumerator DownloadFilesCoroutine(List <PolySketch> sketches)
        {
            bool notifyOnError = true;

            void NotifyCreateError(PolySceneFileInfo sceneFileInfo, string type, Exception ex)
            {
                string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}.";

                ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError);
                notifyOnError = false;
                Debug.LogException(ex);
                Debug.LogError($"{sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}");
            }

            void NotifyWriteError(PolySceneFileInfo sceneFileInfo, string type, UnityWebRequest www)
            {
                string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}.\n" +
                               "Out of disk space?";

                ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError);
                notifyOnError = false;
                Debug.LogError($"{www.error} {sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}");
            }

            byte[] downloadBuffer = new byte[kDownloadBufferSize];
            // Load the icons first, then the thumbnails
            foreach (PolySketch sketch in sketches)
            {
                PolySceneFileInfo sceneFileInfo = sketch.PolySceneFileInfo;
                // TODO(b/36270116): Check filesizes when Poly can give it to us to detect incomplete downloads
                if (!sceneFileInfo.IconDownloaded)
                {
                    if (File.Exists(sceneFileInfo.IconPath))
                    {
                        sceneFileInfo.IconDownloaded = true;
                    }
                    else
                    {
                        using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.IconUrl))
                        {
                            DownloadHandlerFastFile downloadHandler;
                            try
                            {
                                downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.IconPath, downloadBuffer);
                            }
                            catch (Exception ex)
                            {
                                NotifyCreateError(sceneFileInfo, "icon", ex);
                                continue;
                            }
                            www.downloadHandler = downloadHandler;
                            yield return(www.SendWebRequest());

                            if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error))
                            {
                                NotifyWriteError(sceneFileInfo, "icon", www);
                            }
                            else
                            {
                                sceneFileInfo.IconDownloaded = true;
                            }
                        }
                    }
                }
                yield return(null);
            }

            foreach (PolySketch sketch in sketches)
            {
                PolySceneFileInfo sceneFileInfo = sketch.PolySceneFileInfo;
                if (!sceneFileInfo.TiltDownloaded)
                {
                    if (File.Exists(sceneFileInfo.TiltPath))
                    {
                        sceneFileInfo.TiltDownloaded = true;
                    }
                    else
                    {
                        using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.TiltFileUrl))
                        {
                            DownloadHandlerFastFile downloadHandler;
                            try
                            {
                                downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.TiltPath, downloadBuffer);
                            }
                            catch (Exception ex)
                            {
                                NotifyCreateError(sceneFileInfo, "sketch", ex);
                                continue;
                            }
                            www.downloadHandler = downloadHandler;
                            yield return(www.SendWebRequest());

                            if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error))
                            {
                                NotifyWriteError(sceneFileInfo, "sketch", www);
                            }
                            else
                            {
                                sceneFileInfo.TiltDownloaded = true;
                            }
                        }
                    }
                }
                yield return(null);
            }
            yield return(null);
        }
Beispiel #3
0
 public PolySketch(PolySceneFileInfo info)
 {
     m_FileInfo = info;
 }
Beispiel #4
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();
            }
        }