mirror of
https://github.com/Cardidi/dotween-upm-fork.git
synced 2025-12-20 01:06:02 +08:00
419 lines
21 KiB
C#
419 lines
21 KiB
C#
// Author: Daniele Giardini - http://www.demigiant.com
|
|
// Created: 2014/12/24 13:50
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using DG.Tweening;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace DG.DOTweenEditor
|
|
{
|
|
public static class EditorUtils
|
|
{
|
|
public static string projectPath { get; private set; } // Without final slash
|
|
public static string assetsPath { get; private set; } // Without final slash
|
|
public static bool hasPro { get { if (!_hasCheckedForPro) CheckForPro(); return _hasPro; } }
|
|
public static string proVersion { get { if (!_hasCheckedForPro) CheckForPro(); return _proVersion; } }
|
|
// Editor path from Assets (not included) with final slash, in AssetDatabase format (/)
|
|
public static string editorADBDir { get { if (string.IsNullOrEmpty(_editorADBDir)) StoreEditorADBDir(); return _editorADBDir; } }
|
|
// With final slash (system based) - might be NULL in case users are not using a parent Demigiant folder
|
|
public static string demigiantDir { get { if (string.IsNullOrEmpty(_demigiantDir)) StoreDOTweenDirs(); return _demigiantDir; } }
|
|
// With final slash (system based)
|
|
public static string dotweenDir { get { if (string.IsNullOrEmpty(_dotweenDir)) StoreDOTweenDirs(); return _dotweenDir; } }
|
|
// With final slash (system based)
|
|
public static string dotweenProDir { get { if (string.IsNullOrEmpty(_dotweenProDir)) StoreDOTweenDirs(); return _dotweenProDir; } }
|
|
// With final slash (system based)
|
|
public static string dotweenProEditorDir { get { if (string.IsNullOrEmpty(_dotweenProEditorDir)) StoreDOTweenDirs(); return _dotweenProEditorDir; } }
|
|
// With final slash (system based)
|
|
public static string dotweenModulesDir { get { if (string.IsNullOrEmpty(_dotweenModulesDir)) StoreDOTweenDirs(); return _dotweenModulesDir; } }
|
|
public static bool isOSXEditor { get; private set; }
|
|
public static string pathSlash { get; private set; } // for full paths
|
|
public static string pathSlashToReplace { get; private set; } // for full paths
|
|
|
|
static readonly StringBuilder _Strb = new StringBuilder();
|
|
static bool _hasPro;
|
|
static string _proVersion;
|
|
static bool _hasCheckedForPro;
|
|
static string _editorADBDir;
|
|
static string _demigiantDir; // with final slash
|
|
static string _dotweenDir; // with final slash
|
|
static string _dotweenProDir; // with final slash
|
|
static string _dotweenProEditorDir; // with final slash
|
|
static string _dotweenModulesDir; // with final slash
|
|
|
|
static EditorUtils()
|
|
{
|
|
isOSXEditor = Application.platform == RuntimePlatform.OSXEditor;
|
|
bool useWindowsSlashes = Application.platform == RuntimePlatform.WindowsEditor;
|
|
pathSlash = useWindowsSlashes ? "\\" : "/";
|
|
pathSlashToReplace = useWindowsSlashes ? "/" : "\\";
|
|
|
|
projectPath = Application.dataPath;
|
|
projectPath = projectPath.Substring(0, projectPath.LastIndexOf("/"));
|
|
projectPath = projectPath.Replace(pathSlashToReplace, pathSlash);
|
|
|
|
assetsPath = projectPath + pathSlash + "Assets";
|
|
}
|
|
|
|
// ===================================================================================
|
|
// PUBLIC METHODS --------------------------------------------------------------------
|
|
|
|
public static void DelayedCall(float delay, Action callback)
|
|
{
|
|
new DelayedCall(delay, callback);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks that the given editor texture use the correct import settings,
|
|
/// and applies them if they're incorrect.
|
|
/// </summary>
|
|
public static void SetEditorTexture(Texture2D texture, FilterMode filterMode = FilterMode.Point, int maxTextureSize = 32)
|
|
{
|
|
if (texture.wrapMode == TextureWrapMode.Clamp) return;
|
|
|
|
string path = AssetDatabase.GetAssetPath(texture);
|
|
TextureImporter tImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
|
tImporter.textureType = TextureImporterType.GUI;
|
|
tImporter.npotScale = TextureImporterNPOTScale.None;
|
|
tImporter.filterMode = filterMode;
|
|
tImporter.wrapMode = TextureWrapMode.Clamp;
|
|
tImporter.maxTextureSize = maxTextureSize;
|
|
tImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor;
|
|
AssetDatabase.ImportAsset(path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns TRUE if setup is required
|
|
/// </summary>
|
|
public static bool DOTweenSetupRequired()
|
|
{
|
|
if (!Directory.Exists(dotweenDir)) return false;
|
|
return Directory.GetFiles(dotweenDir + "Editor", "DOTweenUpgradeManager.*").Length > 0;
|
|
|
|
// Legacy methods
|
|
// if (!Directory.Exists(dotweenDir)) return false; // Can happen if we were deleting DOTween
|
|
// return Directory.GetFiles(dotweenDir, "*.addon").Length > 0 || hasPro && Directory.GetFiles(dotweenProDir, "*.addon").Length > 0;
|
|
}
|
|
|
|
// Deletes DOTweenUpgradeManager files
|
|
public static void DeleteDOTweenUpgradeManagerFiles()
|
|
{
|
|
Type t = Type.GetType("DG.DOTweenUpgradeManager.Autorun, DOTweenUpgradeManager");
|
|
if (t == null) return;
|
|
|
|
string filePathNoExt = t.Assembly.Location;
|
|
filePathNoExt = filePathNoExt.Substring(0, filePathNoExt.LastIndexOf('.'));
|
|
AssetDatabase.StartAssetEditing();
|
|
DeleteAssetsIfExist(new[] {
|
|
FullPathToADBPath(filePathNoExt + ".dll"),
|
|
FullPathToADBPath(filePathNoExt + ".dll.mdb"),
|
|
FullPathToADBPath(filePathNoExt + ".pdb"),
|
|
FullPathToADBPath(filePathNoExt + ".xml")
|
|
});
|
|
AssetDatabase.StopAssetEditing();
|
|
}
|
|
|
|
// Deletes the files used in older versions of DOTween where Modules still didn't exist
|
|
public static void DeleteLegacyNoModulesDOTweenFiles()
|
|
{
|
|
string adbDOTweenDir = FullPathToADBPath(dotweenDir);
|
|
AssetDatabase.StartAssetEditing();
|
|
DeleteAssetsIfExist(new[] {
|
|
adbDOTweenDir + "DOTween43.dll",
|
|
adbDOTweenDir + "DOTween43.xml",
|
|
adbDOTweenDir + "DOTween43.dll.mdb",
|
|
adbDOTweenDir + "DOTween43.dll.addon",
|
|
adbDOTweenDir + "DOTween43.xml.addon",
|
|
adbDOTweenDir + "DOTween43.dll.mdb.addon",
|
|
adbDOTweenDir + "DOTween46.dll",
|
|
adbDOTweenDir + "DOTween46.xml",
|
|
adbDOTweenDir + "DOTween46.dll.mdb",
|
|
adbDOTweenDir + "DOTween46.dll.addon",
|
|
adbDOTweenDir + "DOTween46.xml.addon",
|
|
adbDOTweenDir + "DOTween46.dll.mdb.addon",
|
|
adbDOTweenDir + "DOTween50.dll",
|
|
adbDOTweenDir + "DOTween50.xml",
|
|
adbDOTweenDir + "DOTween50.dll.mdb",
|
|
adbDOTweenDir + "DOTween50.dll.addon",
|
|
adbDOTweenDir + "DOTween50.xml.addon",
|
|
adbDOTweenDir + "DOTween50.dll.mdb.addon",
|
|
//
|
|
adbDOTweenDir + "DOTweenTextMeshPro.cs.addon",
|
|
adbDOTweenDir + "DOTweenTextMeshPro_mod.cs",
|
|
adbDOTweenDir + "DOTweenTk2d.cs.addon",
|
|
});
|
|
AssetDatabase.StopAssetEditing();
|
|
}
|
|
|
|
// Deletes old DemiLib core if new one (inside Core directory) exists
|
|
public static void DeleteOldDemiLibCore()
|
|
{
|
|
string demiLibDir = EditorUtils.GetAssemblyFilePath(typeof(DOTween).Assembly);
|
|
string slash = demiLibDir.IndexOf("/") != -1 ? "/" : "\\";
|
|
demiLibDir = demiLibDir.Substring(0, demiLibDir.LastIndexOf(slash));
|
|
demiLibDir = demiLibDir.Substring(0, demiLibDir.LastIndexOf(slash)) + slash + "DemiLib";
|
|
string adbDemiLibDir = FullPathToADBPath(demiLibDir);
|
|
if (!AssetExists(adbDemiLibDir)) return;
|
|
|
|
string demiLibNewCoreDir = adbDemiLibDir + "/Core";
|
|
if (!AssetExists(demiLibNewCoreDir)) return;
|
|
|
|
// New version present, delete old versions
|
|
DeleteAssetsIfExist(new[] {
|
|
adbDemiLibDir + "/DemiLib.dll",
|
|
adbDemiLibDir + "/DemiLib.xml",
|
|
adbDemiLibDir + "/DemiLib.dll.mdb",
|
|
adbDemiLibDir + "/Editor/DemiEditor.dll",
|
|
adbDemiLibDir + "/Editor/DemiEditor.xml",
|
|
adbDemiLibDir + "/Editor/DemiEditor.dll.mdb",
|
|
adbDemiLibDir + "/Editor/Imgs"
|
|
});
|
|
// Delete Editor folder if empty
|
|
if (AssetExists(adbDemiLibDir + "/Editor") && Directory.GetFiles(demiLibDir + slash + "Editor").Length == 0) {
|
|
AssetDatabase.DeleteAsset(adbDemiLibDir + "/Editor");
|
|
// Reimport correct Core libraries
|
|
AssetDatabase.ImportAsset(demiLibNewCoreDir, ImportAssetOptions.ImportRecursive);
|
|
}
|
|
}
|
|
|
|
static void DeleteAssetsIfExist(string[] adbFilePaths)
|
|
{
|
|
foreach (string f in adbFilePaths) {
|
|
if (AssetExists(f)) AssetDatabase.DeleteAsset(f);
|
|
}
|
|
}
|
|
// static void ReimportAssets(string[] adbFilePaths)
|
|
// {
|
|
// foreach (string f in adbFilePaths) {
|
|
// if (AssetExists(f)) AssetDatabase.ImportAsset(f, ImportAssetOptions.ForceUpdate);
|
|
// }
|
|
// }
|
|
|
|
/// <summary>
|
|
/// Returns TRUE if the file/directory at the given path exists.
|
|
/// </summary>
|
|
/// <param name="adbPath">Path, relative to Unity's project folder</param>
|
|
/// <returns></returns>
|
|
public static bool AssetExists(string adbPath)
|
|
{
|
|
string fullPath = ADBPathToFullPath(adbPath);
|
|
return File.Exists(fullPath) || Directory.Exists(fullPath);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts the given project-relative path to a full path,
|
|
/// with backward (\) slashes).
|
|
/// </summary>
|
|
public static string ADBPathToFullPath(string adbPath)
|
|
{
|
|
adbPath = adbPath.Replace(pathSlashToReplace, pathSlash);
|
|
return projectPath + pathSlash + adbPath;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts the given full path to a path usable with AssetDatabase methods
|
|
/// (relative to Unity's project folder, and with the correct Unity forward (/) slashes).
|
|
/// </summary>
|
|
public static string FullPathToADBPath(string fullPath)
|
|
{
|
|
string adbPath = fullPath.Substring(projectPath.Length + 1);
|
|
return adbPath.Replace("\\", "/");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Connects to a <see cref="ScriptableObject"/> asset.
|
|
/// If the asset already exists at the given path, loads it and returns it.
|
|
/// Otherwise, either returns NULL or automatically creates it before loading and returning it
|
|
/// (depending on the given parameters).
|
|
/// </summary>
|
|
/// <typeparam name="T">Asset type</typeparam>
|
|
/// <param name="adbFilePath">File path (relative to Unity's project folder)</param>
|
|
/// <param name="createIfMissing">If TRUE and the requested asset doesn't exist, forces its creation</param>
|
|
public static T ConnectToSourceAsset<T>(string adbFilePath, bool createIfMissing = false) where T : ScriptableObject
|
|
{
|
|
if (!AssetExists(adbFilePath)) {
|
|
if (createIfMissing) CreateScriptableAsset<T>(adbFilePath);
|
|
else return null;
|
|
}
|
|
T source = (T)AssetDatabase.LoadAssetAtPath(adbFilePath, typeof(T));
|
|
if (source == null) {
|
|
// Source changed (or editor file was moved from outside of Unity): overwrite it
|
|
CreateScriptableAsset<T>(adbFilePath);
|
|
source = (T)AssetDatabase.LoadAssetAtPath(adbFilePath, typeof(T));
|
|
}
|
|
return source;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Full path for the given loaded assembly, assembly file included
|
|
/// </summary>
|
|
public static string GetAssemblyFilePath(Assembly assembly)
|
|
{
|
|
|
|
string codeBase = assembly.CodeBase;
|
|
UriBuilder uri = new UriBuilder(codeBase);
|
|
string path = Uri.UnescapeDataString(uri.Path);
|
|
if (path.Substring(path.Length - 3) == "dll") return path;
|
|
|
|
// string codeBase = assembly.CodeBase;
|
|
// UriBuilder uri = new UriBuilder(codeBase);
|
|
// string path = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
|
|
// string lastChar = path.Substring(path.Length - 4);
|
|
// if (lastChar == "dll") return path;
|
|
|
|
// Invalid path, use Location
|
|
return Path.GetFullPath(assembly.Location);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the given global define if it's not already present
|
|
/// </summary>
|
|
public static void AddGlobalDefine(string id)
|
|
{
|
|
bool added = false;
|
|
int totGroupsModified = 0;
|
|
BuildTargetGroup[] targetGroups = (BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup));
|
|
foreach(BuildTargetGroup btg in targetGroups) {
|
|
if (!IsValidBuildTargetGroup(btg)) continue;
|
|
string defs = PlayerSettings.GetScriptingDefineSymbolsForGroup(btg);
|
|
string[] singleDefs = defs.Split(';');
|
|
if (Array.IndexOf(singleDefs, id) != -1) continue; // Already present
|
|
added = true;
|
|
totGroupsModified++;
|
|
defs += defs.Length > 0 ? ";" + id : id;
|
|
PlayerSettings.SetScriptingDefineSymbolsForGroup(btg, defs);
|
|
}
|
|
if (added) Debug.Log(string.Format("DOTween : added global define \"{0}\" to {1} BuildTargetGroups", id, totGroupsModified));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the given global define if it's present
|
|
/// </summary>
|
|
public static void RemoveGlobalDefine(string id)
|
|
{
|
|
bool removed = false;
|
|
int totGroupsModified = 0;
|
|
BuildTargetGroup[] targetGroups = (BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup));
|
|
foreach(BuildTargetGroup btg in targetGroups) {
|
|
if (!IsValidBuildTargetGroup(btg)) continue;
|
|
string defs = PlayerSettings.GetScriptingDefineSymbolsForGroup(btg);
|
|
string[] singleDefs = defs.Split(';');
|
|
if (Array.IndexOf(singleDefs, id) == -1) continue; // Not present
|
|
removed = true;
|
|
totGroupsModified++;
|
|
_Strb.Length = 0;
|
|
for (int i = 0; i < singleDefs.Length; ++i) {
|
|
if (singleDefs[i] == id) continue;
|
|
if (_Strb.Length > 0) _Strb.Append(';');
|
|
_Strb.Append(singleDefs[i]);
|
|
}
|
|
PlayerSettings.SetScriptingDefineSymbolsForGroup(btg, _Strb.ToString());
|
|
}
|
|
_Strb.Length = 0;
|
|
if (removed) Debug.Log(string.Format("DOTween : removed global define \"{0}\" from {1} BuildTargetGroups", id, totGroupsModified));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns TRUE if the given global define is present in all the <see cref="BuildTargetGroup"/>
|
|
/// or only in the given <see cref="BuildTargetGroup"/>, depending on passed parameters.<para/>
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <param name="buildTargetGroup"><see cref="BuildTargetGroup"/>to use. Leave NULL to check in all of them.</param>
|
|
public static bool HasGlobalDefine(string id, BuildTargetGroup? buildTargetGroup = null)
|
|
{
|
|
BuildTargetGroup[] targetGroups = buildTargetGroup == null
|
|
? (BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup))
|
|
: new[] {(BuildTargetGroup)buildTargetGroup};
|
|
foreach(BuildTargetGroup btg in targetGroups) {
|
|
if (!IsValidBuildTargetGroup(btg)) continue;
|
|
string defs = PlayerSettings.GetScriptingDefineSymbolsForGroup(btg);
|
|
string[] singleDefs = defs.Split(';');
|
|
if (Array.IndexOf(singleDefs, id) != -1) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ===================================================================================
|
|
// METHODS ---------------------------------------------------------------------------
|
|
|
|
static void CheckForPro()
|
|
{
|
|
_hasCheckedForPro = true;
|
|
try {
|
|
Assembly additionalAssembly = Assembly.Load("DOTweenPro, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
|
|
_proVersion = additionalAssembly.GetType("DG.Tweening.DOTweenPro").GetField("Version", BindingFlags.Static | BindingFlags.Public).GetValue(null) as string;
|
|
_hasPro = true;
|
|
} catch {
|
|
// No DOTweenPro present
|
|
_hasPro = false;
|
|
_proVersion = "-";
|
|
}
|
|
}
|
|
|
|
// AssetDatabase formatted path to DOTween's Editor folder
|
|
static void StoreEditorADBDir()
|
|
{
|
|
// string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
|
// UriBuilder uri = new UriBuilder(codeBase);
|
|
// string fullPath = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
|
|
string fullPath = Path.GetDirectoryName(GetAssemblyFilePath(Assembly.GetExecutingAssembly()));
|
|
string adbPath = fullPath.Substring(Application.dataPath.Length + 1);
|
|
_editorADBDir = adbPath.Replace("\\", "/") + "/";
|
|
}
|
|
|
|
static void StoreDOTweenDirs()
|
|
{
|
|
// string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
|
// UriBuilder uri = new UriBuilder(codeBase);
|
|
// _dotweenDir = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
|
|
_dotweenDir = Path.GetDirectoryName(GetAssemblyFilePath(Assembly.GetExecutingAssembly()));
|
|
string pathSeparator = _dotweenDir.IndexOf("/") != -1 ? "/" : "\\";
|
|
_dotweenDir = _dotweenDir.Substring(0, _dotweenDir.LastIndexOf(pathSeparator) + 1);
|
|
|
|
_dotweenProDir = _dotweenDir.Substring(0, _dotweenDir.LastIndexOf(pathSeparator));
|
|
_dotweenProDir = _dotweenProDir.Substring(0, _dotweenProDir.LastIndexOf(pathSeparator) + 1) + "DOTweenPro" + pathSeparator;
|
|
|
|
_demigiantDir = _dotweenDir.Substring(0, _dotweenDir.LastIndexOf(pathSeparator));
|
|
_demigiantDir = _demigiantDir.Substring(0, _demigiantDir.LastIndexOf(pathSeparator) + 1);
|
|
if (_demigiantDir.Substring(_demigiantDir.Length - 10, 9) != "Demigiant") _demigiantDir = null;
|
|
|
|
_dotweenDir = _dotweenDir.Replace(pathSlashToReplace, pathSlash);
|
|
_dotweenProDir = _dotweenProDir.Replace(pathSlashToReplace, pathSlash);
|
|
_dotweenProEditorDir = _dotweenProDir + "Editor" + pathSlash;
|
|
_dotweenModulesDir = _dotweenDir + "Modules" + pathSlash;
|
|
if (_demigiantDir != null) _demigiantDir = _demigiantDir.Replace(pathSlashToReplace, pathSlash);
|
|
}
|
|
|
|
static void CreateScriptableAsset<T>(string adbFilePath) where T : ScriptableObject
|
|
{
|
|
T data = ScriptableObject.CreateInstance<T>();
|
|
AssetDatabase.CreateAsset(data, adbFilePath);
|
|
}
|
|
|
|
static bool IsValidBuildTargetGroup(BuildTargetGroup group)
|
|
{
|
|
if (group == BuildTargetGroup.Unknown) return false;
|
|
Type moduleManager = Type.GetType("UnityEditor.Modules.ModuleManager, UnityEditor.dll");
|
|
// MethodInfo miIsPlatformSupportLoaded = moduleManager.GetMethod("IsPlatformSupportLoaded", BindingFlags.Static | BindingFlags.NonPublic);
|
|
MethodInfo miGetTargetStringFromBuildTargetGroup = moduleManager.GetMethod(
|
|
"GetTargetStringFromBuildTargetGroup", BindingFlags.Static | BindingFlags.NonPublic
|
|
);
|
|
MethodInfo miGetPlatformName = typeof(PlayerSettings).GetMethod(
|
|
"GetPlatformName", BindingFlags.Static | BindingFlags.NonPublic
|
|
);
|
|
string targetString = (string)miGetTargetStringFromBuildTargetGroup.Invoke(null, new object[] {group});
|
|
string platformName = (string)miGetPlatformName.Invoke(null, new object[] {group});
|
|
|
|
// Group is valid if at least one betweeen targetString and platformName is not empty.
|
|
// This seems to me the safest and more reliant way to check,
|
|
// since ModuleManager.IsPlatformSupportLoaded dosn't work well with BuildTargetGroup (only BuildTarget)
|
|
bool isValid = !string.IsNullOrEmpty(targetString) || !string.IsNullOrEmpty(platformName);
|
|
|
|
// Debug.Log((isValid ? "<color=#00ff00>" : "<color=#ff0000>") + group + " > " + targetString + " / " + platformName + " > " + isValid + "/" + miIsPlatformSupportLoaded.Invoke(null, new object[] {group.ToString()}) + "</color>");
|
|
return isValid;
|
|
}
|
|
}
|
|
} |