static void ImportScene(string sceneName, string jsonText, AssetPack assetPack, string path = null) { var sceneModule = MARSSceneModule.instance; var wasBlockingEnsureSession = sceneModule.BlockEnsureSession; sceneModule.BlockEnsureSession = true; if (string.IsNullOrEmpty(path)) { var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); scene.name = sceneName; } else { var scene = EditorSceneManager.OpenScene(path); foreach (var gameObject in scene.GetRootGameObjects().ToList()) { UnityObject.DestroyImmediate(gameObject); } } // TODO: preload prefabs CompanionSceneUtils.ImportScene(jsonText, assetPack); sceneModule.BlockEnsureSession = wasBlockingEnsureSession; }
static void Publish() { k_ResourceListUpdates.Clear(); s_UploadCount = 0; var subscriber = CreateSubscriber(); var resourceFolder = CompanionResourceUtils.GetCurrentResourceFolder(); var project = new CompanionProject(Application.cloudProjectId, Application.productName, true); foreach (var selected in Selection.objects) { if (selected is SceneAsset sceneAsset) { var path = AssetDatabase.GetAssetPath(sceneAsset); if (string.IsNullOrEmpty(path)) { Debug.LogError("Selected SceneAsset path is invalid"); continue; } var sceneAssetPack = CompanionSceneUtils.GetOrTryCreateAssetPackForSceneAsset(sceneAsset); sceneAssetPack.Clear(); sceneAssetPack.SceneAsset = sceneAsset; var removeScene = true; var unload = true; var sceneCount = SceneManager.sceneCount; for (var i = 0; i < sceneCount; i++) { var existingScene = SceneManager.GetSceneAt(i); if (existingScene.path == path) { if (existingScene.isLoaded) { unload = false; } removeScene = false; break; } } var scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive); var assetGuid = AssetDatabase.AssetPathToGUID(path); if (string.IsNullOrEmpty(assetGuid)) { Debug.LogError("Could not get valid guid for asset at path " + path); continue; } // Hide the OnDestroyNotifier so it is not saved foreach (var root in scene.GetRootGameObjects()) { var notifier = root.GetComponentInChildren <OnDestroyNotifier>(); if (notifier != null) { notifier.gameObject.hideFlags = HideFlags.HideAndDontSave; } } // generate and save thumbnail image for the scene by running a one-shot simulation var thumbnail = SimulateSceneAndCaptureThumbnail(); var cloudGuid = CompanionResourceSync.instance.GetCloudGuid(assetGuid); s_UploadCount++; k_Requests.Clear(); k_Requests.Push(subscriber.SaveScene(project, resourceFolder, cloudGuid, scene, sceneAssetPack, (success, key, size) => { if (scene.IsValid()) { // Restore OnDestroyNotifier HideFlags so that it is discoverable foreach (var root in scene.GetRootGameObjects()) { var notifier = root.GetComponentInChildren <OnDestroyNotifier>(); if (notifier != null) { notifier.gameObject.hideFlags = HideFlags.HideInHierarchy; } } } var sceneName = sceneAsset.name; if (success) { k_ResourceListUpdates.Add(new ResourceListUpdate { ResourceKey = key, Name = sceneName, Type = ResourceType.Scene, FileSize = size, HasBundle = sceneAssetPack.AssetCount > 0, Thumbnail = thumbnail }); Debug.Log($"Published {sceneName}"); } else { Debug.LogError($"Failed to publish {sceneName}"); } if (--s_UploadCount == 0) { FinalizePublish(k_Requests); } })); // Scene serialization is synchronous, so we can close the scene while the upload completes if (unload) { EditorSceneManager.CloseScene(scene, removeScene); } continue; } if (selected is GameObject prefab) { var path = AssetDatabase.GetAssetPath(prefab); if (string.IsNullOrEmpty(path)) { Debug.LogError("SceneAsset for selected AssetPack path is invalid"); continue; } var guid = AssetDatabase.AssetPathToGUID(path); if (string.IsNullOrEmpty(guid)) { Debug.LogError("Could not get valid guid for asset at path " + path); continue; } // Check existing asset bundle name to avoid overwriting it var assetImporter = AssetImporter.GetAtPath(path); if (!string.IsNullOrEmpty(assetImporter.assetBundleName) && assetImporter.assetBundleName != guid) { Debug.LogError(prefab.name + " is already part of an AssetBundle, and cannot be published to the cloud without overwriting its AssetBundle name"); continue; } var bounds = BoundsUtils.GetBounds(prefab.transform); if (bounds.extents.MinComponent() < k_MinPrefabBound) { Debug.LogError(prefab.name + " is too small to be selectable. MARS prefabs must be selectable."); continue; } var thumbnail = ThumbnailUtility.GeneratePrefabThumbnail(prefab); if (thumbnail == null) { Debug.LogError(prefab.name + " is not a visible asset. MARS prefabs must be visible."); continue; } s_UploadCount++; k_Requests.Clear(); k_Requests.Push(subscriber.SavePrefab(project, resourceFolder, prefab, (success, key) => { if (success) { k_ResourceListUpdates.Add(new ResourceListUpdate { ResourceKey = key, Name = prefab.name, Type = ResourceType.Prefab, HasBundle = true, Thumbnail = thumbnail }); Debug.Log($"Published {prefab.name}"); } else { Debug.LogError($"Failed to publish {prefab.name}"); } if (--s_UploadCount == 0) { FinalizePublish(k_Requests); } })); } } }
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; } }