417 lines
No EOL
17 KiB
C#
Executable file
417 lines
No EOL
17 KiB
C#
Executable file
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using ABI.CCK.Components;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.XR;
|
|
using Object = UnityEngine.Object;
|
|
using Random = System.Random;
|
|
|
|
namespace ABI.CCK.Scripts.Editor
|
|
{
|
|
public class CCK_BuildUtility
|
|
{
|
|
#region Variables
|
|
|
|
public static PreAvatarBundleEvent PreAvatarBundleEvent = new PreAvatarBundleEvent();
|
|
public static PrePropBundleEvent PrePropBundleEvent = new PrePropBundleEvent();
|
|
public static PreWorldBundleEvent PreWorldBundleEvent = new PreWorldBundleEvent();
|
|
|
|
public static string upload_id = "";
|
|
|
|
#endregion
|
|
|
|
#region Avatar Upload
|
|
|
|
public static async Task BuildAndUploadAvatar(GameObject avatarObject)
|
|
{
|
|
ClearLog();
|
|
EnforceVRSetting();
|
|
|
|
CVRAssetInfo assetInfo = avatarObject.GetComponent<CVRAssetInfo>();
|
|
|
|
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/avatar");
|
|
SetAssetInfoDirty(assetInfo);
|
|
|
|
GameObject instantiatedAvatar = InstantiateAndUnpackPrefab(avatarObject);
|
|
if (!HandlePreBuildEvent(PreAvatarBundleEvent.Invoke, instantiatedAvatar))
|
|
{
|
|
Object.DestroyImmediate(instantiatedAvatar);
|
|
return;
|
|
}
|
|
|
|
CCK_Tools.CleanEditorOnlyGameObjects(instantiatedAvatar);
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(instantiatedAvatar,
|
|
!Application.unityVersion.Contains("2021")
|
|
? "Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab"
|
|
: $"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{assetInfo.objectId}_{assetInfo.randomNum}.prefab");
|
|
|
|
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
|
|
assetBundleBuild.assetNames = !Application.unityVersion.Contains("2021")
|
|
? new[] { "Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab" }
|
|
: new[]
|
|
{
|
|
$"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{assetInfo.objectId}_{assetInfo.randomNum}.prefab"
|
|
};
|
|
|
|
upload_id = assetInfo.objectId;
|
|
EditorPrefs.SetString("m_ABI_uploadId", upload_id);
|
|
EditorPrefs.SetString("m_ABI_uploadRand", assetInfo.randomNum);
|
|
|
|
assetBundleBuild.assetBundleName = $"cvravatar_{assetInfo.objectId}_{assetInfo.randomNum}.cvravatar";
|
|
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
|
|
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
|
|
|
|
Object.DestroyImmediate(instantiatedAvatar);
|
|
|
|
if (!File.Exists($"{Application.persistentDataPath}/cvravatar_{assetInfo.objectId}_{assetInfo.randomNum}.cvravatar"))
|
|
{
|
|
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
|
|
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
EditorPrefs.SetBool("m_ABI_isBuilding", true);
|
|
EditorApplication.isPlaying = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Spawnable Upload
|
|
|
|
public static async Task BuildAndUploadSpawnable(GameObject spawnableObject)
|
|
{
|
|
ClearLog();
|
|
EnforceVRSetting();
|
|
|
|
CVRAssetInfo assetInfo = spawnableObject.GetComponent<CVRAssetInfo>();
|
|
|
|
CVRSpawnable spawnable = spawnableObject.GetComponent<CVRSpawnable>();
|
|
spawnable.spawnableType = CVRSpawnable.SpawnableType.StandaloneSpawnable;
|
|
EditorUtility.SetDirty(spawnable);
|
|
|
|
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/spawnable");
|
|
SetAssetInfoDirty(assetInfo);
|
|
|
|
GameObject instantiatedSpawnable = InstantiateAndUnpackPrefab(spawnableObject);
|
|
if (!HandlePreBuildEvent(PrePropBundleEvent.Invoke, instantiatedSpawnable))
|
|
{
|
|
Object.DestroyImmediate(instantiatedSpawnable);
|
|
return;
|
|
}
|
|
|
|
CCK_Tools.CleanEditorOnlyGameObjects(instantiatedSpawnable);
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(instantiatedSpawnable,
|
|
!Application.unityVersion.Contains("2021")
|
|
? "Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab"
|
|
: $"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{assetInfo.objectId}_{assetInfo.randomNum}.prefab");
|
|
|
|
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
|
|
assetBundleBuild.assetNames = !Application.unityVersion.Contains("2021")
|
|
? new[] { "Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab" }
|
|
: new[]
|
|
{
|
|
$"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{assetInfo.objectId}_{assetInfo.randomNum}.prefab"
|
|
};
|
|
|
|
upload_id = assetInfo.objectId;
|
|
EditorPrefs.SetString("m_ABI_uploadId", upload_id);
|
|
EditorPrefs.SetString("m_ABI_uploadRand", assetInfo.randomNum);
|
|
|
|
assetBundleBuild.assetBundleName = $"cvrspawnable_{assetInfo.objectId}_{assetInfo.randomNum}.cvrprop";
|
|
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
|
|
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
|
|
|
|
Object.DestroyImmediate(instantiatedSpawnable);
|
|
|
|
if (!File.Exists($"{Application.persistentDataPath}/cvrspawnable_{assetInfo.objectId}_{assetInfo.randomNum}.cvrprop"))
|
|
{
|
|
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
|
|
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
EditorPrefs.SetBool("m_ABI_isBuilding", true);
|
|
EditorApplication.isPlaying = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region World Upload
|
|
|
|
public static async Task BuildAndUploadMapAsset(Scene scene, GameObject descriptor)
|
|
{
|
|
ClearLog();
|
|
EnforceVRSetting();
|
|
|
|
SetupNetworkUUIDs();
|
|
|
|
CVRAssetInfo assetInfo = descriptor.GetComponent<CVRAssetInfo>();
|
|
|
|
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/world");
|
|
SetAssetInfoDirty(assetInfo);
|
|
|
|
if (!HandlePreBuildEvent(PreWorldBundleEvent.Invoke, scene))
|
|
return;
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(descriptor, "Assets/ABI.CCK/Resources/Cache/_CVRWorld.prefab");
|
|
|
|
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
|
|
assetBundleBuild.assetNames = new[] {scene.path};
|
|
assetBundleBuild.assetBundleName = "bundle.cvrworld";
|
|
|
|
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
|
|
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
|
|
|
|
if (!File.Exists($"{Application.persistentDataPath}/bundle.cvrworld"))
|
|
{
|
|
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
|
|
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
EditorPrefs.SetBool("m_ABI_isBuilding", true);
|
|
EditorApplication.isPlaying = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private static async Task InitializeAPIAndSetObjectId(CVRAssetInfo assetInfo, string apiEndpoint)
|
|
{
|
|
if (string.IsNullOrEmpty(assetInfo.objectId))
|
|
{
|
|
#if UNITY_EDITOR
|
|
APIConnection.Initialize(EditorPrefs.GetString("m_ABI_Username"), EditorPrefs.GetString("m_ABI_Key"));
|
|
#endif
|
|
APIConnection.BaseResponse<APIConnection.GenerateResponse> response = await APIConnection.MakeRequest<APIConnection.GenerateResponse>(apiEndpoint, put: true);
|
|
|
|
if (response != null && response.Data != null)
|
|
assetInfo.objectId = response.Data.Id.ToString();
|
|
else
|
|
Debug.LogError($"[CCK:BuildUtility] New Guid could not be generated");
|
|
}
|
|
|
|
Random rnd = new Random();
|
|
assetInfo.randomNum = rnd.Next(11111111, 99999999).ToString();
|
|
}
|
|
|
|
private static void SetAssetInfoDirty(Component assetInfo)
|
|
{
|
|
EditorUtility.SetDirty(assetInfo);
|
|
EditorSceneManager.MarkSceneDirty(assetInfo.gameObject.scene);
|
|
EditorSceneManager.SaveScene(assetInfo.gameObject.scene);
|
|
}
|
|
|
|
private static GameObject InstantiateAndUnpackPrefab(GameObject original)
|
|
{
|
|
GameObject instantiated = Object.Instantiate(original);
|
|
if (PrefabUtility.IsPartOfNonAssetPrefabInstance(instantiated) && PrefabUtility.IsOutermostPrefabInstanceRoot(instantiated))
|
|
PrefabUtility.UnpackPrefabInstance(instantiated, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|
|
|
// Why would you do this?
|
|
if (instantiated.CompareTag("EditorOnly"))
|
|
instantiated.tag = "Untagged";
|
|
|
|
return instantiated;
|
|
}
|
|
|
|
private static bool HandlePreBuildEvent(Action<GameObject> preBuildEvent, GameObject instantiatedObject)
|
|
{
|
|
try
|
|
{
|
|
preBuildEvent.Invoke(instantiatedObject);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError($"[CCK:BuildUtility] Error occurred during PreBuildEvent: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool HandlePreBuildEvent(Action<Scene> preBuildEvent, Scene scene)
|
|
{
|
|
try
|
|
{
|
|
preBuildEvent.Invoke(scene);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError($"[CCK:BuildUtility] Error occurred during PreBuildEvent: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static void SetupNetworkUUIDs()
|
|
{
|
|
CVRInteractable[] interactables = Resources.FindObjectsOfTypeAll<CVRInteractable>();
|
|
CVRObjectSync[] objectSyncs = Resources.FindObjectsOfTypeAll<CVRObjectSync>();
|
|
CVRVideoPlayer[] videoPlayers = Resources.FindObjectsOfTypeAll<CVRVideoPlayer>();
|
|
|
|
CVRSpawnable[] spawnables = Resources.FindObjectsOfTypeAll<CVRSpawnable>();
|
|
|
|
GameInstanceController[] gameInstances = Resources.FindObjectsOfTypeAll<GameInstanceController>();
|
|
|
|
GunController[] gunControllers = Resources.FindObjectsOfTypeAll<GunController>();
|
|
|
|
List<string> UsedGuids = new List<string>();
|
|
|
|
foreach (var interactable in interactables)
|
|
{
|
|
foreach (var action in interactable.actions)
|
|
{
|
|
string guid;
|
|
do
|
|
{
|
|
guid = Guid.NewGuid().ToString();
|
|
} while (!string.IsNullOrEmpty(UsedGuids.Find(match => match == guid)));
|
|
UsedGuids.Add(guid);
|
|
|
|
action.guid = guid;
|
|
}
|
|
}
|
|
|
|
foreach (var objectSync in objectSyncs)
|
|
{
|
|
string guid;
|
|
do
|
|
{
|
|
guid = Guid.NewGuid().ToString();
|
|
} while (!string.IsNullOrEmpty(UsedGuids.Find(match => match == guid)));
|
|
UsedGuids.Add(guid);
|
|
|
|
var newserializedObject = new SerializedObject(objectSync);
|
|
newserializedObject.Update();
|
|
SerializedProperty _guidProperty = newserializedObject.FindProperty("guid");
|
|
_guidProperty.stringValue = guid;
|
|
newserializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
foreach (var player in videoPlayers)
|
|
{
|
|
Guid res;
|
|
if (player.playerId == null || !Guid.TryParse(player.playerId, out res))
|
|
{
|
|
string guid;
|
|
do
|
|
{
|
|
guid = Guid.NewGuid().ToString();
|
|
} while (!string.IsNullOrEmpty(UsedGuids.Find(match => match == guid)));
|
|
UsedGuids.Add(guid);
|
|
|
|
player.playerId = guid;
|
|
}
|
|
}
|
|
|
|
foreach (var spawnable in spawnables)
|
|
{
|
|
string guid;
|
|
do
|
|
{
|
|
guid = Guid.NewGuid().ToString();
|
|
} while (!string.IsNullOrEmpty(UsedGuids.Find(match => match == guid)));
|
|
|
|
if (spawnable.preGeneratedInstanceId == "")
|
|
{
|
|
UsedGuids.Add(guid);
|
|
spawnable.preGeneratedInstanceId = "ws~" + guid;
|
|
}
|
|
else
|
|
{
|
|
UsedGuids.Add(spawnable.preGeneratedInstanceId);
|
|
}
|
|
|
|
spawnable.spawnableType = CVRSpawnable.SpawnableType.WorldSpawnable;
|
|
}
|
|
|
|
int i = 0;
|
|
foreach (GameInstanceController gameInstance in gameInstances)
|
|
{
|
|
if (gameInstance.teams.Count == 0)
|
|
{
|
|
var team = new Team();
|
|
team.name = "Team";
|
|
team.color = Color.red;
|
|
team.playerLimit = 16;
|
|
team.index = i;
|
|
gameInstance.teams.Add(team);
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
foreach (var team in gameInstance.teams)
|
|
{
|
|
team.index = i;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var gunController in gunControllers)
|
|
{
|
|
string guid;
|
|
do
|
|
{
|
|
guid = Guid.NewGuid().ToString();
|
|
} while (!string.IsNullOrEmpty(UsedGuids.Find(match => match == guid)));
|
|
UsedGuids.Add(guid);
|
|
|
|
var newserializedObject = new SerializedObject(gunController);
|
|
newserializedObject.Update();
|
|
SerializedProperty _guidProperty = newserializedObject.FindProperty("referenceID");
|
|
_guidProperty.stringValue = guid;
|
|
newserializedObject.ApplyModifiedProperties();
|
|
}
|
|
}
|
|
|
|
private static void ClearLog()
|
|
{
|
|
var assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
|
|
var type = assembly.GetType("UnityEditor.LogEntries");
|
|
var method = type.GetMethod("Clear");
|
|
method.Invoke(new object(), null);
|
|
}
|
|
|
|
private static void EnforceVRSetting()
|
|
{
|
|
#if UNITY_2021_1_OR_NEWER
|
|
PlayerSettings.virtualRealitySupported = true;
|
|
PlayerSettings.stereoRenderingPath = StereoRenderingPath.Instancing;
|
|
XRSettings.enabled = false;
|
|
#else
|
|
PlayerSettings.virtualRealitySupported = true;
|
|
PlayerSettings.SetVirtualRealitySDKs(BuildTargetGroup.Standalone, new string[] { "None", "Oculus", "OpenVR", "MockHMD" });
|
|
PlayerSettings.stereoRenderingPath = StereoRenderingPath.SinglePass;
|
|
#endif
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#region PreBundleEvents
|
|
|
|
[Serializable]
|
|
public class PreAvatarBundleEvent : UnityEvent<GameObject> { }
|
|
|
|
[Serializable]
|
|
public class PrePropBundleEvent : UnityEvent<GameObject> { }
|
|
|
|
[Serializable]
|
|
public class PreWorldBundleEvent : UnityEvent<Scene> { }
|
|
|
|
#endregion
|
|
} |