internal static RequestHandle GetScene(this IUsesCloudStorage storageUser, CompanionProject project,
                                        CompanionResource resource, Action <bool, string> callback)
 {
     if (callback == null)
     {
         Debug.LogWarning("Callback is null in GetScene");
         return(default);
 internal static RequestHandle GetCloudResourceList(this IUsesCloudStorage storageUser, CompanionProject project,
                                                    string resourceFolder, Action <bool, ResourceList> callback)
 {
     if (callback == null)
     {
         Debug.LogWarning("Callback is null in GetCloudResourceList");
         return(default);
Пример #3
0
        public AssetBundleButton(CompanionResource resource, AssetBundleResource bundle, RuntimePlatform platform,
                                 UnityObject asset, IUsesCloudStorage storageUser)
        {
            clicked += OnClicked;

            if (asset == null)
            {
                SetEnabled(false);
            }

            m_Resource    = resource;
            m_Platform    = platform;
            m_Bundle      = bundle;
            m_Asset       = asset;
            m_StorageUser = storageUser;

            name = $"{resource.name} - {platform} bundle button";

            var state = State.NotUploaded;

            if (m_Bundle != null)
            {
                if (m_Bundle.Timestamp >= m_Resource.timestamp)
                {
                    state = State.Uploaded;
                }
                else
                {
                    state = CompanionResourceUI.IsPlatformInstalled(m_Platform) ? State.Update : State.Warn;
                }
            }

            SetState(state);
        }
 public void DeleteBundles(IUsesCloudStorage storageUser, Stack <RequestHandle> requests)
 {
     foreach (var kvp in m_BundleDictionary)
     {
         requests.Push(storageUser.CloudSaveAsync(kvp.Value.Key, string.Empty));
     }
 }
        internal static RequestHandle SavePrefab(this IUsesCloudStorage storageUser, CompanionProject project, string resourceFolder,
                                                 GameObject prefab, Action <bool, string> callback = null)
        {
            // Write to local storage in case cloud isn't reachable
            var prefabName = prefab.name;
            var path       = AssetDatabase.GetAssetPath(prefab);

            if (string.IsNullOrEmpty(path))
            {
                Debug.LogError("Cannot get path for " + prefab);
                return(default);
        static RequestHandle SaveMarker(this IUsesCloudStorage storageUser, CompanionProject project,
                                        string resourceFolder, string guid, Marker marker, Action <bool, string> callback)
        {
            var jsonText = SceneSerialization.ToJson(marker);

            WriteLocalMarker(project, resourceFolder, guid, jsonText);
            var key = GetMarkerKey(resourceFolder, guid);

            if (!project.linked)
            {
                callback?.Invoke(true, key);
                return(default);
        internal static void AddOrUpdateResource(this IUsesCloudStorage storageUser, CompanionProject project,
                                                 string resourceFolder, string key, string name, ResourceType type, long fileSize, bool hasBundle,
                                                 Stack <RequestHandle> requests, Action <bool, ResourceList> callback = null)
        {
            var localResourceList = GetLocalResourceList(project, resourceFolder) ?? new ResourceList();
            var resource          = localResourceList.AddOrUpdateResource(key, name, type, fileSize, hasBundle);

            WriteLocalResourceList(project, resourceFolder, localResourceList);

            void LocalOnlyUpdate(bool success, ResourceList resourceList)
            {
                resourceList = ResourceList.MergeResourceLists(localResourceList, resourceList);
                ResourceListChanged?.Invoke(false, resourceList);
                callback?.Invoke(success, resourceList);
            }

            if (!project.linked)
            {
                LocalOnlyUpdate(true, new ResourceList());
                return;
            }

            // Get the latest list to make sure we don't lose scenes in case of stale data
            requests.Push(storageUser.GetCloudResourceList(project, resourceFolder, (getListSuccess, cloudResourceList) =>
            {
                if (getListSuccess)
                {
                    cloudResourceList.AddOrOverwriteExistingResource(resource);
                    requests.Push(storageUser.WriteCloudResourceList(project, resourceFolder, cloudResourceList, writeListSuccess =>
                    {
                        if (writeListSuccess)
                        {
#if UNITY_EDITOR
                            CloudResourceListChanged?.Invoke(cloudResourceList);
#endif

                            WriteFallbackCloudResourceList(project, resourceFolder, cloudResourceList);
                            cloudResourceList = ResourceList.MergeResourceLists(localResourceList, cloudResourceList);
                            ResourceListChanged?.Invoke(true, cloudResourceList);
                            callback?.Invoke(true, cloudResourceList);
                        }
                        else
                        {
                            LocalOnlyUpdate(false, cloudResourceList);
                        }
                    }));
                }
                else
                {
                    LocalOnlyUpdate(false, cloudResourceList);
                }
            }));
        }
        static RequestHandle SaveDataRecording(this IUsesCloudStorage storageUser, CompanionProject project, string resourceFolder,
                                               string guid, CompanionDataRecording recording, Action <bool, string, long> callback, ProgressCallback progress)
        {
            var jsonText = SceneSerialization.ToJson(recording);

            WriteLocalDataRecording(project, resourceFolder, guid, jsonText);

            var key = GetDataRecordingKey(resourceFolder, guid);

            if (!project.linked)
            {
                callback?.Invoke(true, key, jsonText.Length);
                return(default);
        static RequestHandle SaveEnvironment(this IUsesCloudStorage storageUser, CompanionProject project,
                                             string resourceFolder, string guid, Environment environment, Action <bool, string, long> callback)
        {
            var jsonText = SceneSerialization.ToJson(environment);

            // Write to local storage in case cloud isn't reachable
            WriteLocalEnvironment(project, resourceFolder, guid, jsonText);
            var key = GetEnvironmentKey(resourceFolder, guid);

            if (!project.linked)
            {
                callback?.Invoke(true, key, jsonText.Length);
                return(default);
Пример #10
0
 public static void GetPrefab(IUsesCloudStorage storageUser, CompanionProject project, string key, Action <GameObject> callback)
 {
     if (k_CachedPrefabs.TryGetValue(key, out var prefab))
     {
         callback?.Invoke(prefab);
     }
     else
     {
         storageUser.GetPrefabAsset(project, key, (success, downloadedPrefab) =>
         {
             SetPrefab(key, downloadedPrefab);
             callback?.Invoke(downloadedPrefab);
         });
     }
 }
Пример #11
0
        static RequestHandle GetAssetBundleAsset(this IUsesCloudStorage storageUser, string group, CompanionProject project,
                                                 string resourceFolder, string platform, string guid, Action <bool, UnityObject> callback)
        {
            const int timeout = 0; // Asset bundles may be quite large and take a long time to download

            // Write to local storage in case cloud isn't reachable
            var folder = CompanionResourceUtils.GetLocalResourceFolderPath(project, resourceFolder, group);
            var path   = Path.Combine(folder, guid);

            if (!project.linked)
            {
                UnityObject asset = null;
                if (File.Exists(path))
                {
                    asset = GetLocalAssetBundleAsset(path);
                }

                callback(asset != null, asset);
                return(default);
Пример #12
0
 /// <summary>
 /// Get the current project identifier
 /// </summary>
 /// <param name="user">The functionality user</param>
 /// <returns>The current project identifier</returns>
 // ReSharper disable once UnusedMember.Global
 public static string GetProjectIdentifier(this IUsesCloudStorage user)
 {
     return(user.provider.GetProjectIdentifier());
 }
        internal static void ImportResource(this IUsesCloudStorage storageUser, CompanionProject project,
                                            CompanionResource resource, string platform, ResourceList resourceList, GameObject simulatedPlanePrefab,
                                            Material simulatedPlaneMaterial, Post postPrefab, MeshFilter meshPrefab, GameObject simulatedLightingPrefab,
                                            Stack <RequestHandle> requests, Action <UnityObject> callback)
        {
            string path;
            string cloudGuid;
            var    resourceKey = resource.key;

            switch (resource.type)
            {
            case ResourceType.Scene:
                if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    return;
                }

                void ImportSceneCallback(bool bundleSuccess, AssetPack assetPack)
                {
                    storageUser.GetScene(project, resource, (success, jsonText) =>
                    {
                        if (success)
                        {
                            CompanionSceneUtils.SplitSceneKey(resourceKey, out _, out cloudGuid);
                            var sceneGuid = CompanionResourceSync.instance.GetAssetGuid(cloudGuid);
                            var scenePath = AssetDatabase.GUIDToAssetPath(sceneGuid);

                            // GUIDToAssetPath will return a path if the asset was recently deleted
                            if (AssetDatabase.LoadAssetAtPath <SceneAsset>(scenePath) == null)
                            {
                                scenePath = null;
                            }

                            if (!string.IsNullOrEmpty(sceneGuid) && string.IsNullOrEmpty(scenePath))
                            {
                                Debug.LogWarningFormat("Could not find scene with guid {0}. Falling back to new scene", sceneGuid);
                            }

                            var sceneName = CompanionSceneUtils.GetSceneName(resource.name);
                            ImportScene(sceneName, jsonText, assetPack, scenePath);

                            // Store cloud ID in temp scene object if original scene not found
                            if (string.IsNullOrEmpty(scenePath))
                            {
                                var cloudIdObject       = new GameObject("__Temp");
                                cloudIdObject.hideFlags = HideFlags.HideInHierarchy | HideFlags.DontSaveInBuild;
                                var cloudIdSaver        = cloudIdObject.AddComponent <CloudGuidSaver>();
                                cloudIdSaver.CloudGuid  = cloudGuid;
                            }
                        }
                    });
                }

                if (resourceList.TryGetAssetBundleKey(resource.key, platform, out var assetBundleKey))
                {
                    requests.Push(storageUser.GetAssetPack(project, assetBundleKey, ImportSceneCallback));
                }
                else
                {
                    ImportSceneCallback(true, null);
                }

                return;

            case ResourceType.Environment:
                requests.Push(storageUser.CloudLoadAsync(resourceKey, (success, responseCode, response) =>
                {
                    if (success)
                    {
                        var environmentName = resource.name;
                        path = EditorUtility.SaveFilePanelInProject(k_SaveEnvironmentDialogTitle, environmentName,
                                                                    k_PrefabExtension, string.Empty);

                        if (string.IsNullOrEmpty(path))
                        {
                            return;
                        }

                        ImportEnvironment(environmentName, response, path, simulatedPlanePrefab,
                                          simulatedPlaneMaterial, postPrefab, meshPrefab, simulatedLightingPrefab, callback);

                        var resourceSync = CompanionResourceSync.instance;
                        CompanionEnvironmentUtils.SplitEnvironmentKey(resourceKey, out _, out cloudGuid);
                        resourceSync.SetAssetGuid(AssetDatabase.AssetPathToGUID(path), cloudGuid);
                    }
                }));

                return;

            case ResourceType.Recording:
                path = EditorUtility.SaveFilePanelInProject(k_SaveRecordingDialogTitle, resource.name,
                                                            k_RecordingExtension, string.Empty);

                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                requests.Push(storageUser.CloudLoadAsync(resourceKey, (success, responseCode, response) =>
                {
                    if (success)
                    {
                        CoroutineUtils.StartCoroutine(storageUser.ImportDataRecording(path,
                                                                                      resourceKey, resource.name, response, requests, callback));
                    }
                }));

                return;

            case ResourceType.Marker:
                path = EditorUtility.SaveFilePanelInProject(k_SaveImageDialogTitle, resource.name,
                                                            k_ImageExtension, string.Empty);

                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                var markerKey = resourceKey;
                requests.Push(storageUser.CloudLoadAsync(markerKey, (success, responseCode, response) =>
                {
                    if (success)
                    {
                        requests.Push(storageUser.ImportMarker(path, markerKey, response, callback));
                    }
                }));

                return;

            case ResourceType.Prefab:
                requests.Push(storageUser.GetPrefabAsset(project, resourceKey, platform,
                                                         (bundleSuccess, prefab) =>
                {
                    UnityObject.Instantiate(prefab);
                }));
                return;
            }
        }
        static IEnumerator ImportDataRecording(this IUsesCloudStorage storageUser, string recordingPath,
                                               string recordingKey, string recordingName, string jsonText, Stack <RequestHandle> requests,
                                               Action <UnityObject> callback)
        {
            k_DataRecordings.Clear();
            k_NewAssets.Clear();

            var recording = SceneSerialization.FromJson <CompanionDataRecording>(jsonText);

            var recordingInfo = SessionRecordingUtils.CreateSessionRecordingAsset(recordingPath);
            var timeline      = recordingInfo.Timeline;

            recordingInfo.name            = recordingName + " Info";
            recordingInfo.CloudResourceId = recordingKey;

            var resourceCount = 0;

            if (recording.HasCameraPath)
            {
                resourceCount++;
                requests.Push(storageUser.DownloadCameraPath(recordingKey, (success, list) =>
                {
                    if (success && list != null && list.Count > 0)
                    {
                        k_CameraPoseRecorder.PoseEvents = list;
                        var dataRecording = k_CameraPoseRecorder.TryCreateDataRecording(timeline, k_NewAssets);
                        if (dataRecording != null)
                        {
                            k_DataRecordings.Add(dataRecording);
                        }
                    }

                    // ReSharper disable once AccessToModifiedClosure
                    resourceCount--;
                }));
            }

            if (recording.HasPlaneData)
            {
                resourceCount++;
                requests.Push(storageUser.DownloadPlaneData(recordingKey, (success, list) =>
                {
                    if (success && list != null && list.Count > 0)
                    {
                        k_PlaneFindingRecorder.PlaneEvents = list;
                        var dataRecording = k_PlaneFindingRecorder.TryCreateDataRecording(timeline, k_NewAssets);
                        if (dataRecording != null)
                        {
                            k_DataRecordings.Add(dataRecording);
                        }
                    }

                    resourceCount--;
                }));
            }

            if (recording.HasPointCloud)
            {
                resourceCount++;
                requests.Push(storageUser.DownloadPointCloud(recordingKey, (success, list) =>
                {
                    if (success && list != null && list.Count > 0)
                    {
                        k_PointCloudRecorder.PointCloudEvents = list;
                        var dataRecording = k_PointCloudRecorder.TryCreateDataRecording(timeline, k_NewAssets);
                        if (dataRecording != null)
                        {
                            k_DataRecordings.Add(dataRecording);
                        }
                    }

                    resourceCount--;
                }));
            }

            while (resourceCount > 0)
            {
                yield return(null);
            }

            foreach (var dataRecording in k_DataRecordings)
            {
                recordingInfo.AddDataRecording(dataRecording);
                dataRecording.name = dataRecording.GetType().Name;
                AssetDatabase.AddObjectToAsset(dataRecording, timeline);
            }

            foreach (var newAsset in k_NewAssets)
            {
                AssetDatabase.AddObjectToAsset(newAsset, timeline);
            }

            AssetDatabase.SaveAssets();
            ProjectWindowUtil.ShowCreatedAsset(timeline);

            k_DataRecordings.Clear();
            k_NewAssets.Clear();

            if (!recording.HasVideo)
            {
                FinalizeDataRecordingImport(timeline, recordingKey, recordingPath, callback);
                yield break;
            }

            var videoPath = EditorUtility.SaveFilePanelInProject(k_SaveVideoDialogTitle, recordingName, k_VideoExtension, string.Empty);

            if (string.IsNullOrEmpty(recordingPath))
            {
                FinalizeDataRecordingImport(timeline, recordingKey, recordingPath, callback);
                yield break;
            }

            // TODO: Progress bar
            requests.Push(storageUser.DownloadVideo(recordingKey, (success, path) =>
            {
                try
                {
                    AssetDatabase.StartAssetEditing();

                    if (File.Exists(path))
                    {
                        var destinationPath = Path.Combine(Directory.GetCurrentDirectory(), videoPath);
                        if (File.Exists(destinationPath))
                        {
                            File.Delete(destinationPath);
                        }

                        File.Move(path, destinationPath);
                    }
                    else
                    {
                        Debug.LogError($"Couldn't find temp video file at path {path}");
                    }
                }
                catch (IOException e)
                {
                    Debug.LogException(e);
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                }

                AssetDatabase.Refresh();

                var videoClip                      = AssetDatabase.LoadAssetAtPath <VideoClip>(videoPath);
                var videoTrack                     = timeline.CreateTrack <MarsVideoPlayableTrack>(null, k_DefaultVideoTrackName);
                var timelineClip                   = videoTrack.CreateClip <MarsVideoPlayableAsset>();
                timelineClip.displayName           = videoClip.name;
                timelineClip.duration              = videoClip.length;
                var videoPlayableAsset             = (MarsVideoPlayableAsset)timelineClip.asset;
                videoPlayableAsset.VideoClip       = videoClip;
                videoPlayableAsset.FacingDirection = CameraFacingDirection.World;
                timeline.editorSettings.fps        = (float)videoClip.frameRate;

                var videoHalfHeight            = videoClip.height * 0.5f;
                var halfFOV                    = recording.fovRadians * 0.5f;
                videoPlayableAsset.FocalLength = videoHalfHeight / Mathf.Tan(halfFOV);

                videoPlayableAsset.ZRotation = recording.zRotation;
            }));

            FinalizeDataRecordingImport(timeline, recordingKey, recordingPath, callback);
        }
Пример #15
0
 /// <summary>
 /// Cancel a request with the given request handle
 /// </summary>
 /// <param name="user">The functionality user</param>
 /// <param name="handle">The handle to the request, which was returned by the method which initiated it</param>
 public static void CancelRequest(this IUsesCloudStorage user, RequestHandle handle)
 {
     user.provider.CancelRequest(handle);
 }
Пример #16
0
 /// <summary>
 /// Load a texture asynchronously from local storage
 /// </summary>
 /// <param name="user">The functionality user</param>
 /// <param name="path">Path to the texture. </param>
 /// <param name="callback">A callback which returns whether the operation was successful, as well as the
 /// response payload if it was. If the operation failed, the byte array will contain the error string</param>
 /// <param name="progress">Called every frame while the request is in progress with two 0-1 values indicating
 /// upload and download progress, respectively</param>
 /// <param name="timeout">The timeout duration (in seconds) for this request</param>
 /// <returns>A handle to the request which can be used to cancel it</returns>
 public static RequestHandle LoadLocalTextureAsync(this IUsesCloudStorage user, string path, LoadTextureCallback callback,
                                                   ProgressCallback progress = null, int timeout = CloudStorageDefaults.DefaultTimeout)
 {
     return(user.provider.LoadLocalTextureAsync(path, callback, progress, timeout));
 }
Пример #17
0
 /// <summary>
 /// Cancel all currently active requests
 /// </summary>
 /// <param name="user">The functionality user</param>
 public static void CancelAllRequests(this IUsesCloudStorage user)
 {
     user.provider.CancelAllRequests();
 }
Пример #18
0
 /// <summary>
 /// Set the current project identifier
 /// </summary>
 /// <param name="user">The functionality user</param>
 /// <param name="id">The project identifier to set</param>
 public static void SetProjectIdentifier(this IUsesCloudStorage user, string id)
 {
     user.provider.SetProjectIdentifier(id);
 }
        static RequestHandle ImportMarker(this IUsesCloudStorage storageUser, string imagePath, string markerKey,
                                          string jsonText, Action <UnityObject> callback)
        {
            return(storageUser.DownloadMarkerImage(markerKey, (success, tempPath) =>
            {
                var destinationPath = Path.Combine(Directory.GetCurrentDirectory(), imagePath);
                try
                {
                    AssetDatabase.StartAssetEditing();

                    if (File.Exists(tempPath))
                    {
                        if (File.Exists(destinationPath))
                        {
                            File.Delete(destinationPath);
                        }

                        File.Move(tempPath, destinationPath);
                    }
                    else
                    {
                        Debug.LogError($"Couldn't find image file at path {tempPath}");
                    }
                }
                catch (IOException e)
                {
                    Debug.LogException(e);
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                }

                // we need access to the created texture for the image before we can add it to a marker library
                AssetDatabase.Refresh();

                ApplyImageMarkerTextureImportSettings(imagePath);

                var marker = SceneSerialization.FromJson <Marker>(jsonText);

                // add the created marker to a marker library
                var markerTex = AssetDatabase.LoadAssetAtPath <Texture2D>(imagePath);
                var markerLibrary = SelectMarkerLibrary();
                Guid markerGuid;
                if (markerTex != null && markerLibrary != null)
                {
                    markerGuid = CompanionEditorAssetUtils.CreateMarkerInLibrary(markerLibrary, marker, markerTex);
                }

                // create a Proxy in the scene with a MarkerCondition looking for the marker's new guid
                var markerProxyObj = CreateMarkerProxy(marker, markerGuid);
                EditorGUIUtility.PingObject(markerProxyObj);


                var prefabSavePath = EditorUtility.SaveFilePanelInProject(k_SaveProxyTitle,
                                                                          string.Format(k_ProxyNameFormat, marker.name), k_PrefabExtension, k_SaveProxyMessage);

                // if user presses 'cancel' in the save prompt, no prefab will be saved
                if (!string.IsNullOrEmpty(prefabSavePath))
                {
                    // creation of prefab is outside the start/stop editing block so we can highlight the created asset
                    var createdPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(markerProxyObj, prefabSavePath, InteractionMode.AutomatedAction);
                    ProjectWindowUtil.ShowCreatedAsset(createdPrefab);
                    callback(createdPrefab);
                }

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();

                var resourceSync = CompanionResourceSync.instance;
                CompanionMarkerUtils.SplitMarkerKey(markerKey, out _, out var cloudGuid);
                resourceSync.SetAssetGuid(AssetDatabase.AssetPathToGUID(prefabSavePath), cloudGuid);
            }));
        }
 internal static RequestHandle UploadSceneAssetBundle(this IUsesCloudStorage storageUser, string resourceFolder,
                                                      string platform, string guid, Action <bool, string, long> callback = null, ProgressCallback progress = null)
 {
     return(UploadAssetBundle(storageUser, CompanionAssetUtils.SceneAssetBundleGroupName, resourceFolder, platform, guid, callback, progress));
 }
Пример #21
0
 /// <summary>
 /// Load from the cloud asynchronously the data of an object which was saved with a known key
 /// </summary>
 /// <param name="user">The functionality user</param>
 /// <param name="key">String that uniquely identifies this instance of the type. </param>
 /// <param name="callback">A callback which returns whether the operation was successful, as well as the
 /// response code and serialized string of the object if it was</param>
 /// <param name="progress">Called every frame while the request is in progress with two 0-1 values indicating
 /// upload and download progress, respectively</param>
 /// <param name="timeout">The timeout duration (in seconds) for this request</param>
 /// <returns>A handle to the request which can be used to cancel it</returns>
 public static RequestHandle CloudLoadAsync(this IUsesCloudStorage user, string key, Action <bool, long, string> callback,
                                            ProgressCallback progress = null, int timeout = CloudStorageDefaults.DefaultTimeout)
 {
     return(user.provider.CloudLoadAsync(key, callback, progress, timeout));
 }