Esempio n. 1
0
        /// <summary>
        /// Starts downloading and importing the given asset (in the background). When done, the asset will
        /// be saved to the user's Assets folder.
        /// </summary>
        /// <param name="asset">The asset to download and import.</param>
        /// <param name="ptAssetLocalPath">Path to the PtAsset that should be created (or replaced).</param>
        /// <param name="options">Import options.</param>
        public void StartDownloadAndImport(PolyAsset asset, string ptAssetLocalPath, EditTimeImportOptions options)
        {
            if (!assetsBeingDownloaded.Add(asset))
            {
                return;
            }
            PtDebug.LogFormat("ABM: starting to fetch asset {0} ({1}) -> {2}", asset.name, asset.displayName,
                              ptAssetLocalPath);

            // Prefer glTF1 to glTF2.
            // It used to be that no Poly assets had both formats, so the ordering did not matter.
            // Blocks assets now have both glTF1 and glTF2. PT does not understand the glTF2 version,
            // so the ordering matters a great deal.
            PolyFormat glTF2format = asset.GetFormatIfExists(PolyFormatType.GLTF_2);
            PolyFormat glTFformat  = asset.GetFormatIfExists(PolyFormatType.GLTF);

            PolyMainInternal.FetchProgressCallback progressCallback = (PolyAsset assetBeingFetched, float progress) => {
                EditorUtility.DisplayProgressBar(DOWNLOAD_PROGRESS_TITLE, DOWNLOAD_PROGRESS_TEXT, progress);
            };

            if (glTFformat != null)
            {
                EditorUtility.DisplayProgressBar(DOWNLOAD_PROGRESS_TITLE, DOWNLOAD_PROGRESS_TEXT, 0.0f);
                PolyMainInternal.Instance.FetchFormatFiles(asset, PolyFormatType.GLTF,
                                                           (PolyAsset resultAsset, PolyStatus status) => {
                    EditorUtility.ClearProgressBar();
                    OnFetchFinished(status, resultAsset, /*isGltf2*/ false, ptAssetLocalPath, options);
                }, progressCallback);
            }
            else if (glTF2format != null)
            {
                EditorUtility.DisplayProgressBar(DOWNLOAD_PROGRESS_TITLE, DOWNLOAD_PROGRESS_TEXT, 0.0f);
                PolyMainInternal.Instance.FetchFormatFiles(asset, PolyFormatType.GLTF_2,
                                                           (PolyAsset resultAsset, PolyStatus status) => {
                    EditorUtility.ClearProgressBar();
                    OnFetchFinished(status, resultAsset, /*isGltf2*/ true, ptAssetLocalPath, options);
                }, progressCallback);
            }
            else
            {
                Debug.LogError("Asset not in GLTF_2 or GLTF format. Can't import.");
                PtAnalytics.SendEvent(PtAnalytics.Action.IMPORT_FAILED, "Unsupported format");
            }
        }
Esempio n. 2
0
        public void Import(PolyAsset asset, PolyImportOptions options, PolyApi.ImportCallback callback = null)
        {
            PolyFormat gltfFormat  = asset.GetFormatIfExists(PolyFormatType.GLTF);
            PolyFormat gltf2Format = asset.GetFormatIfExists(PolyFormatType.GLTF_2);

            if (gltf2Format != null && gltfFormat == null)
            {
                FetchAndImportFormat(asset, gltf2Format, options, callback);
            }
            else if (gltfFormat != null)
            {
                FetchAndImportFormat(asset, gltfFormat, options, callback);
            }
            else
            {
                callback(asset, new PolyStatusOr <PolyImportResult>(
                             PolyStatus.Error("Neither glTF or glTF_2 format was present in asset")));
            }
        }
