123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- // ----------------------------------------------------------------------------
- // <copyright file="PhotonEditorUtils.cs" company="Exit Games GmbH">
- // PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
- // </copyright>
- // <summary>
- // Unity Editor Utils
- // </summary>
- // <author>developer@exitgames.com</author>
- // ----------------------------------------------------------------------------
- #pragma warning disable 618 // Deprecation warnings
- #if UNITY_2017_4_OR_NEWER
- #define SUPPORTED_UNITY
- #endif
- #if UNITY_EDITOR
- namespace Photon.Realtime
- {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor;
- using UnityEngine;
- using System.IO;
- using System.Text;
- using UnityEngine.Networking;
- [InitializeOnLoad]
- public static class PhotonEditorUtils
- {
- /// <summary>Stores a flag which tells Editor scripts if the PhotonEditor.OnProjectChanged got called since initialization.</summary>
- /// <remarks>If not, the AssetDatabase is likely not usable yet and instances of ScriptableObject can't be loaded.</remarks>
- [Obsolete("Directly check EditorApplication.isUpdating to figure out if assets are being imported at the given time.")]
- public static bool ProjectChangedWasCalled
- {
- get
- {
- return UnityEditor.EditorApplication.isUpdating;
- }
- }
- /// <summary>True if the ChatClient of the Photon Chat API is available. If so, the editor may (e.g.) show additional options in settings.</summary>
- public static bool HasChat;
- /// <summary>True if the VoiceClient of the Photon Voice API is available. If so, the editor may (e.g.) show additional options in settings.</summary>
- public static bool HasVoice;
- /// <summary>True if PUN is in the project.</summary>
- public static bool HasPun;
- /// <summary>True if Photon Fusion is available in the project (and enabled).</summary>
- public static bool HasFusion;
- /// <summary>True if the PhotonEditorUtils checked the available products / APIs. If so, the editor may (e.g.) show additional options in settings.</summary>
- public static bool HasCheckedProducts;
- static PhotonEditorUtils()
- {
- HasVoice = Type.GetType("Photon.Voice.VoiceClient, Assembly-CSharp") != null || Type.GetType("Photon.Voice.VoiceClient, Assembly-CSharp-firstpass") != null || Type.GetType("Photon.Voice.VoiceClient, PhotonVoice.API") != null;
- HasChat = Type.GetType("Photon.Chat.ChatClient, Assembly-CSharp") != null || Type.GetType("Photon.Chat.ChatClient, Assembly-CSharp-firstpass") != null || Type.GetType("Photon.Chat.ChatClient, PhotonChat") != null;
- HasPun = Type.GetType("Photon.Pun.PhotonNetwork, Assembly-CSharp") != null || Type.GetType("Photon.Pun.PhotonNetwork, Assembly-CSharp-firstpass") != null || Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking") != null;
- #if FUSION_WEAVER
- HasFusion = true;
- #endif
- PhotonEditorUtils.HasCheckedProducts = true;
- if (EditorPrefs.HasKey("DisablePun") && EditorPrefs.GetBool("DisablePun"))
- {
- HasPun = false;
- }
- if (HasPun)
- {
- // MOUNTING SYMBOLS
- #if !PHOTON_UNITY_NETWORKING
- AddScriptingDefineSymbolToAllBuildTargetGroups("PHOTON_UNITY_NETWORKING");
- #endif
- #if !PUN_2_0_OR_NEWER
- AddScriptingDefineSymbolToAllBuildTargetGroups("PUN_2_0_OR_NEWER");
- #endif
- #if !PUN_2_OR_NEWER
- AddScriptingDefineSymbolToAllBuildTargetGroups("PUN_2_OR_NEWER");
- #endif
- #if !PUN_2_19_OR_NEWER
- AddScriptingDefineSymbolToAllBuildTargetGroups("PUN_2_19_OR_NEWER");
- #endif
- }
- }
- /// <summary>
- /// Adds a given scripting define symbol to all build target groups
- /// You can see all scripting define symbols ( not the internal ones, only the one for this project), in the PlayerSettings inspector
- /// </summary>
- /// <param name="defineSymbol">Define symbol.</param>
- public static void AddScriptingDefineSymbolToAllBuildTargetGroups(string defineSymbol)
- {
- foreach (BuildTarget target in Enum.GetValues(typeof(BuildTarget)))
- {
- BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
- if (group == BuildTargetGroup.Unknown)
- {
- continue;
- }
- var defineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group).Split(';').Select(d => d.Trim()).ToList();
- if (!defineSymbols.Contains(defineSymbol))
- {
- defineSymbols.Add(defineSymbol);
- try
- {
- PlayerSettings.SetScriptingDefineSymbolsForGroup(group, string.Join(";", defineSymbols.ToArray()));
- }
- catch (Exception e)
- {
- Debug.Log("Could not set Photon " + defineSymbol + " defines for build target: " + target + " group: " + group + " " + e);
- }
- }
- }
- }
- /// <summary>
- /// Removes PUN2's Script Define Symbols from project
- /// </summary>
- public static void CleanUpPunDefineSymbols()
- {
- foreach (BuildTarget target in Enum.GetValues(typeof(BuildTarget)))
- {
- BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
- if (group == BuildTargetGroup.Unknown)
- {
- continue;
- }
- var defineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group)
- .Split(';')
- .Select(d => d.Trim())
- .ToList();
- List<string> newDefineSymbols = new List<string>();
- foreach (var symbol in defineSymbols)
- {
- if ("PHOTON_UNITY_NETWORKING".Equals(symbol) || symbol.StartsWith("PUN_2_"))
- {
- continue;
- }
- newDefineSymbols.Add(symbol);
- }
- try
- {
- PlayerSettings.SetScriptingDefineSymbolsForGroup(group, string.Join(";", newDefineSymbols.ToArray()));
- }
- catch (Exception e)
- {
- Debug.LogErrorFormat("Could not set clean up PUN2's define symbols for build target: {0} group: {1}, {2}", target, group, e);
- }
- }
- }
- /// <summary>
- /// Gets the parent directory of a path. Recursive Function, will return null if parentName not found
- /// </summary>
- /// <returns>The parent directory</returns>
- /// <param name="path">Path.</param>
- /// <param name="parentName">Parent name.</param>
- public static string GetParent(string path, string parentName)
- {
- var dir = new DirectoryInfo(path);
- if (dir.Parent == null)
- {
- return null;
- }
- if (string.IsNullOrEmpty(parentName))
- {
- return dir.Parent.FullName;
- }
- if (dir.Parent.Name == parentName)
- {
- return dir.Parent.FullName;
- }
- return GetParent(dir.Parent.FullName, parentName);
- }
- /// <summary>
- /// Check if a GameObject is a prefab asset or part of a prefab asset, as opposed to an instance in the scene hierarchy
- /// </summary>
- /// <returns><c>true</c>, if a prefab asset or part of it, <c>false</c> otherwise.</returns>
- /// <param name="go">The GameObject to check</param>
- public static bool IsPrefab(GameObject go)
- {
- #if UNITY_2021_2_OR_NEWER
- return UnityEditor.SceneManagement.PrefabStageUtility.GetPrefabStage(go) != null || EditorUtility.IsPersistent(go);
- #elif UNITY_2018_3_OR_NEWER
- return UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(go) != null || EditorUtility.IsPersistent(go);
- #else
- return EditorUtility.IsPersistent(go);
- #endif
- }
- //https://forum.unity.com/threads/using-unitywebrequest-in-editor-tools.397466/#post-4485181
- public static void StartCoroutine(System.Collections.IEnumerator update)
- {
- EditorApplication.CallbackFunction closureCallback = null;
- closureCallback = () =>
- {
- try
- {
- if (update.MoveNext() == false)
- {
- EditorApplication.update -= closureCallback;
- }
- }
- catch (Exception ex)
- {
- Debug.LogException(ex);
- EditorApplication.update -= closureCallback;
- }
- };
- EditorApplication.update += closureCallback;
- }
- public static System.Collections.IEnumerator HttpPost(string url, Dictionary<string, string> headers, byte[] payload, Action<string> successCallback, Action<string> errorCallback)
- {
- using (UnityWebRequest w = new UnityWebRequest(url, "POST"))
- {
- if (payload != null)
- {
- w.uploadHandler = new UploadHandlerRaw(payload);
- }
- w.downloadHandler = new DownloadHandlerBuffer();
- if (headers != null)
- {
- foreach (var header in headers)
- {
- w.SetRequestHeader(header.Key, header.Value);
- }
- }
- #if UNITY_2017_2_OR_NEWER
- yield return w.SendWebRequest();
- #else
- yield return w.Send();
- #endif
- while (w.isDone == false)
- yield return null;
- #if UNITY_2020_2_OR_NEWER
- if (w.result == UnityWebRequest.Result.ProtocolError || w.result == UnityWebRequest.Result.ConnectionError || w.result == UnityWebRequest.Result.DataProcessingError)
- #elif UNITY_2017_1_OR_NEWER
- if (w.isNetworkError || w.isHttpError)
- #endif
- {
- if (errorCallback != null)
- {
- errorCallback(w.error);
- }
- }
- else
- {
- if (successCallback != null)
- {
- successCallback(w.downloadHandler.text);
- }
- }
- }
- }
- /// <summary>
- /// Creates a Foldout using a toggle with (GUIStyle)"Foldout") and a separate label. This is a workaround for 2019.3 foldout arrows not working.
- /// </summary>
- /// <param name="isExpanded"></param>
- /// <param name="label"></param>
- /// <returns>Returns the new isExpanded value.</returns>
- public static bool Foldout(this SerializedProperty isExpanded, GUIContent label)
- {
- var rect = EditorGUILayout.GetControlRect();
- bool newvalue = EditorGUI.Toggle(new Rect(rect) { xMin = rect.xMin + 2 }, GUIContent.none, isExpanded.boolValue, (GUIStyle)"Foldout");
- EditorGUI.LabelField(new Rect(rect) { xMin = rect.xMin + 15 }, label);
- if (newvalue != isExpanded.boolValue)
- {
- isExpanded.boolValue = newvalue;
- isExpanded.serializedObject.ApplyModifiedProperties();
- }
- return newvalue;
- }
- /// <summary>
- /// Creates a Foldout using a toggle with (GUIStyle)"Foldout") and a separate label. This is a workaround for 2019.3 foldout arrows not working.
- /// </summary>
- /// <param name="isExpanded"></param>
- /// <param name="label"></param>
- /// <returns>Returns the new isExpanded value.</returns>
- public static bool Foldout(this bool isExpanded, GUIContent label)
- {
- var rect = EditorGUILayout.GetControlRect();
- bool newvalue = EditorGUI.Toggle(new Rect(rect) { xMin = rect.xMin + 2 }, GUIContent.none, isExpanded, (GUIStyle)"Foldout");
- EditorGUI.LabelField(new Rect(rect) { xMin = rect.xMin + 15 }, label);
- return newvalue;
- }
- }
- public class CleanUpDefinesOnPunDelete : UnityEditor.AssetModificationProcessor
- {
- public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions rao)
- {
- if ("Assets/Photon/PhotonUnityNetworking".Equals(assetPath))
- {
- PhotonEditorUtils.CleanUpPunDefineSymbols();
- }
- return AssetDeleteResult.DidNotDelete;
- }
- }
- }
- #endif
|