Пример #1
0
 public void Update()
 {
     if (m_future != null)
     {
         try
         {
             string[] results;
             if (m_future.TryGetResult(out results))
             {
                 Succeeded  = m_successTest == null ? false : m_successTest(results);
                 Output     = results;
                 FinishTime = DateTime.Now;
                 m_future   = null;
                 HasRun     = true;
                 if (Completed != null)
                 {
                     Completed(Succeeded);
                     Completed = null;
                 }
             }
         }
         catch (FutureFailed ex)
         {
             Output     = ex.Message.Split('\n');
             FinishTime = DateTime.Now;
             m_future   = null;
             Succeeded  = false;
             HasRun     = true;
         }
     }
 }
Пример #2
0
 private void ScanAndroidDevices()
 {
     if (m_deviceListFuture == null)
     {
         if ((DateTime.Now - m_timeOfLastDeviceScan).TotalSeconds > kSecondsBetweenDeviceScan &&
             !EditorApplication.isPlaying)
         {
             m_deviceListFuture = new Future <string[]>(() => RunAdb("devices"));
         }
     }
     else
     {
         string[] results;
         if (m_deviceListFuture.TryGetResult(out results))
         {
             m_androidDevices = results.Skip(1).Where(x => !string.IsNullOrEmpty(x.Trim()))
                                .Select(x => x.Split(' ', '\t')[0]).ToArray();
             if (m_androidDevices.Length != 0 && !m_androidDevices.Contains(m_selectedAndroid))
             {
                 m_selectedAndroid = m_androidDevices[0];
             }
             m_deviceListFuture = null;
             Repaint();
             m_timeOfLastDeviceScan = DateTime.Now;
         }
     }
 }
Пример #3
0
  /// Waits for the json data to be read on a background thread, and then executes a precache
  /// coroutine for each found asset.
  private IEnumerator<Null> PrecacheModelsCoroutine(SceneFileInfo sceneFileInfo, string reason) {
    var getIdsFuture = new Future<List<string>>(() => GetModelIds(sceneFileInfo));
    List<string> ids;
    while (true) {
      try {
        if (getIdsFuture.TryGetResult(out ids)) { break; }
      } catch (FutureFailed e) {
        throw new Exception($"While reading {sceneFileInfo}", e);
      }
      yield return null;
    }

    if (ids == null) { yield break; }
    List<IEnumerator<Null>> precacheCoroutines = new List<IEnumerator<Null>>();
    // Only trigger off one precache routine per frame.
    foreach (string id in ids) {
      if (m_ModelsByAssetId.ContainsKey(id)) {
        // Already cached
        continue;
      }
      if (! FileUtils.InitializeDirectory(GetCacheDirectoryForAsset(id))) {
        continue;
      }
      precacheCoroutines.Add(PrecacheCoroutine(
          VrAssetService.m_Instance.GetAsset(id, VrAssetFormat.GLTF2, reason)));
      yield return null;
    }

    var cr = CoroutineUtil.CompleteAllCoroutines(precacheCoroutines);
    while (cr.MoveNext()) {
      yield return cr.Current;
    }
  }
Пример #4
0
        static T Force <T>(Future <T> f) where T : class
        {
            T value;

            while (!f.TryGetResult(out value))
            {
            }
            return(value);
        }
