namespace UIWidgets
{
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
///
/// Compatibility functions.
///
public static class Compatibility
{
#if UNITY_EDITOR
///
/// Upgrade the specified target.
///
/// Target type.
/// Target.
public static void Upgrade(T target)
where T : Component, IUpgradeable
{
target.Upgrade();
MarkDirty(target);
}
///
/// Mark specified component as dirty.
///
/// Type of the component.
/// Component.
public static void MarkDirty(T target)
where T : Component
{
#if UNITY_2018_3_OR_NEWER
if (PrefabUtility.IsPartOfAnyPrefab(target))
#endif
{
PrefabUtility.RecordPrefabInstancePropertyModifications(target);
}
if (IsPrefab(target))
{
EditorUtility.SetDirty(target);
}
}
///
/// Remove text previously added to force recompile.
///
/// Label.
/// True if text removed; otherwise false
[Obsolete("Replaced with RemoveForceRecompileByGUID().")]
public static bool RemoveForceRecompileByLabel(string label)
{
var path = Utilities.GetAssetPath(label);
if (path == null)
{
return false;
}
if (Directory.Exists(path))
{
RemoveForceRecompileFolder(path);
}
else
{
RemoveForceRecompileFile(path);
}
AssetDatabase.Refresh();
return true;
}
static void RemoveForceRecompileFolder(string path)
{
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.cs", SearchOption.AllDirectories);
foreach (var file in files)
{
RemoveForceRecompileFile(file.FullName);
}
}
static void RemoveForceRecompileFile(string filepath)
{
var lines = new List(File.ReadAllLines(filepath));
var prefix = "// Force script reload at ";
if (lines[lines.Count - 1].StartsWith(prefix, StringComparison.InvariantCulture))
{
lines.RemoveAt(lines.Count - 1);
File.WriteAllText(filepath, string.Join("\r\n", lines.ToArray()));
File.SetLastWriteTimeUtc(filepath, DateTime.UtcNow);
}
}
///
/// Use this function to create a Prefab Asset at the given path from the given GameObject including any children in the Scene without modifying the input objects.
///
/// The path to save the Prefab at.
/// The GameObject to save as a Prefab.
/// Prefab instance.
public static GameObject CreatePrefab(string assetPath, GameObject instanceRoot)
{
#if UNITY_2018_3_OR_NEWER
bool success;
var prefab = PrefabUtility.SaveAsPrefabAsset(instanceRoot, assetPath, out success);
if (!success)
{
Debug.LogError("Prefab not saved.");
}
return prefab;
#else
return PrefabUtility.CreatePrefab(assetPath, instanceRoot);
#endif
}
static void ForceRecompileFolder(string path)
{
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.cs", SearchOption.AllDirectories);
foreach (var file in files)
{
ForceRecompileFile(file.FullName);
}
}
///
/// Force recompile by changing specified script content.
///
/// Path to file.
static void ForceRecompileFile(string filepath)
{
var lines = new List(File.ReadAllLines(filepath));
var prefix = "// Force script reload at ";
if (lines[lines.Count - 1].StartsWith(prefix, StringComparison.InvariantCulture))
{
lines[lines.Count - 1] = prefix + DateTime.Now.ToString();
}
else
{
lines.Add(prefix + DateTime.Now.ToString());
}
File.WriteAllText(filepath, string.Join("\r\n", lines.ToArray()));
File.SetLastWriteTimeUtc(filepath, DateTime.UtcNow);
}
///
/// Remove text previously added to force recompile.
///
/// Scripts GUIDs.
public static void RemoveForceRecompileByGUID(string[] guids)
{
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path))
{
Debug.LogWarning("Cannot find path by GUID: " + guids[0]);
continue;
}
if (Directory.Exists(path))
{
RemoveForceRecompileFolder(path);
}
else
{
RemoveForceRecompileFile(path);
}
}
AssetDatabase.Refresh();
}
///
/// Force recompile by changing scripts content.
///
/// Scripts GUIDs.
public static void ForceRecompileByGUID(string[] guids)
{
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path))
{
Debug.LogWarning("Cannot find path by GUID: " + guids[0]);
continue;
}
if (Directory.Exists(path))
{
ForceRecompileFolder(path);
}
else
{
ForceRecompileFile(path);
}
}
AssetDatabase.Refresh();
}
///
/// Force recompile by changing scripts content.
///
/// Label.
/// True if recompilation done; otherwise false
[Obsolete("Replaced with ForceRecompileByGUID().")]
public static bool ForceRecompileByLabel(string label)
{
var path = Utilities.GetAssetPath(label);
if (path == null)
{
return false;
}
if (Directory.Exists(path))
{
ForceRecompileFolder(path);
}
else
{
ForceRecompileFile(path);
}
AssetDatabase.Refresh();
return true;
}
///
/// Get TextMeshPro version.
///
/// TextMeshPro version.
public static string GetTMProVersion()
{
Dictionary guid2version = new Dictionary()
{
{ "496f2e385b0c62542b5c739ccfafd8da", "V1Script" }, // first assetstore version
{ "89f0137620f6af44b9ba852b4190e64e", "V2DLL" }, // unity assetstore version
{ "f4688fdb7df04437aeb418b961361dc5", "V3Package" }, // unity package version
};
foreach (var gv in guid2version)
{
var path = AssetDatabase.GUIDToAssetPath(gv.Key);
if (!string.IsNullOrEmpty(path))
{
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1
if (gv.Value == "V1Script")
{
return gv.Value + "NoInput";
}
#endif
return gv.Value;
}
}
return null;
}
///
/// Imports package at packagePath into the current project.
/// If interactive is true, an import package dialog will be opened, else all assets in the package will be imported into the current project.
///
/// Package path.
/// Show import package dialog.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "interactive", Justification = "Reviewed.")]
public static void ImportPackage(string packagePath, bool interactive = false)
{
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
AssetDatabase.ImportPackage(packagePath, interactive);
#else
EditorUtility.DisplayDialog(
"Warning",
"Unity 4.6 and Unity 4.7 requires to manually import package \"" + packagePath + "\".",
"OK");
#endif
}
///
/// Set ScrollRect viewport.
///
/// ScrollRect.
/// Viewport.
#if !(UNITY_5_3 || UNITY_5_3_OR_NEWER)
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "scrollRect", Justification = "Reviewed.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "viewport", Justification = "Reviewed.")]
#endif
public static void SetViewport(ScrollRect scrollRect, RectTransform viewport)
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
scrollRect.viewport = viewport;
#endif
}
///
/// Save scene if user wants to.
///
/// True if user saved scene; otherwise false.
public static bool SceneSave()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
return UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
#else
return EditorApplication.SaveCurrentSceneIfUserWantsTo();
#endif
}
///
/// Save scene with the specified path.
///
/// Path.
public static void SceneSave(string path)
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene(), path);
#else
EditorApplication.SaveScene(path);
#endif
}
///
/// Create new empty scene.
///
public static void SceneNew()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.EmptyScene, UnityEditor.SceneManagement.NewSceneMode.Single);
#else
EditorApplication.NewScene();
var camera = GameObject.Find("Main Camera");
if (camera != null)
{
UnityEngine.Object.DestroyImmediate(camera);
}
#endif
}
///
/// Returns the first asset object of type T at given path assetPath.
///
/// The asset at path.
/// Path.
/// Asset type.
public static T LoadAssetAtPath(string path)
where T : UnityEngine.Object
{
#if UNITY_4_6 || UNITY_4_7
return (T)AssetDatabase.LoadAssetAtPath(path, typeof(T));
#elif UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
return AssetDatabase.LoadAssetAtPath(path);
#else
return Resources.LoadAssetAtPath(path);
#endif
}
///
/// Create EventSystem.
///
public static void CreateEventSystem()
{
var eventSystemGO = new GameObject("EventSystem");
eventSystemGO.AddComponent();
eventSystemGO.AddComponent();
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
eventSystemGO.AddComponent();
#endif
Undo.RegisterCreatedObjectUndo(eventSystemGO, "Create " + eventSystemGO.name);
}
#endif
#if UNITY_2018_3_OR_NEWER
///
/// Check if request ended with any error.
///
/// Request.
/// true if request has error; otherwise false.
public static bool IsError(UnityWebRequest request)
{
#if UNITY_2020_2_OR_NEWER
return (request.result == UnityWebRequest.Result.ConnectionError)
|| (request.result == UnityWebRequest.Result.DataProcessingError)
|| (request.result == UnityWebRequest.Result.ProtocolError);
#else
return request.isNetworkError || request.isHttpError;
#endif
}
#endif
///
/// Clones the object original and returns the clone.
///
/// Type of the original object.
/// An existing object that you want to make a copy of.
/// The instantiated clone.
public static T Instantiate(T original)
where T : UnityEngine.Object
{
var result = UnityEngine.Object.Instantiate(original);
#if UNITY_4_6 || UNITY_4_7
return result as T;
#else
return result;
#endif
}
///
/// Clones the object original and returns the clone.
///
/// Type of the original object.
/// An existing object that you want to make a copy of.
/// Parent.
/// The instantiated clone.
public static T Instantiate(T original, Transform parent)
where T : Component
{
var result = UnityEngine.Object.Instantiate(original, parent);
#if UNITY_4_6 || UNITY_4_7
return result as T;
#else
return result;
#endif
}
///
/// Set layout group child size settings.
///
/// Layout group.
/// Control width.
/// Control height.
#if !UNITY_2017_1_OR_NEWER
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "width", Justification = "Reviewed.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "lg", Justification = "Reviewed.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "height", Justification = "Reviewed.")]
#endif
public static void SetLayoutChildControlsSize(HorizontalOrVerticalLayoutGroup lg, bool width, bool height)
{
#if UNITY_2017_1_OR_NEWER
lg.childControlWidth = width;
lg.childControlHeight = height;
#endif
}
///
/// Get layout group childControlWidth setting.
///
/// Layout group.
/// childControlWidth value.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "lg", Justification = "Conditional compilation.")]
public static bool GetLayoutChildControlWidth(HorizontalOrVerticalLayoutGroup lg)
{
#if UNITY_2017_1_OR_NEWER
return lg.childControlWidth;
#else
return true;
#endif
}
///
/// Get layout group childControlHeight setting.
///
/// Layout group.
/// childControlHeight value.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "lg", Justification = "Conditional compilation.")]
public static bool GetLayoutChildControlHeight(HorizontalOrVerticalLayoutGroup lg)
{
#if UNITY_2017_1_OR_NEWER
return lg.childControlHeight;
#else
return true;
#endif
}
///
/// Gets the cursor mode.
///
/// The cursor mode.
public static CursorMode GetCursorMode()
{
#if UNITY_WEBGL
return CursorMode.ForceSoftware;
#else
return CursorMode.Auto;
#endif
}
///
/// Gets the components.
///
/// Source.
/// Components.
/// Component type.
public static void GetComponents(GameObject source, List components)
where T : class
{
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
source.GetComponents(components);
#else
foreach (var component in source.GetComponents(typeof(T)))
{
components.Add(component as T);
}
#endif
}
///
/// Gets the component.
///
/// The component.
/// Source.
/// Component type.
public static T GetComponent(Component source)
where T : class
{
return GetComponent(source.gameObject);
}
///
/// Gets the component.
///
/// The component.
/// Source.
/// Component type.
public static T GetComponent(GameObject source)
where T : class
{
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
return source.GetComponent();
#else
return source.GetComponent(typeof(T)) as T;
#endif
}
///
/// Disable and enable gameobject back to apply shader variables changes.
///
/// Target gameobject.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "go", Justification = "Conditional compilation.")]
public static void ToggleGameObject(GameObject go)
{
#if UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
go.SetActive(false);
go.SetActive(true);
#endif
}
///
/// Disable and enable gameobject back to apply shader variables changes.
///
/// Target component.
public static void ToggleGameObject(Component component)
{
ToggleGameObject(component.gameObject);
}
///
/// Returns all components of Type T in the target GameObject or any of its children.
///
/// Type.
/// Target gameobject or component.
/// Should Components on inactive GameObjects be included in the found set? includeInactive decides which children of the GameObject will be searched. The GameObject that you call GetComponentsInChildren on is always searched regardless.
/// A list of all found components matching the specified type.
public static void GetComponentsInChildren(Component target, bool includeInactive, List results)
where T : class
{
#if UNITY_2017_1_OR_NEWER
target.GetComponentsInChildren(includeInactive, results);
#else
results.Clear();
var components = target.GetComponentsInChildren(typeof(T), includeInactive);
for (int i = 0; i < components.Length; i++)
{
results.Add(components[i] as T);
}
#endif
}
///
/// Returns the component of Type T in the GameObject or any of its children using depth first search.
///
/// Component type.
/// Component.
/// Should Components on inactive GameObjects be included in the found set? includeInactive decides which children of the GameObject will be searched. The GameObject that you call GetComponentsInChildren on is always searched regardless.
/// A component of the matching type, if found.
public static T GetComponentInChildren(Component component, bool includeInactive)
where T : Component
{
#if UNITY_2017_1_OR_NEWER
return component.GetComponentInChildren(includeInactive);
#else
var children = component.GetComponentsInChildren(includeInactive);
return (children.Length > 0) ? children[0] : null;
#endif
}
///
/// Get root gameobjects at scene.
///
/// Root gameobjects.
public static List GetRootGameObjects()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
var gos = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
return new List(gos);
#else
var gos = new List();
foreach (var go in Resources.FindObjectsOfTypeAll())
{
if (go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave)
{
continue;
}
if (!EditorUtility.IsPersistent(go.transform.root.gameObject))
{
continue;
}
if (go.transform.parent != null)
{
continue;
}
gos.Add(go);
}
return gos;
#endif
}
///
/// Check is component is part of the prefab.
///
/// Component.
/// true if component is part of the prefab; otherwise false.
public static bool IsPrefab(Component component)
{
#if UNITY_EDITOR
#if UNITY_2018_2_OR_NEWER
if ((PrefabUtility.GetCorrespondingObjectFromSource(component) == null)
&& (PrefabUtility.GetPrefabInstanceHandle(component) != null))
{
return true;
}
#else
if ((PrefabUtility.GetPrefabParent(component.gameObject) == null)
&& (PrefabUtility.GetPrefabObject(component.gameObject) != null))
{
return true;
}
#endif
#endif
return false;
}
#if CSHARP_7_3_OR_NEWER
///
/// Get empty array.
///
/// Type of array.
/// Empty array.
public static T[] EmptyArray()
{
return Array.Empty();
}
#else
///
/// Empty array class.
///
/// Type of array.
static class Empty
{
///
/// Value.
///
public static readonly T[] Value;
static Empty()
{
Value = new T[0];
}
}
///
/// Get empty array.
///
/// Type of array.
/// Empty array.
public static T[] EmptyArray()
{
return Empty.Value;
}
#endif
}
}