// ---------------------------------------------------------------------------- // // PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH // // // Provides some helpful methods and extensions for Hashtables, etc. // // developer@exitgames.com // ---------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; using Hashtable = ExitGames.Client.Photon.Hashtable; using SupportClassPun = ExitGames.Client.Photon.SupportClass; /// /// This static class defines some useful extension methods for several existing classes (e.g. Vector3, float and others). /// public static class Extensions { public static Dictionary ParametersOfMethods = new Dictionary(); public static ParameterInfo[] GetCachedParemeters(this MethodInfo mo) { ParameterInfo[] result; bool cached= ParametersOfMethods.TryGetValue(mo, out result); if (!cached) { result = mo.GetParameters(); ParametersOfMethods[mo] = result; } return result; } public static PhotonView[] GetPhotonViewsInChildren(this UnityEngine.GameObject go) { return go.GetComponentsInChildren(true) as PhotonView[]; } public static PhotonView GetPhotonView(this UnityEngine.GameObject go) { return go.GetComponent() as PhotonView; } /// compares the squared magnitude of target - second to given float value public static bool AlmostEquals(this Vector3 target, Vector3 second, float sqrMagnitudePrecision) { return (target - second).sqrMagnitude < sqrMagnitudePrecision; // TODO: inline vector methods to optimize? } /// compares the squared magnitude of target - second to given float value public static bool AlmostEquals(this Vector2 target, Vector2 second, float sqrMagnitudePrecision) { return (target - second).sqrMagnitude < sqrMagnitudePrecision; // TODO: inline vector methods to optimize? } /// compares the angle between target and second to given float value public static bool AlmostEquals(this Quaternion target, Quaternion second, float maxAngle) { return Quaternion.Angle(target, second) < maxAngle; } /// compares two floats and returns true of their difference is less than floatDiff public static bool AlmostEquals(this float target, float second, float floatDiff) { return Mathf.Abs(target - second) < floatDiff; } /// /// Merges all keys from addHash into the target. Adds new keys and updates the values of existing keys in target. /// /// The IDictionary to update. /// The IDictionary containing data to merge into target. public static void Merge(this IDictionary target, IDictionary addHash) { if (addHash == null || target.Equals(addHash)) { return; } foreach (object key in addHash.Keys) { target[key] = addHash[key]; } } /// /// Merges keys of type string to target Hashtable. /// /// /// Does not remove keys from target (so non-string keys CAN be in target if they were before). /// /// The target IDicitionary passed in plus all string-typed keys from the addHash. /// A IDictionary that should be merged partly into target to update it. public static void MergeStringKeys(this IDictionary target, IDictionary addHash) { if (addHash == null || target.Equals(addHash)) { return; } foreach (object key in addHash.Keys) { // only merge keys of type string if (key is string) { target[key] = addHash[key]; } } } /// Helper method for debugging of IDictionary content, inlcuding type-information. Using this is not performant. /// Should only be used for debugging as necessary. /// Some Dictionary or Hashtable. /// String of the content of the IDictionary. public static string ToStringFull(this IDictionary origin) { return SupportClassPun.DictionaryToString(origin, false); } /// Helper method for debugging of object[] content. Using this is not performant. /// Should only be used for debugging as necessary. /// Any object[]. /// A comma-separated string containing each value's ToString(). public static string ToStringFull(this object[] data) { if (data == null) return "null"; string[] sb = new string[data.Length]; for (int i = 0; i < data.Length; i++) { object o = data[i]; sb[i] = (o != null) ? o.ToString() : "null"; } return string.Join(", ", sb); } /// /// This method copies all string-typed keys of the original into a new Hashtable. /// /// /// Does not recurse (!) into hashes that might be values in the root-hash. /// This does not modify the original. /// /// The original IDictonary to get string-typed keys from. /// New Hashtable containing only string-typed keys of the original. public static Hashtable StripToStringKeys(this IDictionary original) { Hashtable target = new Hashtable(); if (original != null) { foreach (object key in original.Keys) { if (key is string) { target[key] = original[key]; } } } return target; } /// /// This removes all key-value pairs that have a null-reference as value. /// Photon properties are removed by setting their value to null. /// Changes the original passed IDictionary! /// /// The IDictionary to strip of keys with null-values. public static void StripKeysWithNullValues(this IDictionary original) { object[] keys = new object[original.Count]; //original.Keys.CopyTo(keys, 0); // todo: figure out which platform didn't support this int i = 0; foreach (object k in original.Keys) { keys[i++] = k; } for (int index = 0; index < keys.Length; index++) { var key = keys[index]; if (original[key] == null) { original.Remove(key); } } } /// /// Checks if a particular integer value is in an int-array. /// /// This might be useful to look up if a particular actorNumber is in the list of players of a room. /// The array of ints to check. /// The number to lookup in target. /// True if nr was found in target. public static bool Contains(this int[] target, int nr) { if (target == null) { return false; } for (int index = 0; index < target.Length; index++) { if (target[index] == nr) { return true; } } return false; } } /// Small number of extension methods that make it easier for PUN to work cross-Unity-versions. public static class GameObjectExtensions { /// Unity-version-independent replacement for active GO property. /// Unity 3.5: active. Any newer Unity: activeInHierarchy. public static bool GetActive(this GameObject target) { #if UNITY_3_5 return target.active; #else return target.activeInHierarchy; #endif } #if UNITY_3_5 /// Unity-version-independent setter for active and SetActive(). public static void SetActive(this GameObject target, bool value) { target.active = value; } #endif }