Пример #5
0
        // Helper for State.Looking
        // Updates:
        // - m_CapturesFuture
        // - m_SelectNextCaptureTimer
        // - m_AudioCapture
        // On failure, m_AudioCapture is unchanged (still null).
        void SelectNextCapture()
        {
            // So we don't have to worry about calling Dispose() on these things
            Debug.Assert(m_AudioCapture == null);
            Debug.Assert(m_FinalSource == null);

            Queue <WasapiCapture> captures;

            if (m_CapturesFuture == null)
            {
                m_CapturesFuture     = new Future <Queue <WasapiCapture> >(GetAudioCaptures, CleanupAudioCaptures);
                m_nCapturesFound     = -1;
                m_SearchFoundNoAudio = false;
            }

            if (!m_CapturesFuture.TryGetResult(out captures))
            {
                // Future not ready yet.  Retry again next frame; it should complete quickly.
                m_SelectNextCaptureTimer = 0;
                return;
            }

            // The count decrements as we consume, but m_nCapturesFound will be the high water mark
            m_nCapturesFound = Mathf.Max(m_nCapturesFound, captures.Count);

            if (m_nCapturesFound == 0)
            {
                // Future is ready, but it says there are no sources
                ControllerConsoleScript.m_Instance.AddNewLine("No audio sources available.");
                m_SearchFoundNoAudio = true;
                StopFuture(); // Re-query for captures after timeout
                m_SelectNextCaptureTimer = m_SelectDeviceTimeoutDuration;
                return;
            }

            if (captures.Count == 0)
            {
                // Future is ready, and there were sources, but we've tried them all
                StopFuture(); // Re-query for captures next frame
                m_SelectNextCaptureTimer = 0;
                return;
            }

            var    capture = captures.Dequeue();
            string line    = string.Format(
                "Trying {1}/{2}: {0}", capture.Device.FriendlyName,
                m_nCapturesFound - captures.Count, m_nCapturesFound);

            ControllerConsoleScript.m_Instance.AddNewLine(line);
            m_AudioCapture           = capture;
            m_SampleRate             = m_AudioCapture.WaveFormat.SampleRate;
            m_FriendlyName           = m_AudioCapture.Device.FriendlyName;
            m_SelectNextCaptureTimer = m_SelectDeviceTimeoutDuration;
        }
Пример #6
0
            private IEnumerable RequestLoadIconAndMetadataCoroutineThreaded()
            {
                var thumbFuture = new Future <byte[]>(() => ReadThumbnail(m_FileInfo));

                byte[] data;
                while (!thumbFuture.TryGetResult(out data))
                {
                    yield return(null);
                }

                if (data != null && data.Length > 0)
                {
                    if (m_Icon == null)
                    {
                        m_Icon = new Texture2D(128, 128, TextureFormat.RGB24, true);
                    }
                    m_Icon.LoadImage(data);
                    m_Icon.Apply();
                }
                else
                {
                    // TODO: why is the icon missing/invalid? should we be noisier
                    // about invalid files? But RequestLoadIcon() doesn't have a
                    // way of indicating "not a tilt"
                }
                if (m_Authors == null)
                {
                    var            metadataFuture = new Future <SketchMetadata>(() => m_FileInfo.ReadMetadata());
                    SketchMetadata metadata;
                    while (!metadataFuture.TryGetResult(out metadata))
                    {
                        yield return(null);
                    }
                    if (metadata != null)
                    {
                        m_Authors = metadata.Authors;
                    }
                    else
                    {
                        if (SaveLoadScript.m_Instance.LastMetadataError != null)
                        {
                            ControllerConsoleScript.m_Instance.AddNewLine(
                                string.Format("Error detected in sketch '{0}'.\nTry re-saving.",
                                              m_FileInfo.HumanName));
                            Debug.LogWarning(string.Format("Error reading metadata for {0}.\n{1}",
                                                           m_FileInfo.FullPath, SaveLoadScript.m_Instance.LastMetadataError));
                        }
                    }
                }
                m_bMetadataValid = true;
            }
Пример #7
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;
        }
Пример #8
0
        // Delete any files that aren't referenced in m_Sketches (actually m_AssetIds)
        // Does this on a background thread so prevent hitches.
        private IEnumerator DeleteOldSketchesCoroutine()
        {
            if (m_CacheDir != null)
            {
                var task = new Future <bool>(() => {
                    var unknown = new DirectoryInfo(m_CacheDir).GetFiles().Where(
                        f => !m_AssetIds.ContainsKey(Path.GetFileNameWithoutExtension(f.Name)));
                    foreach (var f in unknown)
                    {
                        f.Delete();
                    }
                    return(true);
                });

                bool unused;
                while (!task.TryGetResult(out unused))
                {
                    yield return(null);
                }
            }
        }
