You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
9.2 KiB

  1. #if UNITY_EDITOR || !(UNITY_WP_8_1 || UNITY_WSA || UNITY_WSA_8_1 || UNITY_WSA_10_0 || UNITY_WINRT || UNITY_WINRT_8_1 || UNITY_WINRT_10_0)
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System;
  6. using System.Linq;
  7. using System.Reflection;
  8. namespace ProGrids
  9. {
  10. public static class pg_Util
  11. {
  12. public static Color ColorWithString(string value)
  13. {
  14. string valid = "01234567890.,";
  15. value = new string(value.Where(c => valid.Contains(c)).ToArray());
  16. string[] rgba = value.Split(',');
  17. // BRIGHT pink
  18. if(rgba.Length < 4)
  19. return new Color(1f, 0f, 1f, 1f);
  20. return new Color(
  21. float.Parse(rgba[0]),
  22. float.Parse(rgba[1]),
  23. float.Parse(rgba[2]),
  24. float.Parse(rgba[3]));
  25. }
  26. private static Vector3 VectorToMask(Vector3 vec)
  27. {
  28. return new Vector3( Mathf.Abs(vec.x) > Mathf.Epsilon ? 1f : 0f,
  29. Mathf.Abs(vec.y) > Mathf.Epsilon ? 1f : 0f,
  30. Mathf.Abs(vec.z) > Mathf.Epsilon ? 1f : 0f );
  31. }
  32. private static Axis MaskToAxis(Vector3 vec)
  33. {
  34. Axis axis = Axis.None;
  35. if( Mathf.Abs(vec.x) > 0 ) axis |= Axis.X;
  36. if( Mathf.Abs(vec.y) > 0 ) axis |= Axis.Y;
  37. if( Mathf.Abs(vec.z) > 0 ) axis |= Axis.Z;
  38. return axis;
  39. }
  40. private static Axis BestAxis(Vector3 vec)
  41. {
  42. float x = Mathf.Abs(vec.x);
  43. float y = Mathf.Abs(vec.y);
  44. float z = Mathf.Abs(vec.z);
  45. return (x > y && x > z) ? Axis.X : ((y > x && y > z) ? Axis.Y : Axis.Z);
  46. }
  47. public static Axis CalcDragAxis(Vector3 movement, Camera cam)
  48. {
  49. Vector3 mask = VectorToMask(movement);
  50. if(mask.x + mask.y + mask.z == 2)
  51. {
  52. return MaskToAxis(Vector3.one - mask);
  53. }
  54. else
  55. {
  56. switch( MaskToAxis(mask) )
  57. {
  58. case Axis.X:
  59. if( Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.up)) < Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.forward)))
  60. return Axis.Z;
  61. else
  62. return Axis.Y;
  63. case Axis.Y:
  64. if( Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.right)) < Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.forward)))
  65. return Axis.Z;
  66. else
  67. return Axis.X;
  68. case Axis.Z:
  69. if( Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.right)) < Mathf.Abs(Vector3.Dot(cam.transform.forward, Vector3.up)))
  70. return Axis.Y;
  71. else
  72. return Axis.X;
  73. default:
  74. return Axis.None;
  75. }
  76. }
  77. }
  78. public static float ValueFromMask(Vector3 val, Vector3 mask)
  79. {
  80. if(Mathf.Abs(mask.x) > .0001f)
  81. return val.x;
  82. else if(Mathf.Abs(mask.y) > .0001f)
  83. return val.y;
  84. else
  85. return val.z;
  86. }
  87. public static Vector3 SnapValue(Vector3 val, float snapValue)
  88. {
  89. float _x = val.x, _y = val.y, _z = val.z;
  90. return new Vector3(
  91. Snap(_x, snapValue),
  92. Snap(_y, snapValue),
  93. Snap(_z, snapValue)
  94. );
  95. }
  96. /**
  97. * Fetch a type with name and optional assembly name. `type` should include namespace.
  98. */
  99. private static Type GetType(string type, string assembly = null)
  100. {
  101. Type t = Type.GetType(type);
  102. if(t == null)
  103. {
  104. IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();
  105. if(assembly != null)
  106. assemblies = assemblies.Where(x => x.FullName.Contains(assembly));
  107. foreach(Assembly ass in assemblies)
  108. {
  109. t = ass.GetType(type);
  110. if(t != null)
  111. return t;
  112. }
  113. }
  114. return t;
  115. }
  116. public static void SetUnityGridEnabled(bool isEnabled)
  117. {
  118. try
  119. {
  120. Type annotationUtility = GetType("UnityEditor.AnnotationUtility");
  121. PropertyInfo pi = annotationUtility.GetProperty("showGrid", BindingFlags.NonPublic | BindingFlags.Static);
  122. pi.SetValue(null, isEnabled, BindingFlags.NonPublic | BindingFlags.Static, null, null, null);
  123. }
  124. catch
  125. {}
  126. }
  127. public static bool GetUnityGridEnabled()
  128. {
  129. try
  130. {
  131. Type annotationUtility = GetType("UnityEditor.AnnotationUtility");
  132. PropertyInfo pi = annotationUtility.GetProperty("showGrid", BindingFlags.NonPublic | BindingFlags.Static);
  133. return (bool) pi.GetValue(null, null);
  134. }
  135. catch
  136. {}
  137. return false;
  138. }
  139. const float EPSILON = .0001f;
  140. public static Vector3 SnapValue(Vector3 val, Vector3 mask, float snapValue)
  141. {
  142. float _x = val.x, _y = val.y, _z = val.z;
  143. return new Vector3(
  144. ( Mathf.Abs(mask.x) < EPSILON ? _x : Snap(_x, snapValue) ),
  145. ( Mathf.Abs(mask.y) < EPSILON ? _y : Snap(_y, snapValue) ),
  146. ( Mathf.Abs(mask.z) < EPSILON ? _z : Snap(_z, snapValue) )
  147. );
  148. }
  149. public static Vector3 SnapToCeil(Vector3 val, Vector3 mask, float snapValue)
  150. {
  151. float _x = val.x, _y = val.y, _z = val.z;
  152. return new Vector3(
  153. ( Mathf.Abs(mask.x) < EPSILON ? _x : SnapToCeil(_x, snapValue) ),
  154. ( Mathf.Abs(mask.y) < EPSILON ? _y : SnapToCeil(_y, snapValue) ),
  155. ( Mathf.Abs(mask.z) < EPSILON ? _z : SnapToCeil(_z, snapValue) )
  156. );
  157. }
  158. public static Vector3 SnapToFloor(Vector3 val, float snapValue)
  159. {
  160. float _x = val.x, _y = val.y, _z = val.z;
  161. return new Vector3(
  162. SnapToFloor(_x, snapValue),
  163. SnapToFloor(_y, snapValue),
  164. SnapToFloor(_z, snapValue)
  165. );
  166. }
  167. public static Vector3 SnapToFloor(Vector3 val, Vector3 mask, float snapValue)
  168. {
  169. float _x = val.x, _y = val.y, _z = val.z;
  170. return new Vector3(
  171. ( Mathf.Abs(mask.x) < EPSILON ? _x : SnapToFloor(_x, snapValue) ),
  172. ( Mathf.Abs(mask.y) < EPSILON ? _y : SnapToFloor(_y, snapValue) ),
  173. ( Mathf.Abs(mask.z) < EPSILON ? _z : SnapToFloor(_z, snapValue) )
  174. );
  175. }
  176. public static float Snap(float val, float round)
  177. {
  178. return round * Mathf.Round(val / round);
  179. }
  180. public static float SnapToFloor(float val, float snapValue)
  181. {
  182. return snapValue * Mathf.Floor(val / snapValue);
  183. }
  184. public static float SnapToCeil(float val, float snapValue)
  185. {
  186. return snapValue * Mathf.Ceil(val / snapValue);
  187. }
  188. public static Vector3 CeilFloor(Vector3 v)
  189. {
  190. v.x = v.x < 0 ? -1 : 1;
  191. v.y = v.y < 0 ? -1 : 1;
  192. v.z = v.z < 0 ? -1 : 1;
  193. return v;
  194. }
  195. abstract class SnapEnabledOverride
  196. {
  197. public abstract bool IsEnabled();
  198. }
  199. class SnapIsEnabledOverride : SnapEnabledOverride
  200. {
  201. bool m_SnapIsEnabled;
  202. public SnapIsEnabledOverride(bool snapIsEnabled)
  203. {
  204. m_SnapIsEnabled = snapIsEnabled;
  205. }
  206. public override bool IsEnabled() { return m_SnapIsEnabled; }
  207. }
  208. class ConditionalSnapOverride : SnapEnabledOverride
  209. {
  210. public System.Func<bool> m_IsEnabledDelegate;
  211. public ConditionalSnapOverride(System.Func<bool> d)
  212. {
  213. m_IsEnabledDelegate = d;
  214. }
  215. public override bool IsEnabled() { return m_IsEnabledDelegate(); }
  216. }
  217. private static Dictionary<Transform, SnapEnabledOverride> m_SnapOverrideCache = new Dictionary<Transform, SnapEnabledOverride>();
  218. private static Dictionary<Type, bool> m_NoSnapAttributeTypeCache = new Dictionary<Type, bool>();
  219. private static Dictionary<Type, MethodInfo> m_ConditionalSnapAttributeCache = new Dictionary<Type, MethodInfo>();
  220. public static void ClearSnapEnabledCache()
  221. {
  222. m_SnapOverrideCache.Clear();
  223. }
  224. public static bool SnapIsEnabled(Transform t)
  225. {
  226. SnapEnabledOverride so;
  227. if(m_SnapOverrideCache.TryGetValue(t, out so))
  228. return so.IsEnabled();
  229. object[] attribs = null;
  230. foreach(Component c in t.GetComponents<MonoBehaviour>())
  231. {
  232. if(c == null)
  233. continue;
  234. Type type = c.GetType();
  235. bool hasNoSnapAttrib;
  236. if(m_NoSnapAttributeTypeCache.TryGetValue(type, out hasNoSnapAttrib))
  237. {
  238. if(hasNoSnapAttrib)
  239. {
  240. m_SnapOverrideCache.Add(t, new SnapIsEnabledOverride(!hasNoSnapAttrib));
  241. return true;
  242. }
  243. }
  244. else
  245. {
  246. attribs = type.GetCustomAttributes(true);
  247. hasNoSnapAttrib = attribs.Any(x => x != null && x.ToString().Contains("ProGridsNoSnap"));
  248. m_NoSnapAttributeTypeCache.Add(type, hasNoSnapAttrib);
  249. if(hasNoSnapAttrib)
  250. {
  251. m_SnapOverrideCache.Add(t, new SnapIsEnabledOverride(!hasNoSnapAttrib));
  252. return true;
  253. }
  254. }
  255. MethodInfo mi;
  256. if(m_ConditionalSnapAttributeCache.TryGetValue(type, out mi))
  257. {
  258. if(mi != null)
  259. {
  260. m_SnapOverrideCache.Add(t, new ConditionalSnapOverride(() => { return (bool) mi.Invoke(c, null); }));
  261. return (bool) mi.Invoke(c, null);
  262. }
  263. }
  264. else
  265. {
  266. if( attribs.Any(x => x != null && x.ToString().Contains("ProGridsConditionalSnap")) )
  267. {
  268. mi = type.GetMethod("IsSnapEnabled", BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public);
  269. m_ConditionalSnapAttributeCache.Add(type, mi);
  270. if(mi != null)
  271. {
  272. m_SnapOverrideCache.Add(t, new ConditionalSnapOverride(() => { return (bool) mi.Invoke(c, null); }));
  273. return (bool) mi.Invoke(c, null);
  274. }
  275. }
  276. else
  277. {
  278. m_ConditionalSnapAttributeCache.Add(type, null);
  279. }
  280. }
  281. }
  282. m_SnapOverrideCache.Add(t, new SnapIsEnabledOverride(true));
  283. return true;
  284. }
  285. }
  286. public static class PGExtensions
  287. {
  288. public static bool Contains(this Transform[] t_arr, Transform t)
  289. {
  290. for(int i = 0; i < t_arr.Length; i++)
  291. if(t_arr[i] == t)
  292. return true;
  293. return false;
  294. }
  295. public static float Sum(this Vector3 v)
  296. {
  297. return v[0] + v[1] + v[2];
  298. }
  299. public static bool InFrustum(this Camera cam, Vector3 point)
  300. {
  301. Vector3 p = cam.WorldToViewportPoint(point);
  302. return (p.x >= 0f && p.x <= 1f) &&
  303. (p.y >= 0f && p.y <= 1f) &&
  304. p.z >= 0f;
  305. }
  306. }
  307. }
  308. #endif