/// <summary> /// Exports and uploads the saber via adb /// </summary> /// <param name="saber"></param> void ExportAndUpload(SaberReferences saber) { string saberName = saber.descriptor.objectName + "." + extension; string path = EditorUtility.SaveFilePanel("Save " + extension + " file", "", saberName, extension); if (path == "") { EditorUtility.DisplayDialog("Exportation Failed!", "Invalid path", "OK"); return; } string folderPath = Path.GetDirectoryName(path) + "/"; if (exporterConfig.ipAddress != "") { QosmeticUtils.adb("connect " + exporterConfig.ipAddress + ":5555"); } QosmeticUtils.adb("shell am force-stop com.beatgames.beatsaber"); ExportSaberFile(saber, folderPath); QosmeticUtils.adb("push \"" + folderPath + saberName + "\" \"" + questPath + saberName + "\""); QosmeticUtils.adb("shell am start com.beatgames.beatsaber/com.unity3d.player.UnityPlayerActivity"); EditorUtility.DisplayDialog("Exportation Successful!", "If the game did not turn off or the saber is not showing up, make sure your quest is connected through adb", "OK"); EditorUtility.RevealInFinder(folderPath + saberName); }
void ExportAllAndUpload() { string path = EditorUtility.SaveFolderPanel("Select folder to export all ." + extension + " files", "", ""); if (path == "") { EditorUtility.DisplayDialog("Export Failed", "Path was invalid", "OK"); return; } path += "/"; List <string> skippedWalls = new List <string>(); bool wallsWereSkipped = false; bool atLeastOneSuccessful = false; if (exporterConfig.ipAddress != "") { QosmeticUtils.adb("connect " + exporterConfig.ipAddress + ":5555"); } QosmeticUtils.adb("shell am force-stop com.beatgames.beatsaber"); foreach (var wall in questwalls) { bool disableExport = shouldDisableExport(wall); if (!disableExport) { atLeastOneSuccessful = true; ExportWallFile(wall, path); string wallName = wall.descriptor.objectName + "." + extension; QosmeticUtils.adb("push\"" + path + wallName + "\" \"" + questPath + wallName + "\""); } else { wallsWereSkipped = true; skippedWalls.Add(wall.descriptor.objectName); } } if (wallsWereSkipped) { string message = "These Walls were skipped due to exporter issues: \n"; foreach (var wallName in skippedWalls) { message += wallName + "\n"; } EditorUtility.DisplayDialog("Sabers Were skipped...", message, "OK"); } else { EditorUtility.DisplayDialog("Wall exports successful!", "Exported all walls successfully!", "OK"); } if (atLeastOneSuccessful) { QosmeticUtils.adb("shell am start com.beatgames.beatsaber/com.unity3d.player.UnityPlayerActivity"); EditorUtility.RevealInFinder(path); } }
/// <summary> /// Runs the code to display the bmbf input options in the GUI /// </summary> /// <param name="saber"></param> void BMBFConfigDisplay(SaberReferences saber) { QosmeticUtils.addIfNull(saber.bmbfmod); saber.bmbfmod.components[0].type = "FileCopyMod"; saber.bmbfmod.components[0].targetRootedPathAndFileName = questPath + "testSaber." + extension; if (saber.advancedInfo) { saber.bmbfmod.coverImageFilename = EditorGUILayout.TextField("Cover image name", saber.bmbfmod.coverImageFilename); } else if (saber.bmbfmod.coverImageFilename == "" && exporterConfig.defaultCoverImageFileName != "") { saber.bmbfmod.coverImageFilename = exporterConfig.defaultCoverImageFileName; } saber.bmbfmod.icon = saber.bmbfmod.coverImageFilename; if (saber.advancedInfo) { saber.bmbfmod.version = EditorGUILayout.TextField("Saber version", saber.bmbfmod.version); } else if (saber.bmbfmod.version == "" && exporterConfig.defaultVersion != "") { saber.bmbfmod.version = exporterConfig.defaultVersion; } if (saber.advancedInfo) { saber.bmbfmod.links.pageLink = EditorGUILayout.TextField("Page link", saber.bmbfmod.links.pageLink); } else if (saber.bmbfmod.links.pageLink == "" && exporterConfig.defaultPageLink != "") { saber.bmbfmod.links.pageLink = exporterConfig.defaultPageLink; } saber.bmbfmod.gameVersion = EditorGUILayout.TextField("Game version", saber.bmbfmod.gameVersion); saber.bmbfmod.description[0] = EditorGUILayout.TextField("Description", saber.bmbfmod.description[0]); saber.bmbfmod.platform = "Quest"; saber.bmbfmod.name = EditorGUILayout.TextField("Saber name", saber.bmbfmod.name); saber.bmbfmod.author = EditorGUILayout.TextField("Author name", saber.bmbfmod.author); saber.bmbfmod.category = "Saber"; saber.bmbfmod.components[0].sourceFileName = saber.bmbfmod.name + "." + extension; string modID = saber.bmbfmod.name + saber.bmbfmod.author + "V" + saber.bmbfmod.version; modID = QosmeticUtils.sanitizeString(modID); saber.bmbfmod.id = modID; }
void OnGUI() { GUILayout.Label("Object cleanup at export config", EditorStyles.boldLabel); exporterConfig.removeLightsAtExport = EditorGUILayout.ToggleLeft("Remove Lights at export", exporterConfig.removeLightsAtExport); exporterConfig.removeCamerasAtExport = EditorGUILayout.ToggleLeft("Remove Cameras at export", exporterConfig.removeCamerasAtExport); GUILayout.Space(5); /* * GUILayout.Label("Default information config", EditorStyles.boldLabel); * exporterConfig.defaultVersion = EditorGUILayout.TextField("Default Version", exporterConfig.defaultVersion); * exporterConfig.defaultPageLink = EditorGUILayout.TextField("Default Page Link", exporterConfig.defaultPageLink); * exporterConfig.defaultCoverImageFileName = EditorGUILayout.TextField("Default Cover Image File Name", exporterConfig.defaultCoverImageFileName); * GUILayout.Space(5); */ GUILayout.Label("Quest IP Address for file upload", EditorStyles.boldLabel); exporterConfig.ipAddress = EditorGUILayout.TextField("IP address", exporterConfig.ipAddress); GUILayout.Space(5); GUILayout.Label("Misc.", EditorStyles.boldLabel); exporterConfig.forceAllowExport = EditorGUILayout.ToggleLeft("Force Allow Export", exporterConfig.forceAllowExport); GUILayout.Space(5); exporterConfig.allowOwnCamera = EditorGUILayout.ToggleLeft("Allow Own Camera (add QosmeticsCam script to it)", exporterConfig.allowOwnCamera); GUILayout.Space(5); exporterConfig.setCamLayerOnExport = EditorGUILayout.ToggleLeft("Set cam layer on export (only export is visible)", exporterConfig.setCamLayerOnExport); GUILayout.Space(5); if (GUILayout.Button("Save config")) { string json = JsonUtility.ToJson(exporterConfig, true); File.WriteAllText(exporterConfigPath, json); EditorUtility.DisplayDialog("Config Saved", "For changes to show up in your exports, close and reopen the exporter unity window (not the entire unity project)", "OK"); OnFocus(); } GUILayout.Label("If you want to upload files wirelessly, press this button every time you reboot your quest:", EditorStyles.boldLabel); GUILayout.Label("Make sure that when you click this button, your quest is connected with a usb cable", EditorStyles.boldLabel); if (GUILayout.Button("Connect quest wirelessly")) { QosmeticUtils.adb("adb tcpip 5555"); } }
/// <summary> /// Exports a complete Zip package ready to be loaded into bmbf /// </summary> /// <param name="saber"></param> void ExportSaberZip(SaberReferences saber, string path = "") { /* * if (EditorUserBuildSettings.activeBuildTarget.ToString() != "Android") * { * EditorUtility.DisplayDialog("Exportation Failed!", "Your projects build target is not Android.", "OK"); * return; * } */ bool batch = path != ""; GameObject saberObject = saber.gameObject; TextAsset config = new TextAsset(JsonUtility.ToJson(saber.config, true)); string bmbfmodJson = JsonUtility.ToJson(saber.bmbfmod, true); TextAsset bmbfmod = new TextAsset(bmbfmodJson); string descriptorString = JsonUtility.ToJson(saber.descriptor, true); TextAsset descriptor = new TextAsset(descriptorString); string zipname = saber.bmbfmod.name + "V" + saber.bmbfmod.version + ".zip"; zipname = QosmeticUtils.sanitizeString(zipname); if (!batch) { path = EditorUtility.SaveFilePanel("Save " + "." + extension + " zip", "", zipname, "zip"); } else { path += zipname; } if (path == "") { EditorUtility.DisplayDialog("Exportation Failed!", "Invalid path", "OK"); return; } string fileName = saber.bmbfmod.name + "." + extension; string folderPath = Path.GetDirectoryName(path); string workingDir = Application.temporaryCachePath + "/QuestSaber"; if (File.Exists(path)) { File.Delete(path); } if (!Directory.Exists(workingDir)) { Directory.CreateDirectory(workingDir); } if (exporterConfig.removeCamerasAtExport) { QosmeticUtils.PurgeCameras(saberObject); } if (exporterConfig.removeLightsAtExport) { QosmeticUtils.PurgeLights(saberObject); } Selection.activeObject = saberObject; EditorUtility.SetDirty(saber); EditorSceneManager.MarkSceneDirty(saberObject.scene); EditorSceneManager.SaveScene(saberObject.scene); GameObject camObject; Camera exportCam; if (exporterConfig.allowOwnCamera) // manual cam { camObject = cam.gameObject; exportCam = cam; } else // automatic cam: { camObject = GameObject.CreatePrimitive(PrimitiveType.Quad); exportCam = camObject.AddComponent <Camera>(); exportCam.gameObject.name = "Camera"; exportCam.transform.localPosition = new Vector3(0.6f, 0.4f, 0.05f); exportCam.transform.rotation = Quaternion.Euler(25f, -70f, 0.0f); exportCam.clearFlags = CameraClearFlags.SolidColor; exportCam.nearClipPlane = 0.01f; exportCam.backgroundColor = new Color(0.0f, 0.0f, 25.0f / 256.0f); } exportCam.nearClipPlane = 0.01f; int oldCamMask = exportCam.cullingMask; int oldObjectMask = saber.gameObject.layer; int newMask = 31; int newCamMask = 1 << 31; // moved prefab forward so that the layermask isnt f****d up on the actual exported file PrefabUtility.SaveAsPrefabAsset(Selection.activeGameObject as GameObject, "Assets/" + prefabName + ".prefab"); if (exporterConfig.setCamLayerOnExport) { exportCam.cullingMask = newCamMask; QosmeticUtils.SetLayerRecursively(exportCam.gameObject, newMask); QosmeticUtils.SetLayerRecursively(saber.gameObject, newMask); } Texture2D thumbnail = QosmeticUtils.getTexture2D(exportCam, 1024, 1024); //Start actually constructing the bundle AssetDatabase.CreateAsset(config, "Assets/config.asset"); AssetDatabase.CreateAsset(bmbfmod, "Assets/BMBFmod.asset"); AssetDatabase.CreateAsset(thumbnail, "Assets/thumbnail.asset"); AssetDatabase.CreateAsset(descriptor, "Assets/descriptor.asset"); AssetBundleBuild assetBundleBuild = default(AssetBundleBuild); assetBundleBuild.assetNames = new string[] { "Assets/" + prefabName + ".prefab", "Assets/config.asset", "Assets/BMBFmod.asset", "Assets/thumbnail.asset", "Assets/descriptor.asset" }; assetBundleBuild.assetBundleName = fileName; BuildTargetGroup selectedBuildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; BuildTarget activeBuildTarget = EditorUserBuildSettings.activeBuildTarget; //Build Bundle BuildPipeline.BuildAssetBundles(workingDir, new AssetBundleBuild[] { assetBundleBuild }, 0, BuildTarget.Android); EditorPrefs.SetString("currentBuildingAssetBundlePath", folderPath); EditorUserBuildSettings.SwitchActiveBuildTarget(selectedBuildTargetGroup, activeBuildTarget); thumbnail = QosmeticUtils.getTexture2D(exportCam, 1024, 512); Directory.CreateDirectory(workingDir + "/tempzip"); QosmeticUtils.exportImage(thumbnail, workingDir + "/tempzip/" + saber.bmbfmod.coverImageFilename); File.Move(workingDir + "/" + fileName, workingDir + "/tempzip/" + fileName); File.WriteAllText(workingDir + "/tempzip/bmbfmod.json", bmbfmodJson); QosmeticUtils.createZipFromFolder(workingDir + "/tempzip", path); //Asset cleanup AssetDatabase.DeleteAsset("Assets/" + prefabName + ".prefab"); AssetDatabase.DeleteAsset("Assets/config.asset"); AssetDatabase.DeleteAsset("Assets/BMBFmod.asset"); AssetDatabase.DeleteAsset("Assets/thumbnail.asset"); AssetDatabase.DeleteAsset("Assets/descriptor.asset"); if (!exporterConfig.allowOwnCamera) { DestroyImmediate(camObject); } clearTemp(workingDir); AssetDatabase.Refresh(); if (exporterConfig.setCamLayerOnExport) { if (exporterConfig.allowOwnCamera) { exportCam.cullingMask = oldCamMask; } if (exporterConfig.allowOwnCamera) { QosmeticUtils.SetLayerRecursively(exportCam.gameObject, oldObjectMask); } QosmeticUtils.SetLayerRecursively(saber.gameObject, oldObjectMask); } if (!batch) { EditorUtility.DisplayDialog("Exportation Successful!", "Exportation Successful!", "OK"); EditorUtility.RevealInFinder(path); } }
void OnGUI() { GUILayout.BeginHorizontal(); GUILayout.Label("Quest Sabers", EditorStyles.boldLabel); if (GUILayout.Button("Go to saber scene")) { EditorSceneManager.OpenScene("Assets/scenes/questsabers.unity"); OnFocus(); } if (GUILayout.Button("Add New Saber Template")) { AddSaberTemplate(); } GUILayout.EndHorizontal(); GUILayout.Space(5); if (GUILayout.Button("Export all Active sabers")) { ExportAll(); } if (GUILayout.Button("Export and Upload all Active sabers")) { ExportAllAndUpload(); } GUILayout.Space(10); foreach (var saber in questsabers) { if (saber == null) { continue; } GUILayout.Label("GameObject : " + saber.gameObject.name, EditorStyles.boldLabel); saber.descriptorFolded = EditorGUILayout.BeginFoldoutHeaderGroup(saber.descriptorFolded, "Saber Descriptor"); if (saber.descriptorFolded) { GUILayout.Space(5); DescriptorDisplay(saber); } EditorGUILayout.EndFoldoutHeaderGroup(); GUILayout.Space(5); saber.configFolded = EditorGUILayout.BeginFoldoutHeaderGroup(saber.configFolded, "Saber config"); if (saber.configFolded) { SaberConfigDisplay(saber); } EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUILayout.Space(10); bool disableExport = shouldDisableExport(saber); if (disableExport && exporterConfig.forceAllowExport) { GUILayout.Label("WARNING! force allow export is set to true so this saber file is unlikely to work correctly in game!", EditorStyles.boldLabel); } EditorGUI.BeginDisabledGroup(disableExport && !exporterConfig.forceAllowExport); if (GUILayout.Button("Export " + saber.descriptor.objectName + "." + extension)) { ExportSaberFile(saber); } if (GUILayout.Button("Export and Upload " + saber.descriptor.objectName + "." + extension + " To Quest")) { ExportAndUpload(saber); } EditorGUI.EndDisabledGroup(); if (QosmeticUtils.GetObjectBounds(saber.gameObject).extents.z * 2.0 > 2.0) { GUILayout.Label("The saber might be too long", EditorStyles.boldLabel); } if (QosmeticUtils.GetObjectBounds(saber.gameObject).extents.z * 2.0 < 0.5) { GUILayout.Label("The saber might be too short", EditorStyles.boldLabel); } if (QosmeticUtils.GetObjectBounds(saber.gameObject).extents.x * 2.0 > 1.0) { GUILayout.Label("The saber might be too large", EditorStyles.boldLabel); } if (debug) { if (GUILayout.Button("Log config json")) { SetTrailConfigs(saber); Debug.Log(JsonUtility.ToJson(saber.config, true)); } } } }
/// <summary> /// Exports just a qbloq file /// </summary> /// <param name="bloq"></param> void ExportBloqFile(BloqReferences bloq, string path = "") { bool batch = path != ""; GameObject bloqObject = bloq.gameObject; TextAsset config = new TextAsset(JsonUtility.ToJson(bloq.config, true)); //string bmbfmodJson = JsonUtility.ToJson(bloq.bmbfmod, true); //TextAsset bmbfmod = new TextAsset(bmbfmodJson); string descriptorString = JsonUtility.ToJson(bloq.descriptor, true); TextAsset descriptor = new TextAsset(descriptorString); string bloqName = bloq.descriptor.objectName + "." + extension; if (!batch) { path = EditorUtility.SaveFilePanel("Save " + extension + " file", "", bloqName, extension); } else { path += bloqName; } if (path == "") { EditorUtility.DisplayDialog("Exportation Failed!", "Invalid path", "OK"); return; } string fileName = Path.GetFileName(path); string folderPath = Path.GetDirectoryName(path); string workingDir = Application.temporaryCachePath + "/QuestBloq"; if (File.Exists(path)) { File.Delete(path); } if (!Directory.Exists(workingDir)) { Directory.CreateDirectory(workingDir); } if (exporterConfig.removeCamerasAtExport) { QosmeticUtils.PurgeCameras(bloqObject); } if (exporterConfig.removeLightsAtExport) { QosmeticUtils.PurgeLights(bloqObject); } Selection.activeObject = bloqObject; EditorUtility.SetDirty(bloq); EditorSceneManager.MarkSceneDirty(bloqObject.scene); EditorSceneManager.SaveScene(bloqObject.scene); GameObject camObject; Camera exportCam; if (exporterConfig.allowOwnCamera) // manual cam { camObject = cam.gameObject; exportCam = cam; } else // automatic cam: { camObject = GameObject.CreatePrimitive(PrimitiveType.Quad); exportCam = camObject.AddComponent <Camera>(); exportCam.gameObject.name = "Camera"; exportCam.transform.localPosition = new Vector3(2.2f, 2.6f, -6.4f); exportCam.transform.rotation = Quaternion.Euler(20.0f, -20.0f, 0.0f); exportCam.clearFlags = CameraClearFlags.SolidColor; exportCam.backgroundColor = new Color(0.0f, 0.0f, 25.0f / 256.0f); } exportCam.nearClipPlane = 0.01f; int oldCamMask = exportCam.cullingMask; int oldObjectMask = bloq.gameObject.layer; int newMask = 31; int newCamMask = 1 << 31; // moved prefab forward so that the layermask isnt f****d up on the actual exported file PrefabUtility.SaveAsPrefabAsset(Selection.activeGameObject as GameObject, "Assets/" + prefabName + ".prefab"); if (exporterConfig.setCamLayerOnExport) { exportCam.cullingMask = newCamMask; QosmeticUtils.SetLayerRecursively(exportCam.gameObject, newMask); QosmeticUtils.SetLayerRecursively(bloq.gameObject, newMask); } Texture2D thumbnail = bloq.thumbnail; if (!thumbnail) { thumbnail = QosmeticUtils.getTexture2D(exportCam, 1024, 1024); } //Start actually constructing the bundle AssetDatabase.CreateAsset(config, "Assets/config.asset"); //AssetDatabase.CreateAsset(bmbfmod, "Assets/BMBFmod.asset"); AssetDatabase.CreateAsset(thumbnail, "Assets/thumbnail.asset"); AssetDatabase.CreateAsset(descriptor, "Assets/descriptor.asset"); AssetBundleBuild assetBundleBuild = default(AssetBundleBuild); assetBundleBuild.assetNames = new string[] { "Assets/" + prefabName + ".prefab", "Assets/config.asset", //"Assets/BMBFmod.asset", "Assets/thumbnail.asset", "Assets/descriptor.asset" }; assetBundleBuild.assetBundleName = fileName; BuildTargetGroup selectedBuildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; BuildTarget activeBuildTarget = EditorUserBuildSettings.activeBuildTarget; //Build Bundle BuildPipeline.BuildAssetBundles(workingDir, new AssetBundleBuild[] { assetBundleBuild }, 0, BuildTarget.Android); EditorPrefs.SetString("currentBuildingAssetBundlePath", folderPath); EditorUserBuildSettings.SwitchActiveBuildTarget(selectedBuildTargetGroup, activeBuildTarget); //Asset cleanup AssetDatabase.DeleteAsset("Assets/" + prefabName + ".prefab"); AssetDatabase.DeleteAsset("Assets/config.asset"); //AssetDatabase.DeleteAsset("Assets/BMBFmod.asset"); AssetDatabase.DeleteAsset("Assets/thumbnail.asset"); AssetDatabase.DeleteAsset("Assets/descriptor.asset"); if (!exporterConfig.allowOwnCamera) { DestroyImmediate(camObject); } File.Move(workingDir + "/" + fileName, path); AssetDatabase.Refresh(); clearTemp(workingDir); if (exporterConfig.setCamLayerOnExport) { if (exporterConfig.allowOwnCamera) { exportCam.cullingMask = oldCamMask; } if (exporterConfig.allowOwnCamera) { QosmeticUtils.SetLayerRecursively(exportCam.gameObject, oldObjectMask); } QosmeticUtils.SetLayerRecursively(bloq.gameObject, oldObjectMask); } if (!batch) { EditorUtility.DisplayDialog("Exportation Successful!", "Exportation Successful!", "OK"); EditorUtility.RevealInFinder(path); } }
void OnGUI() { GUILayout.BeginHorizontal(); GUILayout.Label("Quest Bloqs", EditorStyles.boldLabel); if (GUILayout.Button("Go to Bloq scene")) { EditorSceneManager.OpenScene("Assets/scenes/questnotes.unity"); OnFocus(); } if (GUILayout.Button("Add New Bloq Template")) { AddBloqTemplate(); } GUILayout.EndHorizontal(); GUILayout.Space(5); if (GUILayout.Button("Export all Active bloqs")) { ExportAll(); } if (GUILayout.Button("Export and Upload all Active bloqs")) { ExportAllAndUpload(); } GUILayout.Space(10); foreach (var bloq in questbloqs) { if (bloq == null) { continue; } GUILayout.Label("GameObject : " + bloq.gameObject.name, EditorStyles.boldLabel); bloq.descriptorFolded = EditorGUILayout.BeginFoldoutHeaderGroup(bloq.descriptorFolded, "Bloq Descriptor"); if (bloq.descriptorFolded) { //bloq.advancedInfo = EditorGUILayout.ToggleLeft("Advanced BMBF mod info", bloq.advancedInfo); GUILayout.Space(5); DescriptorDisplay(bloq); } EditorGUILayout.EndFoldoutHeaderGroup(); GUILayout.Space(5); bloq.configFolded = EditorGUILayout.BeginFoldoutHeaderGroup(bloq.configFolded, "Bloq config"); if (bloq.configFolded) { BloqConfigDisplay(bloq); } EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUILayout.Space(10); bool disableExport = shouldDisableExport(bloq); if (disableExport && exporterConfig.forceAllowExport) { GUILayout.Label("WARNING! force allow export is set to true so this bloq file is unlikely to work correctly in game!", EditorStyles.boldLabel); } EditorGUI.BeginDisabledGroup(disableExport && !exporterConfig.forceAllowExport); if (GUILayout.Button("Export " + bloq.descriptor.objectName + "." + extension)) { GetHasBomb(bloq); GetHasDebris(bloq); ExportBloqFile(bloq); } if (GUILayout.Button("Export and Upload " + bloq.descriptor.objectName + "." + extension)) { GetHasBomb(bloq); GetHasDebris(bloq); ExportAndUpload(bloq); } EditorGUI.EndDisabledGroup(); foreach (Transform child in bloq.transform) { if (QosmeticUtils.GetObjectBounds(child.gameObject).extents.x * 2.0 > 1.4) { GUILayout.Label(child.gameObject.name + " might be too wide (x)", EditorStyles.boldLabel); } if (QosmeticUtils.GetObjectBounds(child.gameObject).extents.y * 2.0 > 1.4) { GUILayout.Label(child.gameObject.name + " might be too tall (y)", EditorStyles.boldLabel); } if (QosmeticUtils.GetObjectBounds(child.gameObject).extents.z * 2.0 > 1.4) { GUILayout.Label(child.gameObject.name + " might be too long (z)", EditorStyles.boldLabel); } } } }