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);
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);
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); }); } }
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);
/// <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); }
/// <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); }
/// <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)); }
/// <summary> /// Cancel all currently active requests /// </summary> /// <param name="user">The functionality user</param> public static void CancelAllRequests(this IUsesCloudStorage user) { user.provider.CancelAllRequests(); }
/// <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)); }
/// <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)); }