Пример #9
0
        // Initiates the contact with Poly.
        public IEnumerator <Null> GetAssetCoroutine()
        {
            if (string.IsNullOrEmpty(App.Config.GoogleSecrets?.ApiKey))
            {
                IsCanceled = true;
                yield break;
            }
            m_Ready = false;

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

            using (var cr = request.SendAsync().AsIeNull())
            {
                while (!request.Done)
                {
                    try
                    {
                        cr.MoveNext();
                    }
                    catch (VrAssetServiceException e)
                    {
                        Debug.LogException(e);
                        IsCanceled = true;
                        yield break;
                    }
                    yield return(cr.Current);
                }
            }

            // Deserialize request string in to an Asset class.
            MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(request.Result));

            using (var jsonReader = new JsonTextReader(new StreamReader(memStream)))
            {
                Future <JObject> f = new Future <JObject>(() => JObject.Parse(request.Result));
                JObject          json;
                while (!f.TryGetResult(out json))
                {
                    yield return(null);
                }

                if (json.Count == 0)
                {
                    Debug.LogErrorFormat("Failed to deserialize response for {0}", m_URI);
                    yield break;
                }

                // Find the asset by looking through the format list for the specified type.
                VrAssetFormat requestedType = m_Asset.DesiredType;

                while (true)
                {
                    var format = json["formats"]?.FirstOrDefault(x =>
                                                                 x["formatType"]?.ToString() == requestedType.ToString());
                    if (format != null)
                    {
                        string internalRootFilePath = format["root"]?["relativePath"].ToString();
                        // If we successfully get a gltf2 format file, internally change the extension to
                        // "gltf2" so that the cache knows that it is a gltf2 file.
                        if (requestedType == VrAssetFormat.GLTF2)
                        {
                            internalRootFilePath = Path.ChangeExtension(internalRootFilePath, "gltf2");
                        }

                        // Get root element info.
                        m_Asset.SetRootElement(
                            internalRootFilePath,
                            format["root"]?["url"].ToString());

                        // Get all resource infos.  There may be zero.
                        foreach (var r in format["resources"])
                        {
                            string path = r["relativePath"].ToString();
                            m_Asset.AddResourceElement(path, r["url"].ToString());

                            // The root element should be the only gltf file.
                            Debug.Assert(!path.EndsWith(".gltf") && !path.EndsWith(".gltf2"),
                                         string.Format("Found extra gltf resource: {0}", path));
                        }
                        break;
                    }
                    else
                    {
                        // We asked for an asset in a format that it doesn't have.
                        // In some cases, we should look for a different format as backup.
                        if (requestedType == VrAssetFormat.GLTF2)
                        {
                            requestedType = VrAssetFormat.GLTF;
                        }
                        else
                        {
                            // In other cases, we should fail and get out.
                            Debug.LogErrorFormat("Can't download {0} in {1} format.", m_Asset.Id, m_Asset.DesiredType);
                            yield break;
                        }
                    }
                }
            }

            // Download root asset.
            request = new WebRequest(m_Asset.RootDataURL, App.GoogleIdentity);
            using (var cr = request.SendAsync().AsIeNull())
            {
                while (!request.Done)
                {
                    try
                    {
                        cr.MoveNext();
                    }
                    catch (VrAssetServiceException e)
                    {
                        Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}",
                                             m_Asset.Id, m_Asset.RootDataURL, e);
                        yield break;
                    }
                    yield return(cr.Current);
                }
            }
            m_Asset.CopyBytesToRootElement(request.ResultBytes);

            // Download all resource assets.
            foreach (var e in m_Asset.ResourceElements)
            {
                request = new WebRequest(e.dataURL, App.GoogleIdentity);
                using (var cr = request.SendAsync().AsIeNull())
                {
                    while (!request.Done)
                    {
                        try
                        {
                            cr.MoveNext();
                        }
                        catch (VrAssetServiceException ex)
                        {
                            Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}",
                                                 m_Asset.Id, m_Asset.RootDataURL, ex);
                            e.assetBytes = null;
                            yield break;
                        }
                        yield return(cr.Current);
                    }
                }
                e.assetBytes = request.ResultBytes;
            }

            m_Ready = true;
        }