Esempio n. 3
0
        private void OnFetchFinished(PolyStatus status, PolyAsset asset, bool isGltf2,
                                     string ptAssetLocalPath, EditTimeImportOptions options)
        {
            if (!status.ok)
            {
                Debug.LogErrorFormat("Error fetching asset {0} ({1}): {2}", asset.name, asset.displayName, status);
                EditorUtility.DisplayDialog("Download Error",
                                            string.Format("*** Error downloading asset '{0}'. Try again later.", asset.displayName), "OK");
                PtAnalytics.SendEvent(PtAnalytics.Action.IMPORT_FAILED, "Asset fetch failed");
                return;
            }

            string baseName, downloadLocalPath;

            if (!PrepareDownload(asset, out baseName, out downloadLocalPath))
            {
                return;
            }

            string absPath = PtUtils.ToAbsolutePath(downloadLocalPath);

            string extension = isGltf2 ? ".gltf2" : ".gltf";
            string fileName  = baseName + extension;

            // We have to place an import request so that PolyImporter does the right thing when it sees the new file.
            PolyImporter.AddImportRequest(new PolyImporter.ImportRequest(
                                              downloadLocalPath + "/" + fileName, ptAssetLocalPath, options, asset));

            // Now unpackage it. GltfProcessor will pick it up automatically.
            UnpackPackageToFolder(isGltf2 ? asset.GetFormatIfExists(PolyFormatType.GLTF_2) :
                                  asset.GetFormatIfExists(PolyFormatType.GLTF), absPath, fileName);

            PtDebug.LogFormat("ABM: Successfully downloaded {0} to {1}", asset, absPath);
            AssetDatabase.Refresh();
            if (null != refreshCallback)
            {
                refreshCallback();
            }
        }
Esempio n. 4
0
        public void FetchFormatFiles(PolyAsset asset, PolyFormatType formatType,
                                     PolyApi.FetchFormatFilesCallback completionCallback, FetchProgressCallback progressCallback = null)
        {
            PolyUtils.AssertNotNull(asset, "Asset can't be null.");
            PolyUtils.AssertNotNull(formatType, "formatType can't be null.");
            PolyFormat packageToFetch = asset.GetFormatIfExists(formatType);

            if (packageToFetch == null)
            {
                if (completionCallback != null)
                {
                    completionCallback(asset, PolyStatus.Error("Format type not present in asset"));
                }
                return;
            }

            PolyUtils.AssertNotNull(packageToFetch.root, "packageToFetch.root can't be null.");
            PolyUtils.AssertNotNull(packageToFetch.root.url, "packageToFetch.root.url can't be null.");
            PolyUtils.AssertNotNull(packageToFetch.resources, "packageToFetch.resources can't be null.");

            string accessToken = GetAccessToken();

            FetchOperationState state = new FetchOperationState();

            state.asset = asset;
            state.completionCallback  = completionCallback;
            state.progressCallback    = progressCallback;
            state.packageBeingFetched = packageToFetch;

            // Indicates how many files are pending download (1 for main file + 1 for each resource).
            state.totalFiles = state.pendingFiles = 1 + packageToFetch.resources.Count;

            // Note that the callbacks are asynchronous so they may complete in any order.  What we do know is that they
            // will all be called on the main thread, so they won't be called concurrently.

            long maxCacheAge = asset.IsMutable ? MUTABLE_ASSET_MAX_CACHE_AGE : IMMUTABLE_ASSET_MAX_CACHE_AGE;

            PolyClientUtils.GetRawFileBytes(packageToFetch.root.url, accessToken, maxCacheAge,
                                            (PolyStatus status, byte[] data) => { ProcessFileFetchResult(state, ROOT_FILE_INDEX, status, data); });

            for (int i = 0; i < packageToFetch.resources.Count; i++)
            {
                int thisIndex = i; // copy of variable, for closure below.
                PolyClientUtils.GetRawFileBytes(packageToFetch.resources[i].url, accessToken, maxCacheAge,
                                                (status, data) => { ProcessFileFetchResult(state, thisIndex, status, data); });
            }
        }
