using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace JustTrack
{
///
/// Provides Unity editor menu items for the justtrack SDK integration and configuration.
///
public class JustTrackMenu
{
///
/// Opens the justtrack SDK settings in the Unity Project Settings window.
///
[MenuItem("justtrack/Show Settings", false, 100)]
public static void ShowSettings()
{
SettingsService.OpenProjectSettings(JustTrackSettingsIMGUIRegister.SettingsPath);
}
///
/// Validates the current justtrack SDK configuration and displays any errors or warnings.
///
[MenuItem("justtrack/Validate Configuration", false, 101)]
public static void ValidateConfiguration()
{
Debug.ClearDeveloperConsole();
ClearConsole();
var settings = JustTrackUtils.GetOrCreateSettings();
if (settings == null)
{
Debug.LogError("justtrack SDK configuration was not correctly loaded");
return;
}
JustTrackUtils.Validate(settings, (validateResult) =>
{
foreach (string error in validateResult.Errors)
{
Debug.LogError(error);
}
foreach (string warning in validateResult.Warnings)
{
Debug.LogWarning(warning);
}
if (validateResult.Errors.Count == 0)
{
Debug.Log("justtrack configuration is valid");
}
});
}
///
/// Creates an instance of the justtrack SDK prefab in the current scene.
///
[MenuItem("justtrack/Create SDK Instance", false, 102)]
public static void CreateInstance()
{
var path = "Packages/io.justtrack.justtrack-unity-sdk/Prefabs/JustTrackSDK.prefab";
var fallback = "Assets/JustTrack/Prefabs/JustTrackSDK.prefab";
UnityEngine.Object prefab;
if (File.Exists(path))
{
prefab = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject));
}
else
{
prefab = AssetDatabase.LoadAssetAtPath(fallback, typeof(GameObject));
}
PrefabUtility.InstantiatePrefab(prefab);
}
///
/// Generates and displays a comprehensive diagnostic report of the justtrack SDK integration.
///
[MenuItem("justtrack/Print Diagnostics", false, 103)]
public static void PrintDiagnostics()
{
JustTrackSettings settings = JustTrackUtils.GetSettings();
string[] thirdPartySDKs = new string[]
{
"com.ironsource.sdk",
"com.appsflyer.af-android-sdk",
"firebase-installations",
"com.unity3d.ads",
"com.chartboost:chartboost-sdk",
"com.chartboost.mediation",
"com.applovin.applovin-sdk",
};
var commonInfoLines = new List();
var androidInfoLines = new List();
var iOSInfoLines = new List();
commonInfoLines.Add($"Unity Version: {Application.unityVersion}");
commonInfoLines.Add($"Version: {JustTrackSDK.GetVersion()}");
var generatedFiles = new List();
if (JustTrackCodeGenerator.HasFBAudienceNetworkAdpt())
{
generatedFiles.Add("FacebookAudienceNetworkAdapter.cs");
}
commonInfoLines.Add("Generated Files: " + JoinElements(generatedFiles));
commonInfoLines.Add("Scene Count: " + SceneManager.sceneCount);
commonInfoLines.Add(AnalyizeScene("Main Scene", SceneManager.GetSceneByBuildIndex(0)));
for (int i = 1; i < SceneManager.sceneCount; i++)
{
commonInfoLines.Add(AnalyizeScene("Scene " + i, SceneManager.GetSceneByBuildIndex(i)));
}
androidInfoLines.Add("API Token: " + settings.AndroidApiToken);
androidInfoLines.Add("Package ID: " + PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android));
androidInfoLines.Add("Scripting Backend: " + (JustTrackUtils.IsIL2CPP(true) ? "IL2CPP" : "Mono"));
androidInfoLines.Add("Automatic Purchase Tracking: " + !settings.AndroidDisableAutomaticInAppPurchaseTracking);
iOSInfoLines.Add("API Token: " + settings.IosApiToken);
iOSInfoLines.Add("Package ID: " + PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.iOS));
iOSInfoLines.Add("Scripting Backend: " + (JustTrackUtils.IsIL2CPP(false) ? "IL2CPP" : "Mono"));
iOSInfoLines.Add("Automatic Purchase Tracking: " + !settings.IosDisableAutomaticInAppPurchaseTracking);
var justtrackSdks = new List();
var nativeSdks = new List();
// Check external libs in Assets folder
string[] sdkExtensions = new string[] { ".dll", ".jar", ".a", ".framework", ".aar" };
foreach (string assetPath in AssetDatabase.GetAllAssetPaths())
{
if (!ArrayUtility.Contains(sdkExtensions, Path.GetExtension(assetPath)))
{
continue;
}
string fileName = Path.GetFileName(assetPath);
Match match = Regex.Match(fileName, @"^(.*)-(\d+(\.\d+)*.*)$");
string sdkName = fileName;
string sdkVersion = string.Empty;
if (match.Success)
{
sdkName = match.Groups[1].Value;
sdkVersion = match.Groups[2].Value;
}
foreach (var thirdPartySDK in thirdPartySDKs)
{
if (fileName.Contains(thirdPartySDK))
{
nativeSdks.Add($"{sdkName}: {sdkVersion}");
break;
}
}
if (fileName.Contains("justtrack"))
{
justtrackSdks.Add($"{sdkName}: {sdkVersion} (native)");
}
}
nativeSdks.Sort();
JustTrackUtils.Validate(settings, (validateResult) =>
{
var verificationBlock = new List();
foreach (string error in validateResult.Errors)
{
verificationBlock.Add("Error: " + error);
}
foreach (string warning in validateResult.Warnings)
{
verificationBlock.Add("Warning: " + warning);
}
if (validateResult.Errors.Count == 0)
{
verificationBlock.Add("Verification Status: valid");
}
else
{
verificationBlock.Add("Verification Status: invalid");
}
var report = CombineBlock("Common", commonInfoLines) +
CombineBlock("Native version", justtrackSdks) +
CombineBlock("Android", androidInfoLines) +
CombineBlock("iOS", iOSInfoLines) +
CombineBlock("Native Dependencies", nativeSdks) +
CombineBlock("Verification", verificationBlock);
DisplayDiagnoseDialog(report);
});
}
private static string AnalyizeScene(string prefix, Scene scene)
{
if (scene == null)
{
return prefix + ": No scene found or loaded";
}
if (!scene.IsValid())
{
return prefix + ": " + scene.name + " (INVALID)";
}
GameObject[] rootObjects;
try
{
rootObjects = scene.GetRootGameObjects();
}
catch (Exception e)
{
return prefix + ": " + scene.name + " (ERROR: " + e + ")";
}
foreach (GameObject go in rootObjects)
{
if (HasJustTrackSDK(go))
{
return prefix + ": " + scene.name + " (contains JustTrack SDK)";
}
}
return prefix + ": " + scene.name + " (Does not contain JustTrack SDK)";
}
private static string JoinElements(List elements)
{
if (elements.Count == 0)
{
return "-";
}
return string.Join(", ", elements.ToArray());
}
private static bool HasJustTrackSDK(GameObject gameObject)
{
return gameObject.GetComponentInChildren() != null;
}
private static string CombineBlock(string name, List block)
{
if (block.Count == 0)
{
block.Add("- empty -");
}
return "\n### " + name + " ###\n\n" + string.Join("\n", block.ToArray()) + "\n";
}
private static void DisplayDiagnoseDialog(string dialogText)
{
int option = EditorUtility.DisplayDialogComplex("Integration Scan", dialogText, "OK", "Copy", null);
if (option == 1)
{
GUIUtility.systemCopyBuffer = dialogText;
}
}
///
/// Opens the justtrack SDK Android documentation in the default web browser.
///
[MenuItem("justtrack/Android Docs", false, 200)]
public static void AndroidDocs()
{
Application.OpenURL("https://docs.justtrack.io/sdk/overview");
}
///
/// Opens the justtrack SDK iOS documentation in the default web browser.
///
[MenuItem("justtrack/iOS Docs", false, 201)]
public static void IOSDocs()
{
Application.OpenURL("https://docs.justtrack.io/sdk/overview");
}
///
/// Opens the justtrack SDK Unity documentation in the default web browser.
///
[MenuItem("justtrack/Unity Docs", false, 202)]
public static void UnityDocs()
{
Application.OpenURL("https://docs.justtrack.io/sdk/overview");
}
///
/// Opens the justtrack SDK WebGL documentation in the default web browser.
///
[MenuItem("justtrack/WebGL Docs", false, 202)]
public static void WebGLDocs()
{
Application.OpenURL("https://docs.justtrack.io/sdk/overview");
}
private static void ClearConsole()
{
try
{
var assembly = Assembly.GetAssembly(typeof(SceneView));
var type = assembly.GetType("UnityEditor.LogEntries");
var method = type.GetMethod("Clear");
method.Invoke(new object(), null);
}
catch (Exception)
{
// well... then it seems like we don't clear the console today
}
}
}
}