// ----------------------------------------------------------------------------
//
// 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
}