Пример #10
0
            /// Returns:
            ///   bool - false if incomplete, true upon successful completion.
            ///   GameObject - caller should check output GameObject to determine success.
            ///   ImportMaterialCollector - non-null upon successful completion.
            /// Raises an exception on unsuccessful completion.
            public bool TryEndAsyncLoad(out GameObject root,
                                        out ImportMaterialCollector importMaterialCollector)
            {
                // Three things happen in this function.
                // 1: It waits to try and get the result of reading the model on a background thread
                // 2: It checks the rate limiter to make sure we don't have too many of these going on at once.
                // 3: It enumerates through, creating meshes for the model. These are time-limited so that
                //    it will stop if it has taken too long in a single frame.
                root = null;
                importMaterialCollector = null;
                if (m_meshEnumerator == null)
                {
                    IDisposable state;
                    if (!m_stateReader.TryGetResult(out state))
                    {
                        return(false);
                    }

                    IEnumerable <Null> enumerable;
                    m_root = DoUnityThreadWork(state, out enumerable, out m_ImportMaterialCollector);
                    // TODO: Possible bugs if DoUnityThreadWork ever did fail:
                    // We assume the invariant that (root == null) == (IsValid == false)
                    // We assume the invariant that m_ImportMaterialCollector != null
                    // We don't dispose the GameObject or the enumerable
                    // If the user calls TryEndAsyncLoad again we might try to call DoUnityThreadWork again
                    if (m_root == null)
                    {
                        return(false);
                    }
                    m_meshEnumerator = enumerable.GetEnumerator();
                    m_root.SetActive(false);
                }
                // Yield until the limiter unblocks.
                // Multiple calls to TryGetResult above are harmless.
                if (sm_Limiter.IsBlocked())
                {
                    return(false);
                }

                // Finish constructing the actual game object.
                Stopwatch stopwatch = new Stopwatch();

                stopwatch.Start();
                long numTicks = (long)((Stopwatch.Frequency * kMeshMsPerFrame) / 1000);

                while (true)
                {
                    if (!m_meshEnumerator.MoveNext())
                    {
                        m_root.SetActive(true);
                        root = m_root;
                        importMaterialCollector = m_ImportMaterialCollector;
                        stopwatch.Stop();
                        return(true);
                    }
                    if (stopwatch.ElapsedTicks > numTicks)
                    {
                        stopwatch.Stop();
                        return(false);
                    }
                }
            }
Пример #11
0
        public IEnumerator <Null> NextPage(List <PolyAssetCatalog.AssetDetails> files,
                                           string thumbnailSuffix)
        {
            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);
            }

            if (json.Count == 0)
            {
                yield break;
            }

            JToken lastAsset = null;
            var    assets    = json["assets"] ?? json["userAssets"];

            foreach (JToken possibleAsset in assets)
            {
                try
                {
                    // User assets are nested in an 'asset' node.
                    JToken asset = possibleAsset["asset"] ?? possibleAsset;
                    if (asset["visibility"].ToString() == "PRIVATE")
                    {
                        continue;
                    }

                    // We now don't filter the liked Poly objects, but we don't want to return liked Tilt Brush
                    // sketches so in this section we filter out anything with a Tilt file in it.
                    // Also, although currently all Poly objects have a GLTF representation we should probably
                    // not rely on that continuing, so we discard anything that doesn't have a GLTF (1)
                    // representation. We look for PGLTF and GLTF as for a lot of objects Poly is returning
                    // PGLTF without GLTF.
                    bool skipObject = false;
                    foreach (var format in asset["formats"])
                    {
                        var formatType = format["formatType"].ToString();
                        if (formatType == "TILT")
                        {
                            skipObject = true;
                            break;
                        }
                    }
                    if (skipObject)
                    {
                        continue;
                    }
                    lastAsset = asset;
                    string accountName = asset["authorName"]?.ToString() ?? "Unknown";
                    files.Add(new PolyAssetCatalog.AssetDetails(asset, accountName, thumbnailSuffix));
                }
                catch (NullReferenceException)
                {
                    UnityEngine.Debug.LogErrorFormat("Failed to load asset: {0}",
                                                     lastAsset == null ? "NULL" : lastAsset.ToString());
                }
                yield return(null);
            }

            JToken jPageToken = json["nextPageToken"];

            m_PageToken = jPageToken != null?jPageToken.ToString() : null;
        }