Esempio n. 5
0
        public void Visit(PolyVoosAsset asset)
        {
            string assetName = asset.assetId;
            string uri       = asset.GetUri();

            PolyApi.GetAsset(assetName, maybeAsset =>
            {
                if (MaybeLogError(assetName, maybeAsset))
                {
                    cache.CreateCacheEntry(uri, GameObject.CreatePrimitive(PrimitiveType.Cube), null);
                    return;
                }

                PolyAsset polyAsset = maybeAsset.Value;

                // We need both the asset and the thumbnail to consider it "downloaded".
                // We'll download them in parallel, and whichever one finishes second
                // will call SetCacheEntry.
                GameObject assetObject = null;
                Texture2D thumbnail    = null;

                PolyApi.FetchThumbnail(polyAsset, (_, maybeImported) =>
                {
                    if (MaybeLogError(assetName, maybeImported))
                    {
                        return;
                    }
                    thumbnail = polyAsset.thumbnailTexture;

                    // If we finished first, don't SetCacheEntry yet.
                    if (assetObject != null)
                    {
                        // Ok, both resources are done. Report completion!
                        // Set the cache (and flush the wait list)
                        cache.CreateCacheEntry(uri, assetObject, thumbnail);
                    }
                });

                System.Action <GameObject> onAssetImported = importedGameObject =>
                {
                    cache.downloadedPolyAssets.Add(polyAsset);

                    assetObject      = importedGameObject;
                    assetObject.name = assetName;
                    PrepareImportedModel(assetObject, polyAsset.description);

                    // If we finished first, don't SetCacheEntry yet.
                    if (thumbnail != null)
                    {
                        // Ok, both resources are done. Report completion!
                        // Set the cache (and flush the wait list)
                        cache.CreateCacheEntry(uri, assetObject, thumbnail);
                    }
                };

                var objFormat = polyAsset.GetFormatIfExists(PolyFormatType.OBJ);
                var fbx       = polyAsset.GetFormatIfExists(PolyFormatType.FBX);

#if USE_TRILIB
                // Blocks models, like the pug, have both GLTFs and FBX's. But, TRILIB
                // doesn't seem to load Blocks FBX well, so don't do it. However, it's
                // not trivial to detect Blocks models. So our current heuristic is
                // going to simply be, only load the FBX if it has FBX but NOT OBJ. At
                // least as of 20190325, actual FBX uploads don't have OBJs. In the
                // future, we can even peek at the GLTF and see if it was generated by
                // Blocks.
                if (objFormat == null && fbx != null)
                {
                    string tempDir = Util.CreateTempDirectory();

                    Dictionary <string, string> url2path = new Dictionary <string, string>();
                    foreach (var file in fbx.resources)
                    {
                        string localPath   = System.IO.Path.Combine(tempDir, file.relativePath);
                        url2path[file.url] = localPath;
                    }

                    // The root
                    string rootPath        = System.IO.Path.Combine(tempDir, fbx.root.relativePath);
                    url2path[fbx.root.url] = rootPath;

                    Util.DownloadFilesToDisk(url2path,
                                             () =>
                    {
                        // All done!
                        using (var loader = new TriLib.AssetLoaderAsync())
                        {
                            TriLib.AssetLoaderOptions opts = GetTriLibOpts();
                            loader.LoadFromFileWithTextures(rootPath, opts, null,
                                                            obj =>
                            {
                                System.IO.Directory.Delete(tempDir, true);
                                onAssetImported(obj);
                            });
                        }
                    },
                                             errors =>
                    {
                        System.IO.Directory.Delete(tempDir, true);
                        Debug.LogError($"Could not download Poly FBX for asset ID {assetName}. Errors: {string.Join("\n", errors)}");
                        return;
                    });
                }
                else
#endif
                {
                    PolyApi.Import(polyAsset, cache.polyImportOptions, (_, maybeImported) =>
                    {
                        if (MaybeLogError(assetName, maybeImported))
                        {
                            return;
                        }
                        onAssetImported(maybeImported.Value.gameObject);
                    });
                }
            });
        }