initial upload
This commit is contained in:
156
Assets/Convai/Scripts/Editor/CustomPackage/CCToolsImporter.cs
Normal file
156
Assets/Convai/Scripts/Editor/CustomPackage/CCToolsImporter.cs
Normal file
@ -0,0 +1,156 @@
|
||||
#if !CC_TOOLS
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Convai.Scripts.Editor.CustomPackage
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public static class CCToolsImporter
|
||||
{
|
||||
private const string CC_TOOLS_SYMBOL = "CC_TOOLS";
|
||||
private const string URP_URL = "https://github.com/soupday/cc_unity_tools_URP.git";
|
||||
private const string HDRP_URL = "https://github.com/soupday/cc_unity_tools_HDRP.git";
|
||||
private const string BASE_URL = "https://github.com/soupday/cc_unity_tools_3D.git";
|
||||
private const int MAX_RETRY_ATTEMPTS = 5;
|
||||
private static int _retryCount = 0;
|
||||
|
||||
static CCToolsImporter()
|
||||
{
|
||||
EditorApplication.update += CheckAndInstallCCTools;
|
||||
}
|
||||
|
||||
private static void CheckAndInstallCCTools()
|
||||
{
|
||||
// Ensure we only attempt to check/install once
|
||||
EditorApplication.update -= CheckAndInstallCCTools;
|
||||
|
||||
// Check if the package is already installed
|
||||
var listRequest = Client.List(true);
|
||||
while (!listRequest.IsCompleted) { }
|
||||
|
||||
if (IsPackageAlreadyInstalled(listRequest))
|
||||
{
|
||||
Debug.Log("CC Tools package is already installed. Adding define symbol.");
|
||||
AddCCToolsDefineSymbol();
|
||||
return;
|
||||
}
|
||||
|
||||
// If not installed, proceed with installation
|
||||
TryInstallCCTools();
|
||||
}
|
||||
|
||||
private static bool IsPackageAlreadyInstalled(ListRequest listRequest)
|
||||
{
|
||||
return listRequest.Status == StatusCode.Success &&
|
||||
listRequest.Result.Any(package => package.packageId.Contains("cc_unity_tools"));
|
||||
}
|
||||
|
||||
private static void TryInstallCCTools()
|
||||
{
|
||||
// Determine appropriate package URL based on render pipeline
|
||||
string packageUrl = DeterminePackageUrl();
|
||||
|
||||
// Start package installation asynchronously
|
||||
AddRequest addRequest = Client.Add(packageUrl);
|
||||
|
||||
// Use a coroutine-friendly approach to handle installation
|
||||
EditorApplication.update += () => HandlePackageInstallation(addRequest);
|
||||
}
|
||||
|
||||
private static void HandlePackageInstallation(AddRequest addRequest)
|
||||
{
|
||||
// Check if the request is not completed
|
||||
if (!addRequest.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the update method to prevent multiple executions
|
||||
EditorApplication.update -= () => HandlePackageInstallation(addRequest);
|
||||
|
||||
switch (addRequest.Status)
|
||||
{
|
||||
case StatusCode.Success:
|
||||
Debug.Log("CC Tools has been installed successfully.");
|
||||
AddCCToolsDefineSymbol();
|
||||
|
||||
if (DeterminePackageUrl() == URP_URL)
|
||||
{
|
||||
ConvaiCustomPackageInstaller convaiCustomPackageInstaller = new ConvaiCustomPackageInstaller();
|
||||
convaiCustomPackageInstaller.InstallConvaiURPConverter();
|
||||
}
|
||||
break;
|
||||
case StatusCode.Failure:
|
||||
HandleInstallationFailure(addRequest);
|
||||
break;
|
||||
case StatusCode.InProgress:
|
||||
Debug.Log("CC Tools installation is in progress.");
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning("Unexpected status during CC Tools installation.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleInstallationFailure(AddRequest addRequest)
|
||||
{
|
||||
Debug.LogError($"CC Tools installation failed: {addRequest.Error.message}");
|
||||
|
||||
// Implement a retry mechanism
|
||||
if (_retryCount < MAX_RETRY_ATTEMPTS)
|
||||
{
|
||||
_retryCount++;
|
||||
Debug.Log($"Retrying CC Tools installation. Attempt {_retryCount} of {MAX_RETRY_ATTEMPTS}");
|
||||
|
||||
// Wait a short time before retrying to reduce chances of conflict
|
||||
EditorApplication.delayCall += () => { TryInstallCCTools(); };
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Maximum retry attempts reached. CC Tools installation failed.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string DeterminePackageUrl()
|
||||
{
|
||||
if (GraphicsSettings.currentRenderPipeline == null)
|
||||
return BASE_URL;
|
||||
|
||||
string renderPipelineName = GraphicsSettings.currentRenderPipeline.GetType().Name;
|
||||
|
||||
return renderPipelineName == "UniversalRenderPipelineAsset"
|
||||
? URP_URL
|
||||
: HDRP_URL;
|
||||
}
|
||||
|
||||
private static void AddCCToolsDefineSymbol()
|
||||
{
|
||||
foreach (BuildTarget target in Enum.GetValues(typeof(BuildTarget)))
|
||||
{
|
||||
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
|
||||
|
||||
if (group == BuildTargetGroup.Unknown)
|
||||
continue;
|
||||
|
||||
NamedBuildTarget namedTarget = NamedBuildTarget.FromBuildTargetGroup(group);
|
||||
List<string> symbols = PlayerSettings.GetScriptingDefineSymbols(namedTarget)
|
||||
.Split(';')
|
||||
.Select(d => d.Trim())
|
||||
.ToList();
|
||||
|
||||
if (!symbols.Contains(CC_TOOLS_SYMBOL))
|
||||
symbols.Add(CC_TOOLS_SYMBOL);
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbols(namedTarget, string.Join(";", symbols.ToArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38ca92565cfb4bdba6cdb861acd779e4
|
||||
timeCreated: 1719503566
|
||||
@ -0,0 +1,554 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Convai.Scripts.Runtime.LoggerSystem;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
|
||||
|
||||
namespace Convai.Scripts.Editor.CustomPackage
|
||||
{
|
||||
public class ConvaiCustomPackageInstaller : IActiveBuildTargetChanged
|
||||
{
|
||||
#region Constants
|
||||
|
||||
// XR Package Paths
|
||||
private const string AR_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiARUpgrader.unitypackage";
|
||||
private const string VR_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiVRUpgrader.unitypackage";
|
||||
private const string MR_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiMRUpgrader.unitypackage";
|
||||
private const string XR_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiXR.unitypackage";
|
||||
|
||||
private const string XR_PREFAB_PATH = "Assets/Convai/ConvaiXR/Prefabs/Convai Essentials - XR.prefab";
|
||||
|
||||
// Other Package Paths
|
||||
private const string IOS_BUILD_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiiOSBuild.unitypackage";
|
||||
private const string URP_CONVERTER_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiURPConverter.unitypackage";
|
||||
private const string TMP_PACKAGE_PATH = "Assets/Convai/Custom Packages/ConvaiCustomTMP.unitypackage";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private SetupTypes _currentSetup;
|
||||
private List<string> _setupSteps;
|
||||
private int _totalSetupSteps;
|
||||
private int _currentStep = 0;
|
||||
private string _currentStepDescription = "";
|
||||
private bool _assembliesLocked = false;
|
||||
|
||||
private BuildTarget _selectedARPlatform;
|
||||
private InstallationType _installationType;
|
||||
|
||||
public int callbackOrder { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
private enum SetupTypes
|
||||
{
|
||||
AR,
|
||||
VR,
|
||||
MR,
|
||||
iOS,
|
||||
NormalUnityPackage
|
||||
}
|
||||
|
||||
private enum InstallationType
|
||||
{
|
||||
Automatic,
|
||||
Manual
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public ConvaiCustomPackageInstaller()
|
||||
{
|
||||
}
|
||||
|
||||
public ConvaiCustomPackageInstaller(VisualElement root = null)
|
||||
{
|
||||
if (root != null)
|
||||
{
|
||||
InitializeUI(root);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Initialization
|
||||
|
||||
private void InitializeUI(VisualElement root)
|
||||
{
|
||||
root.Q<Button>("install-ar-package").clicked += () => StartPackageInstall(SetupTypes.AR);
|
||||
root.Q<Button>("install-vr-package").clicked += () => StartPackageInstall(SetupTypes.VR);
|
||||
root.Q<Button>("install-mr-package").clicked += () => StartPackageInstall(SetupTypes.MR);
|
||||
root.Q<Button>("install-ios-build-package").clicked += () =>
|
||||
{
|
||||
InitializeSetupSteps(SetupTypes.iOS);
|
||||
InstallConvaiPackage(IOS_BUILD_PACKAGE_PATH);
|
||||
TryToDownloadiOSDLL();
|
||||
};
|
||||
root.Q<Button>("install-urp-converter").clicked += () =>
|
||||
{
|
||||
InitializeSetupSteps(SetupTypes.NormalUnityPackage);
|
||||
InstallConvaiPackage(URP_CONVERTER_PACKAGE_PATH);
|
||||
EditorUtility.ClearProgressBar();
|
||||
};
|
||||
root.Q<Button>("convai-custom-tmp-package").clicked += () =>
|
||||
{
|
||||
InitializeSetupSteps(SetupTypes.NormalUnityPackage);
|
||||
InstallConvaiPackage(TMP_PACKAGE_PATH);
|
||||
EditorUtility.ClearProgressBar();
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Build Target Change Handling
|
||||
|
||||
public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget)
|
||||
{
|
||||
if (newTarget == BuildTarget.iOS) TryToDownloadiOSDLL();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Package Installation
|
||||
|
||||
private async void StartPackageInstall(SetupTypes setupType)
|
||||
{
|
||||
_currentSetup = setupType;
|
||||
|
||||
InitializeSetupSteps(setupType);
|
||||
|
||||
if (setupType == SetupTypes.AR)
|
||||
{
|
||||
if (!await ConfirmARPlatform()) return;
|
||||
if (!await ConfirmAutomaticInstallation(SetupTypes.AR)) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!await ConfirmInstallationType(setupType)) return;
|
||||
}
|
||||
|
||||
InitializeSetupSteps(setupType);
|
||||
_currentStep = 0;
|
||||
|
||||
ConvaiLogger.DebugLog($"Installation of {setupType} package has started... This process may take 3-5 minutes.", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
LockAssemblies();
|
||||
|
||||
try
|
||||
{
|
||||
await HandlePackageInstall();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConvaiLogger.Error($"An error occurred during package installation: {e.Message}", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnlockAssemblies();
|
||||
EditorUtility.ClearProgressBar();
|
||||
ConvaiLogger.DebugLog($"Convai {setupType} setup process completed.", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeSetupSteps(SetupTypes setupType)
|
||||
{
|
||||
_setupSteps = new List<string>();
|
||||
if (setupType == SetupTypes.AR && _selectedARPlatform != EditorUserBuildSettings.activeBuildTarget)
|
||||
{
|
||||
_setupSteps.Add($"Change build platform to {_selectedARPlatform}");
|
||||
}
|
||||
else if ((setupType == SetupTypes.VR || setupType == SetupTypes.MR) &&
|
||||
_installationType == InstallationType.Automatic &&
|
||||
EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android)
|
||||
{
|
||||
_setupSteps.Add("Change build platform to Android");
|
||||
}
|
||||
|
||||
switch (setupType)
|
||||
{
|
||||
case SetupTypes.AR:
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
_setupSteps.AddRange(_selectedARPlatform == BuildTarget.Android
|
||||
? new[] { "Universal Render Pipeline (URP)", "ARCore", "Convai AR Package", "Convai URP Converter" }
|
||||
: new[] { "Universal Render Pipeline (URP)", "ARKit", "Convai iOS DLL", "Convai iOS Build Package", "Convai AR Package", "Convai URP Converter", });
|
||||
}
|
||||
else
|
||||
{
|
||||
_setupSteps.Add("Convai AR Package");
|
||||
}
|
||||
|
||||
break;
|
||||
case SetupTypes.VR:
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
_setupSteps.AddRange(new[] { "Universal Render Pipeline (URP)", "OpenXR", "XR Interaction Toolkit", "Convai VR Package", "Convai URP Converter" });
|
||||
}
|
||||
else
|
||||
{
|
||||
_setupSteps.Add("Convai VR Package");
|
||||
}
|
||||
|
||||
break;
|
||||
case SetupTypes.MR:
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
_setupSteps.AddRange(new[] { "Universal Render Pipeline (URP)", "XR Management", "Oculus XR Plugin", "Convai URP Converter", "Meta XR SDK All", "Convai MR Package" });
|
||||
}
|
||||
else
|
||||
{
|
||||
_setupSteps.Add("Convai MR Package");
|
||||
}
|
||||
|
||||
break;
|
||||
case SetupTypes.iOS:
|
||||
_setupSteps.AddRange(new[] { "Convai iOS Build Package", "Convai iOS DLL" });
|
||||
break;
|
||||
case SetupTypes.NormalUnityPackage:
|
||||
_setupSteps.Add("Convai Custom Package");
|
||||
break;
|
||||
}
|
||||
|
||||
_totalSetupSteps = _setupSteps.Count;
|
||||
}
|
||||
|
||||
private async Task HandlePackageInstall()
|
||||
{
|
||||
switch (_currentSetup)
|
||||
{
|
||||
case SetupTypes.AR:
|
||||
await HandleARPackageInstall();
|
||||
break;
|
||||
case SetupTypes.VR:
|
||||
await HandleVRPackageInstall();
|
||||
break;
|
||||
case SetupTypes.MR:
|
||||
await HandleMRPackageInstall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleARPackageInstall()
|
||||
{
|
||||
ChangeBuildTarget(_selectedARPlatform);
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
await InitializeURPSetup();
|
||||
|
||||
if (_selectedARPlatform == BuildTarget.Android)
|
||||
{
|
||||
await InitializeARCoreSetup();
|
||||
}
|
||||
else if (_selectedARPlatform == BuildTarget.iOS)
|
||||
{
|
||||
await InitializeARKitSetup();
|
||||
TryToDownloadiOSDLL();
|
||||
InstallConvaiPackage(IOS_BUILD_PACKAGE_PATH);
|
||||
}
|
||||
|
||||
InstallConvaiPackage(AR_PACKAGE_PATH);
|
||||
InstallConvaiPackage(URP_CONVERTER_PACKAGE_PATH);
|
||||
}
|
||||
|
||||
private async Task HandleVRPackageInstall()
|
||||
{
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
ChangeBuildTarget(BuildTarget.Android);
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
await InitializeURPSetup();
|
||||
await InitializeOpenXRSetup();
|
||||
await InitializeXRInteractionToolkitSetup();
|
||||
InstallConvaiPackage(VR_PACKAGE_PATH);
|
||||
InstallConvaiPackage(URP_CONVERTER_PACKAGE_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
InstallConvaiPackage(XR_PACKAGE_PATH);
|
||||
await TryToInstantiateXRPrefab();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleMRPackageInstall()
|
||||
{
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
ChangeBuildTarget(BuildTarget.Android);
|
||||
await InitializeURPSetup();
|
||||
await InitializeXRManagementSetup();
|
||||
await InitializeOculusXRSetup();
|
||||
InstallConvaiPackage(URP_CONVERTER_PACKAGE_PATH);
|
||||
await InitializeMetaXRSDKAllSetup();
|
||||
InstallConvaiPackage(MR_PACKAGE_PATH);
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
else
|
||||
{
|
||||
InstallConvaiPackage(XR_PACKAGE_PATH);
|
||||
await TryToInstantiateXRPrefab();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Package Initialization
|
||||
|
||||
private async Task InitializePackageSetup(string packageName, string stepDescription)
|
||||
{
|
||||
UpdateProgressBar(stepDescription);
|
||||
if (IsPackageInstalled(packageName))
|
||||
{
|
||||
IncrementProgress($"{packageName} is already installed. Skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
ConvaiLogger.DebugLog($"{packageName} Package Installation Request sent to Package Manager.", ConvaiLogger.LogCategory.Editor);
|
||||
AddRequest request = Client.Add(packageName);
|
||||
|
||||
while (!request.IsCompleted)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
if (request.Status == StatusCode.Success)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
IncrementProgress($"Successfully installed: {packageName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvaiLogger.Error($"Failed to install {packageName}: {request.Error.message}", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
}
|
||||
|
||||
private Task InitializeURPSetup() => InitializePackageSetup("com.unity.render-pipelines.universal", "Installing Universal Render Pipeline (URP)");
|
||||
private Task InitializeARCoreSetup() => InitializePackageSetup("com.unity.xr.arcore@5.1.4", "Installing ARCore");
|
||||
private Task InitializeARKitSetup() => InitializePackageSetup("com.unity.xr.arkit@5.1.4", "Installing ARKit");
|
||||
private Task InitializeOpenXRSetup() => InitializePackageSetup("com.unity.xr.openxr@1.10.0", "Installing OpenXR");
|
||||
private Task InitializeOculusXRSetup() => InitializePackageSetup("com.unity.xr.oculus", "Installing Oculus XR Plugin");
|
||||
private Task InitializeMetaXRSDKAllSetup() => InitializePackageSetup("com.meta.xr.sdk.all", "Installing Meta XR SDK");
|
||||
private Task InitializeXRManagementSetup() => InitializePackageSetup("com.unity.xr.management", "Installing XR Management");
|
||||
private Task InitializeXRInteractionToolkitSetup() => InitializePackageSetup("com.unity.xr.interaction.toolkit@2.5.4", "Installing XR Interaction Toolkit");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Package Installation Methods
|
||||
|
||||
private void InstallConvaiPackage(string packagePath)
|
||||
{
|
||||
string packageName = Path.GetFileNameWithoutExtension(packagePath);
|
||||
UpdateProgressBar($"Installing {packageName}");
|
||||
|
||||
ConvaiLogger.DebugLog($"Importing: {packageName}", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
AssetDatabase.ImportPackage(packagePath, false);
|
||||
|
||||
IncrementProgress($"{packageName} Custom Unity Package Installation Completed.");
|
||||
}
|
||||
|
||||
private async Task TryToInstantiateXRPrefab()
|
||||
{
|
||||
if (_installationType != InstallationType.Manual || _currentSetup == SetupTypes.AR) return;
|
||||
|
||||
ConvaiLogger.DebugLog("Attempting to instantiate XR Prefab...", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
const int maxAttempts = 30;
|
||||
const int delayBetweenAttempts = 1000; // 1 second
|
||||
|
||||
for (int attempt = 0; attempt < maxAttempts; attempt++)
|
||||
{
|
||||
await DelayWithEditorAvailableCheck(delayBetweenAttempts);
|
||||
|
||||
if (TryInstantiatePrefab(out GameObject prefab))
|
||||
{
|
||||
ConvaiLogger.DebugLog($"Convai XR Prefab Instantiated on attempt {attempt + 1}.", ConvaiLogger.LogCategory.Editor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ConvaiLogger.Error($"Failed to load XR Prefab at path: {XR_PREFAB_PATH} after {maxAttempts} attempts.", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
|
||||
private bool TryInstantiatePrefab(out GameObject prefab)
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
prefab = AssetDatabase.LoadAssetAtPath<GameObject>(XR_PREFAB_PATH);
|
||||
|
||||
if (prefab != null)
|
||||
{
|
||||
PrefabUtility.InstantiatePrefab(prefab);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void TryToDownloadiOSDLL() => iOSDLLDownloader.TryToDownload();
|
||||
|
||||
private async Task<bool> ConfirmARPlatform()
|
||||
{
|
||||
string[] options = { "Android", "iOS" };
|
||||
int choice = await DisplayDialogComplex("Select AR Platform", "Choose the target platform for AR development:", options);
|
||||
|
||||
if (choice == -1 || choice == 1) return false; // User cancelled
|
||||
|
||||
_selectedARPlatform = choice == 0 ? BuildTarget.Android : BuildTarget.iOS;
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> ConfirmInstallationType(SetupTypes setupType)
|
||||
{
|
||||
string[] options = { "Automatic", "Manual" };
|
||||
string message = $"Choose the installation type for {setupType}:\n\n" +
|
||||
"Automatic Installation: All necessary packages will be installed, and your project settings will be changed to prepare for building. This option is suitable for new projects. " +
|
||||
"Using it on existing projects may pose risks and could lead to errors in your current setup.\n\n" +
|
||||
"Manual Installation: Only the Convai XR package will be installed, and your project settings will remain unchanged. This option is suitable for those who already have an existing XR project.";
|
||||
|
||||
int choice = await DisplayDialogComplex($"Select {setupType} Installation Type", message, options);
|
||||
|
||||
if (choice == -1 || choice == 1) return false; // User cancelled
|
||||
|
||||
_installationType = choice == 0 ? InstallationType.Automatic : InstallationType.Manual;
|
||||
|
||||
if (_installationType == InstallationType.Automatic)
|
||||
{
|
||||
return await ConfirmAutomaticInstallation(setupType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> ConfirmAutomaticInstallation(SetupTypes setupType)
|
||||
{
|
||||
InitializeSetupSteps(setupType);
|
||||
|
||||
string packageList = string.Join("\n", _setupSteps.Select(p => $"- {p}"));
|
||||
|
||||
string message = $"Automatic installation for {setupType} will change your project settings, import the following packages, and perform the following steps: \n\n" +
|
||||
$"{packageList}\n\n" +
|
||||
"* This process cannot be undone.\n\n" +
|
||||
"** Recommended for new projects.\n\n" +
|
||||
"Are you sure you want to proceed with the automatic installation?";
|
||||
|
||||
int choice = await DisplayDialogComplex("Confirm Automatic Installation", message, new[] { "Yes, proceed", "No, cancel" });
|
||||
|
||||
return choice == 0;
|
||||
}
|
||||
|
||||
private void ChangeBuildTarget(BuildTarget target)
|
||||
{
|
||||
UpdateProgressBar($"Changing Build Target to {target}");
|
||||
|
||||
if (EditorUserBuildSettings.activeBuildTarget != target)
|
||||
{
|
||||
ConvaiLogger.DebugLog($"Build Target Platform is being Changed to {target}...", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
BuildTargetGroup targetGroup = target == BuildTarget.Android ? BuildTargetGroup.Android : BuildTargetGroup.iOS;
|
||||
bool switched = EditorUserBuildSettings.SwitchActiveBuildTarget(targetGroup, target);
|
||||
|
||||
if (switched)
|
||||
{
|
||||
IncrementProgress($"Build Target changed to {target}");
|
||||
}
|
||||
else
|
||||
{
|
||||
IncrementProgress($"Failed to Change Build Target to {target}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IncrementProgress($"Build Target is already set to {target}");
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallConvaiURPConverter()
|
||||
{
|
||||
InitializeSetupSteps(SetupTypes.NormalUnityPackage);
|
||||
InstallConvaiPackage(URP_CONVERTER_PACKAGE_PATH);
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utility Methods
|
||||
|
||||
private static bool IsPackageInstalled(string packageName) =>
|
||||
PackageInfo.GetAllRegisteredPackages().Any(packageInfo => packageInfo.name == packageName);
|
||||
|
||||
private void LockAssemblies()
|
||||
{
|
||||
if (!_assembliesLocked)
|
||||
{
|
||||
EditorApplication.LockReloadAssemblies();
|
||||
_assembliesLocked = true;
|
||||
ConvaiLogger.DebugLog("Assemblies locked for package installation.", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnlockAssemblies()
|
||||
{
|
||||
if (_assembliesLocked)
|
||||
{
|
||||
EditorApplication.UnlockReloadAssemblies();
|
||||
_assembliesLocked = false;
|
||||
ConvaiLogger.DebugLog("Assemblies unlocked after package installation.", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DelayWithEditorAvailableCheck(int delayBetweenAttempts)
|
||||
{
|
||||
await Task.Delay(delayBetweenAttempts);
|
||||
|
||||
if (EditorApplication.isCompiling || EditorApplication.isUpdating)
|
||||
{
|
||||
ConvaiLogger.DebugLog("Waiting for Unity to finish compiling or updating...", ConvaiLogger.LogCategory.Editor);
|
||||
await DelayWithEditorAvailableCheck(delayBetweenAttempts); // Recursive call to wait again
|
||||
}
|
||||
}
|
||||
|
||||
private Task<int> DisplayDialogComplex(string title, string message, string[] options)
|
||||
{
|
||||
return Task.FromResult(EditorUtility.DisplayDialogComplex(title, message, options[0], "Cancel", options[1]));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Progress Management
|
||||
|
||||
private void UpdateProgressBar(string stepDescription)
|
||||
{
|
||||
_currentStepDescription = stepDescription;
|
||||
float progress = (float)_currentStep / _totalSetupSteps;
|
||||
int progressPercentage = Mathf.RoundToInt(progress * 100);
|
||||
string title = $"Convai {_currentSetup} Setup Progress";
|
||||
string info = $"Step {_currentStep + 1} of {_totalSetupSteps}: {_currentStepDescription} ({progressPercentage}% Complete)";
|
||||
|
||||
EditorUtility.DisplayProgressBar(title, info, progress);
|
||||
}
|
||||
|
||||
private void IncrementProgress(string completedStepDescription)
|
||||
{
|
||||
_currentStep++;
|
||||
ConvaiLogger.DebugLog(completedStepDescription, ConvaiLogger.LogCategory.Editor);
|
||||
if (_currentStep < _totalSetupSteps)
|
||||
{
|
||||
UpdateProgressBar(_setupSteps[_currentStep]);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53fd043db40ab5b4798e83e7f3204952
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
172
Assets/Convai/Scripts/Editor/CustomPackage/IOSDLLDownloader.cs
Normal file
172
Assets/Convai/Scripts/Editor/CustomPackage/IOSDLLDownloader.cs
Normal file
@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using Convai.Scripts.Runtime.LoggerSystem;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Convai.Scripts.Editor.CustomPackage
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor window for downloading and extracting iOS DLL from a specified URL.
|
||||
/// </summary>
|
||||
public class iOSDLLDownloader
|
||||
{
|
||||
private const string DOWNLOAD_ENDPOINT_URL = "https://api.convai.com/user/downloadAsset";
|
||||
private const string RELATIVE_PATH = "Convai/Plugins/gRPC/Grpc.Core/runtimes";
|
||||
private static string _targetDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to download the iOS DLL if it doesn't already exist.
|
||||
/// </summary>
|
||||
public static void TryToDownload()
|
||||
{
|
||||
if (CheckFileExistence()) return;
|
||||
ConvaiLogger.DebugLog("<color=lime>The iOS DLL download has started...</color>", ConvaiLogger.LogCategory.Editor);
|
||||
DownloadAndExtract(GetTargetDirectory());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to download and extract the ZIP file from the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="outputPath">Directory to extract the contents to.</param>
|
||||
/// <returns></returns>
|
||||
private static void DownloadAndExtract(string outputPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string downloadURL = GetDownloadURL();
|
||||
|
||||
if (downloadURL == null)
|
||||
ConvaiLogger.Error("Failed to get download URL. Please check the API key and try again.", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
using UnityWebRequest webRequest = UnityWebRequest.Get(downloadURL);
|
||||
webRequest.SendWebRequest();
|
||||
|
||||
while (!webRequest.isDone)
|
||||
{
|
||||
float progress = webRequest.downloadProgress;
|
||||
EditorUtility.DisplayProgressBar("Downloading required iOS DLL...",
|
||||
"Please wait for the download to finish and do not close Unity. " + (int)(progress * 100) + "%", progress);
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (webRequest.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError)
|
||||
{
|
||||
ConvaiLogger.Error($"Error downloading file: {webRequest.error}", ConvaiLogger.LogCategory.Editor);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] results = webRequest.downloadHandler.data;
|
||||
string zipPath = Path.Combine(Path.GetTempPath(), "downloaded.zip");
|
||||
File.WriteAllBytes(zipPath, results);
|
||||
ExtractZipFile(zipPath, outputPath);
|
||||
File.Delete(zipPath);
|
||||
ConvaiLogger.Info($"Downloaded and extracted to {outputPath}" + "/ios/libgrpc.a", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
// Refresh the asset database to make sure the new files are recognized
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConvaiLogger.Error(e.Message, ConvaiLogger.LogCategory.Editor);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the download URL from Convai API.
|
||||
/// </summary>
|
||||
/// <returns>The download URL or null.</returns>
|
||||
private static string GetDownloadURL()
|
||||
{
|
||||
if (!ConvaiAPIKeySetup.GetAPIKey(out string apiKey)) return null;
|
||||
|
||||
string body = @"{""service_name"": ""unity-builds"",""version"":""ios""}";
|
||||
|
||||
WebRequest request = WebRequest.Create(DOWNLOAD_ENDPOINT_URL);
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/json";
|
||||
request.Headers.Add("CONVAI-API-KEY", apiKey);
|
||||
|
||||
using (StreamWriter streamWriter = new(request.GetRequestStream()))
|
||||
{
|
||||
streamWriter.Write(body);
|
||||
}
|
||||
|
||||
using (WebResponse response = request.GetResponse())
|
||||
using (Stream dataStream = response.GetResponseStream())
|
||||
using (StreamReader reader = new(dataStream))
|
||||
{
|
||||
JObject responseJson = JObject.Parse(reader.ReadToEnd());
|
||||
return (string)responseJson["download_link"];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the contents of a ZIP file to the specified output folder.
|
||||
/// </summary>
|
||||
/// <param name="zipFilePath">Path to the ZIP file.</param>
|
||||
/// <param name="outputFolder">Directory to extract the contents to.</param>
|
||||
private static void ExtractZipFile(string zipFilePath, string outputFolder)
|
||||
{
|
||||
if (!Directory.Exists(outputFolder)) Directory.CreateDirectory(outputFolder);
|
||||
|
||||
using (ZipArchive archive = ZipFile.OpenRead(zipFilePath))
|
||||
{
|
||||
float totalEntries = archive.Entries.Count;
|
||||
float currentEntry = 0;
|
||||
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
string fullPath = Path.Combine(outputFolder, entry.FullName);
|
||||
|
||||
// Ensure the directory exists
|
||||
string directoryName = Path.GetDirectoryName(fullPath);
|
||||
if (!Directory.Exists(directoryName))
|
||||
if (directoryName != null)
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
// Extract the entry to the output directory
|
||||
entry.ExtractToFile(fullPath, true);
|
||||
|
||||
// Update the progress bar
|
||||
currentEntry++;
|
||||
float progress = currentEntry / totalEntries;
|
||||
EditorUtility.DisplayProgressBar("Extracting", $"Extracting file {entry.Name}...", progress);
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target directory for extracting the files.
|
||||
/// </summary>
|
||||
/// <returns>Target directory path.</returns>
|
||||
private static string GetTargetDirectory()
|
||||
{
|
||||
_targetDirectory = Path.Combine(Application.dataPath, RELATIVE_PATH);
|
||||
if (!Directory.Exists(_targetDirectory)) Directory.CreateDirectory(_targetDirectory);
|
||||
return _targetDirectory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the iOS DLL file already exists.
|
||||
/// </summary>
|
||||
/// <returns>True if the file exists, otherwise false.</returns>
|
||||
private static bool CheckFileExistence()
|
||||
{
|
||||
string fullPath = Path.Combine(Application.dataPath, RELATIVE_PATH + "/ios/libgrpc.a");
|
||||
bool fileExists = File.Exists(fullPath);
|
||||
if (fileExists) ConvaiLogger.DebugLog("iOS DLL already exists. No need to download.", ConvaiLogger.LogCategory.Editor);
|
||||
|
||||
return fileExists;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 526eafca5259e824591be577e0305054
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user