GameObjectExtensions.cs 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace O3DWB
  7. {
  8. public static class GameObjectExtensions
  9. {
  10. #region Extension Methods
  11. public static bool IsSceneObject(this GameObject gameObject)
  12. {
  13. var prefabAssetType = PrefabUtility.GetPrefabAssetType(gameObject);
  14. return prefabAssetType == PrefabAssetType.NotAPrefab;
  15. }
  16. public static Octave3DMesh GetOctave3DMesh(this GameObject gameObject)
  17. {
  18. Mesh mesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
  19. if (mesh == null) return null;
  20. return Octave3DMeshDatabase.Get().GetOctave3DMesh(mesh);
  21. }
  22. public static void SetMeshPivotPoint(this GameObject gameObject, Vector3 pivotPoint)
  23. {
  24. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  25. if (mesh == null) return;
  26. Vector3[] vertexPositions = mesh.vertices;
  27. for(int vIndex = 0; vIndex < vertexPositions.Length; ++vIndex)
  28. {
  29. vertexPositions[vIndex] = vertexPositions[vIndex] - pivotPoint;
  30. }
  31. mesh.vertices = vertexPositions;
  32. mesh.RecalculateBounds();
  33. gameObject.transform.position = pivotPoint;
  34. }
  35. public static void SetWorldPosDontAffectChildren(this GameObject gameObject, Vector3 worldPos)
  36. {
  37. Transform objectTransform = gameObject.transform;
  38. Dictionary<Transform, Vector3> childToPos = new Dictionary<Transform, Vector3>();
  39. for (int childIndex = 0; childIndex < objectTransform.childCount; ++childIndex )
  40. {
  41. Transform childTransform = objectTransform.GetChild(childIndex);
  42. childToPos.Add(childTransform, childTransform.position);
  43. }
  44. objectTransform.position = worldPos;
  45. for (int childIndex = 0; childIndex < objectTransform.childCount; ++childIndex)
  46. {
  47. Transform childTransform = objectTransform.GetChild(childIndex);
  48. childTransform.position = childToPos[childTransform];
  49. }
  50. }
  51. public static List<GameObject> GetAllMeshObjectsInHierarchy(this GameObject root)
  52. {
  53. var meshFilters = root.GetComponentsInChildren<MeshFilter>();
  54. if (meshFilters.Length == 0) return new List<GameObject>();
  55. var meshObjects = new List<GameObject>(meshFilters.Length);
  56. foreach(var meshFilter in meshFilters)
  57. {
  58. if(meshFilter.sharedMesh != null) meshObjects.Add(meshFilter.gameObject);
  59. }
  60. return meshObjects;
  61. }
  62. public static List<Vector3> GetOverlappedVertsInHierarchy(this GameObject root, OrientedBox overlapBox)
  63. {
  64. List<GameObject> allObjects = root.GetAllChildrenIncludingSelf();
  65. if (allObjects.Count == 0) return new List<Vector3>();
  66. var overlappedVerts = new List<Vector3>(allObjects.Count * 50);
  67. foreach (var gameObject in allObjects)
  68. {
  69. Mesh mesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
  70. if (mesh != null)
  71. {
  72. Octave3DMesh octave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(mesh);
  73. if (octave3DMesh != null) overlappedVerts.AddRange(octave3DMesh.GetOverlappedWorldVerts(overlapBox, new TransformMatrix(gameObject.transform.localToWorldMatrix)));
  74. }
  75. }
  76. return overlappedVerts;
  77. }
  78. public static List<Octave3DMesh> GetAllOctave3DMeshesInHierarchy(this GameObject root)
  79. {
  80. List<GameObject> allObjects = root.GetAllChildrenIncludingSelf();
  81. if (allObjects.Count == 0) return new List<Octave3DMesh>();
  82. var allOctave3DMeshes = new List<Octave3DMesh>(allObjects.Count);
  83. foreach(var gameObject in allObjects)
  84. {
  85. Mesh mesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
  86. if(mesh != null)
  87. {
  88. Octave3DMesh octave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(mesh);
  89. if (octave3DMesh != null) allOctave3DMeshes.Add(octave3DMesh);
  90. }
  91. }
  92. return allOctave3DMeshes;
  93. }
  94. public static void EmbedInSurfaceByVertex(this GameObject root, Vector3 embedDirection, GameObject embedSurface)
  95. {
  96. if (!root.DoesHierarchyContainMesh()) return;
  97. OrientedBox worldOOBB = root.GetHierarchyWorldOrientedBox();
  98. if (worldOOBB.IsValid())
  99. {
  100. Vector3 worldOOBBScaledSize = worldOOBB.ScaledSize;
  101. embedDirection.Normalize();
  102. BoxFace boxFace = worldOOBB.GetBoxFaceMostAlignedWithNormal(embedDirection);
  103. Vector3 faceCenter = worldOOBB.GetBoxFaceCenter(boxFace);
  104. Plane facePlane = worldOOBB.GetBoxFacePlane(boxFace);
  105. int sizeComponentIndex = -1;
  106. if (boxFace == BoxFace.Back || boxFace == BoxFace.Front) sizeComponentIndex = 2;
  107. else if (boxFace == BoxFace.Left || boxFace == BoxFace.Right) sizeComponentIndex = 0;
  108. else if (boxFace == BoxFace.Top || boxFace == BoxFace.Bottom) sizeComponentIndex = 1;
  109. const float vCollectSizeScale = 0.01f;
  110. const float vCollectEps = 1e-2f;
  111. Vector3 vCollectBoxSize = worldOOBB.ScaledSize;
  112. vCollectBoxSize[sizeComponentIndex] *= vCollectSizeScale;
  113. vCollectBoxSize[sizeComponentIndex] += vCollectEps;
  114. vCollectBoxSize[(sizeComponentIndex + 1) % 3] += vCollectEps;
  115. vCollectBoxSize[(sizeComponentIndex + 2) % 3] += vCollectEps;
  116. OrientedBox vCollectBox = new OrientedBox(worldOOBB);
  117. vCollectBox.Scale = Vector3.one;
  118. vCollectBox.ModelSpaceSize = vCollectBoxSize;
  119. vCollectBox.Center = (faceCenter + facePlane.normal * vCollectEps) - facePlane.normal * vCollectBoxSize[sizeComponentIndex] * 0.5f;
  120. List<Vector3> overlappedVerts = root.GetOverlappedVertsInHierarchy(vCollectBox);
  121. if (overlappedVerts.Count == 0) return;
  122. GameObjectRayHit surfaceRayHit;
  123. float maxDistSq = float.MinValue;
  124. bool needToMove = false;
  125. Vector3 cameraPos = SceneViewCamera.Camera.transform.position;
  126. foreach (var vertex in overlappedVerts)
  127. {
  128. // Ignore if already below the surface
  129. Ray ray = new Ray(vertex, -embedDirection);
  130. if (embedSurface.RaycastTerrainOrMesh(ray, out surfaceRayHit)) continue;
  131. // Ignore if already on the surface
  132. Vector3 fromCamToPt = vertex - cameraPos;
  133. ray = new Ray(cameraPos, Vector3.Normalize(fromCamToPt));
  134. if (embedSurface.RaycastTerrainOrMesh(ray, out surfaceRayHit))
  135. {
  136. if (Mathf.Abs(fromCamToPt.magnitude - (surfaceRayHit.HitPoint - cameraPos).magnitude) < 1e-3f) continue;
  137. }
  138. ray = new Ray(vertex, embedDirection);
  139. if (embedSurface.RaycastTerrainOrMesh(ray, out surfaceRayHit))
  140. {
  141. float distSq = (vertex - surfaceRayHit.HitPoint).sqrMagnitude;
  142. if (distSq > maxDistSq)
  143. {
  144. maxDistSq = distSq;
  145. needToMove = true;
  146. }
  147. }
  148. }
  149. if (needToMove) root.transform.position += embedDirection * Mathf.Sqrt(maxDistSq);
  150. }
  151. }
  152. public static void EmbedAllObjectsInSurface(List<GameObject> gameObjects, Vector3 embedDirection, GameObject embedSurface)
  153. {
  154. foreach (GameObject gameObject in gameObjects)
  155. {
  156. if (gameObject == embedSurface) continue;
  157. gameObject.EmbedInSurface(embedDirection, embedSurface);
  158. }
  159. }
  160. public static void EmbedObjectBoxInSurface(OrientedBox objectBox, Vector3 embedDirection, GameObject embedSurface)
  161. {
  162. GameObjectRayHit rayHit;
  163. if (objectBox.IsValid())
  164. {
  165. BoxFace boxFace = objectBox.GetBoxFaceMostAlignedWithNormal(embedDirection);
  166. //Vector3 faceCenter = objectBox.GetBoxFaceCenter(boxFace);
  167. /*Ray ray = new Ray(faceCenter, embedDirection);
  168. if (embedSurface.RaycastTerrainOrMeshReverseIfFail(ray, out rayHit))
  169. {
  170. Vector3 moveVector = rayHit.HitPoint - faceCenter;
  171. objectBox.Center += moveVector;
  172. }*/
  173. float maxDistSq = float.MinValue;
  174. float minDistSq = float.MaxValue;
  175. bool hitAlongPrjDir = false;
  176. bool hitAlongReversePrjDir = false;
  177. List<Vector3> boxFaceCorners = objectBox.GetBoxFaceCornerPoints(boxFace);
  178. foreach (var corner in boxFaceCorners)
  179. {
  180. Ray ray = new Ray(corner, -embedDirection);
  181. if (embedSurface.RaycastTerrainOrMesh(ray, out rayHit))
  182. {
  183. float distSq = (corner - rayHit.HitPoint).sqrMagnitude;
  184. if (distSq < minDistSq)
  185. {
  186. minDistSq = distSq;
  187. hitAlongReversePrjDir = true;
  188. }
  189. continue;
  190. }
  191. ray = new Ray(corner, embedDirection);
  192. if (embedSurface.RaycastTerrainOrMesh(ray, out rayHit))
  193. {
  194. float distSq = (corner - rayHit.HitPoint).sqrMagnitude;
  195. if (distSq > maxDistSq)
  196. {
  197. maxDistSq = distSq;
  198. hitAlongPrjDir = true;
  199. }
  200. }
  201. }
  202. if (hitAlongPrjDir) objectBox.Center += embedDirection * Mathf.Sqrt(maxDistSq);
  203. else
  204. if (hitAlongReversePrjDir) objectBox.Center -= embedDirection * Mathf.Sqrt(minDistSq);
  205. }
  206. }
  207. public static void EmbedInSurface(this GameObject gameObject, Vector3 embedDirection, GameObject embedSurface)
  208. {
  209. GameObjectRayHit rayHit;
  210. OrientedBox worldOOBB = gameObject.GetHierarchyWorldOrientedBox();
  211. if (worldOOBB.IsValid())
  212. {
  213. BoxFace boxFace = worldOOBB.GetBoxFaceMostAlignedWithNormal(embedDirection);
  214. //Vector3 faceCenter = worldOOBB.GetBoxFaceCenter(boxFace);
  215. /*Ray ray = new Ray(faceCenter, embedDirection);
  216. if (embedSurface.RaycastTerrainOrMeshReverseIfFail(ray, out rayHit))
  217. {
  218. Vector3 moveVector = rayHit.HitPoint - faceCenter;
  219. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  220. gameObject.transform.position += moveVector;
  221. worldOOBB.Center += moveVector;
  222. }*/
  223. float maxDistSq = float.MinValue;
  224. float minDistSq = float.MaxValue;
  225. bool hitAlongPrjDir = false;
  226. bool hitAlongReversePrjDir = false;
  227. List<Vector3> boxFaceCorners = worldOOBB.GetBoxFaceCornerPoints(boxFace);
  228. foreach (var corner in boxFaceCorners)
  229. {
  230. Ray ray = new Ray(corner, -embedDirection);
  231. if (embedSurface.RaycastTerrainOrMesh(ray, out rayHit))
  232. {
  233. float distSq = (corner - rayHit.HitPoint).sqrMagnitude;
  234. if (distSq < minDistSq)
  235. {
  236. minDistSq = distSq;
  237. hitAlongReversePrjDir = true;
  238. }
  239. continue;
  240. }
  241. ray = new Ray(corner, embedDirection);
  242. if (embedSurface.RaycastTerrainOrMesh(ray, out rayHit))
  243. {
  244. float distSq = (corner - rayHit.HitPoint).sqrMagnitude;
  245. if (distSq > maxDistSq)
  246. {
  247. maxDistSq = distSq;
  248. hitAlongPrjDir = true;
  249. }
  250. }
  251. }
  252. if (hitAlongPrjDir)
  253. {
  254. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  255. gameObject.transform.position += embedDirection * Mathf.Sqrt(maxDistSq);
  256. }
  257. else
  258. if (hitAlongReversePrjDir)
  259. {
  260. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  261. gameObject.transform.position -= embedDirection * Mathf.Sqrt(minDistSq);
  262. }
  263. }
  264. }
  265. public static void ProjectAllObjectsOnPlane(List<GameObject> gameObjects, Vector3 projectionDir, Plane plane)
  266. {
  267. List<GameObject> parents = GameObjectExtensions.GetParents(gameObjects);
  268. foreach (GameObject gameObject in parents)
  269. {
  270. gameObject.ProjectOnPlane(projectionDir, plane);
  271. }
  272. }
  273. public static void ProjectOnPlane(this GameObject gameObject, Vector3 projectionDir, Plane plane)
  274. {
  275. OrientedBox worldOOBB = gameObject.GetHierarchyWorldOrientedBox();
  276. if (worldOOBB.IsValid())
  277. {
  278. BoxFace boxFace = worldOOBB.GetBoxFaceMostAlignedWithNormal(projectionDir);
  279. //Vector3 faceCenter = worldOOBB.GetBoxFaceCenter(boxFace);
  280. /*Ray ray = new Ray(faceCenter, embedDirection);
  281. if (embedSurface.RaycastTerrainOrMeshReverseIfFail(ray, out rayHit))
  282. {
  283. Vector3 moveVector = rayHit.HitPoint - faceCenter;
  284. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  285. gameObject.transform.position += moveVector;
  286. worldOOBB.Center += moveVector;
  287. }*/
  288. float maxDistSq = float.MinValue;
  289. float minDistSq = float.MaxValue;
  290. bool hitAlongPrjDir = false;
  291. bool hitAlongReversePrjDir = false;
  292. List<Vector3> boxFaceCorners = worldOOBB.GetBoxFaceCornerPoints(boxFace);
  293. foreach (var corner in boxFaceCorners)
  294. {
  295. Ray ray = new Ray(corner, -projectionDir);
  296. float t;
  297. if (plane.Raycast(ray, out t))
  298. {
  299. float distSq = (corner - ray.GetPoint(t)).sqrMagnitude;
  300. if (distSq < minDistSq)
  301. {
  302. minDistSq = distSq;
  303. hitAlongReversePrjDir = true;
  304. }
  305. continue;
  306. }
  307. ray = new Ray(corner, projectionDir);
  308. if (plane.Raycast(ray, out t))
  309. {
  310. float distSq = (corner - ray.GetPoint(t)).sqrMagnitude;
  311. if (distSq > maxDistSq)
  312. {
  313. maxDistSq = distSq;
  314. hitAlongPrjDir = true;
  315. }
  316. }
  317. }
  318. if (hitAlongPrjDir)
  319. {
  320. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  321. gameObject.transform.position += projectionDir * Mathf.Sqrt(maxDistSq);
  322. }
  323. else
  324. if (hitAlongReversePrjDir)
  325. {
  326. GameObjectExtensions.RecordObjectTransformsForUndo(new List<GameObject> { gameObject });
  327. gameObject.transform.position -= projectionDir * Mathf.Sqrt(minDistSq);
  328. }
  329. }
  330. }
  331. public static List<Vector3> GetLocalAxes(this GameObject gameObject)
  332. {
  333. Transform gameObjectTransform = gameObject.transform;
  334. return new List<Vector3> { gameObjectTransform.right, gameObjectTransform.up, gameObjectTransform.forward };
  335. }
  336. public static void ApplyTransformDataToRootChildren(this GameObject root, GameObject sourceRoot)
  337. {
  338. List<GameObject> destChildren = root.GetAllChildren();
  339. List<GameObject> sourceChildren = sourceRoot.GetAllChildren();
  340. if (destChildren.Count != sourceChildren.Count) return;
  341. // Note: Assumes there will always be a 1 to 1 mapping between the children in the hierarchy.
  342. for(int childIndex = 0; childIndex < destChildren.Count; ++childIndex)
  343. {
  344. destChildren[childIndex].transform.InheritWorldTransformFrom(sourceChildren[childIndex].transform);
  345. }
  346. }
  347. public static GameObject CloneAsWorkingObject(this GameObject gameObject, Transform parentTransform, bool allowUndoRedo = true)
  348. {
  349. Transform gameObjectTransform = gameObject.transform;
  350. GameObject clone = GameObject.Instantiate(gameObject, gameObjectTransform.position, gameObjectTransform.rotation) as GameObject;
  351. if (allowUndoRedo) UndoEx.RegisterCreatedGameObject(clone);
  352. clone.transform.localScale = gameObjectTransform.transform.lossyScale;
  353. clone.name = gameObject.name;
  354. clone.isStatic = gameObject.isStatic;
  355. clone.layer = gameObject.layer;
  356. clone.transform.parent = parentTransform;
  357. Octave3DScene.Get().RegisterObjectHierarchy(clone);
  358. SceneViewCamera.Instance.SetObjectVisibilityDirty();
  359. return clone;
  360. }
  361. public static GameObject GetSourcePrefab(this GameObject gameObject)
  362. {
  363. return PrefabUtility.GetCorrespondingObjectFromSource(gameObject) as GameObject;
  364. }
  365. public static GameObject GetSourcePrefabRoot(this GameObject gameObject)
  366. {
  367. GameObject sourcePrefab = gameObject.GetSourcePrefab();
  368. if (sourcePrefab == null) return null;
  369. Transform sourcePrefabTransform = sourcePrefab.transform;
  370. if (sourcePrefabTransform.root != null) sourcePrefab = sourcePrefabTransform.root.gameObject;
  371. return sourcePrefab;
  372. }
  373. public static bool RaycastBox(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  374. {
  375. objectRayHit = null;
  376. OrientedBox objectWorldOrientedBox = gameObject.GetWorldOrientedBox();
  377. OrientedBoxRayHit objectBoxRayHit;
  378. if (objectWorldOrientedBox.Raycast(ray, out objectBoxRayHit))
  379. objectRayHit = new GameObjectRayHit(ray, gameObject, objectBoxRayHit, null, null, null);
  380. return objectRayHit != null;
  381. }
  382. public static bool RaycastSprite(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  383. {
  384. objectRayHit = null;
  385. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  386. if (spriteRenderer == null) return false;
  387. OrientedBox objectWorldOrientedBox = gameObject.GetWorldOrientedBox();
  388. OrientedBoxRayHit objectBoxRayHit;
  389. if(objectWorldOrientedBox.Raycast(ray, out objectBoxRayHit))
  390. {
  391. SpriteRayHit spriteHit = new SpriteRayHit(ray, objectBoxRayHit.HitEnter, spriteRenderer, objectBoxRayHit.HitPoint, objectBoxRayHit.HitNormal);
  392. objectRayHit = new GameObjectRayHit(ray, gameObject, null, null, null, spriteHit);
  393. }
  394. return objectRayHit != null;
  395. }
  396. public static bool RaycastMesh(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  397. {
  398. objectRayHit = null;
  399. Mesh objectMesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
  400. if (objectMesh == null) return false;
  401. Octave3DMesh octaveMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(objectMesh);
  402. if (octaveMesh == null) return false;
  403. MeshRayHit meshRayHit = octaveMesh.Raycast(ray, gameObject.transform.GetWorldMatrix());
  404. if (meshRayHit == null) return false;
  405. objectRayHit = new GameObjectRayHit(ray, gameObject, null, meshRayHit, null, null);
  406. return true;
  407. }
  408. public static bool RaycastMeshReverseIfFail(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  409. {
  410. if (gameObject.RaycastMesh(ray, out objectRayHit)) return true;
  411. return gameObject.RaycastMesh(new Ray(ray.origin, -ray.direction), out objectRayHit);
  412. }
  413. public static bool RaycastTerrain(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  414. {
  415. objectRayHit = null;
  416. if (!gameObject.HasTerrain()) return false;
  417. TerrainCollider terrainCollider = gameObject.GetComponent<TerrainCollider>();
  418. if (terrainCollider == null) return false;
  419. RaycastHit raycastHit;
  420. if (terrainCollider.Raycast(ray, out raycastHit, float.MaxValue))
  421. {
  422. TerrainRayHit terrainRayHit = new TerrainRayHit(ray, raycastHit);
  423. objectRayHit = new GameObjectRayHit(ray, gameObject, null, null, terrainRayHit, null);
  424. }
  425. return objectRayHit != null;
  426. }
  427. public static bool RaycastTerrainReverseIfFail(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  428. {
  429. if (gameObject.RaycastTerrain(ray, out objectRayHit)) return true;
  430. return gameObject.RaycastTerrain(new Ray(ray.origin, -ray.direction), out objectRayHit);
  431. }
  432. public static bool RaycastTerrainOrMeshReverseIfFail(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  433. {
  434. objectRayHit = null;
  435. if(gameObject.HasTerrain() && gameObject.GetComponent<TerrainCollider>() != null) return gameObject.RaycastTerrainReverseIfFail(ray, out objectRayHit);
  436. else if (gameObject.HasMesh()) return gameObject.RaycastMeshReverseIfFail(ray, out objectRayHit);
  437. return false;
  438. }
  439. public static bool RaycastTerrainOrMesh(this GameObject gameObject, Ray ray, out GameObjectRayHit objectRayHit)
  440. {
  441. objectRayHit = null;
  442. if (gameObject.HasTerrain() && gameObject.GetComponent<TerrainCollider>() != null) return gameObject.RaycastTerrain(ray, out objectRayHit);
  443. else if (gameObject.HasMesh()) return gameObject.RaycastMesh(ray, out objectRayHit);
  444. return false;
  445. }
  446. public static void SetHierarchyStatic(this GameObject hierarchyRoot, bool isStatic)
  447. {
  448. List<GameObject> allChildren = hierarchyRoot.GetAllChildrenIncludingSelf();
  449. foreach(GameObject child in allChildren)
  450. {
  451. child.isStatic = isStatic;
  452. }
  453. }
  454. public static void RotateHierarchyBoxAroundPoint(this GameObject root, float rotationInDegrees, Vector3 rotationAxis, Vector3 pivotPoint)
  455. {
  456. // OLD CODE: Was not taking pivot point into account.
  457. /*OrientedBox hierarchyWorldOrientedBox = root.GetHierarchyWorldOrientedBox();
  458. Transform rootTransform = root.transform;
  459. Vector3 fromCenterToPosition = rootTransform.position - hierarchyWorldOrientedBox.Center;
  460. Quaternion oldRotation = rootTransform.rotation;
  461. rotationAxis.Normalize();
  462. rootTransform.Rotate(rotationAxis, rotationInDegrees, Space.World);
  463. fromCenterToPosition = oldRotation.GetRelativeRotation(rootTransform.rotation) * fromCenterToPosition;
  464. rootTransform.position = hierarchyWorldOrientedBox.Center + fromCenterToPosition;*/
  465. OrientedBox hierarchyWorldOrientedBox = root.GetHierarchyWorldOrientedBox();
  466. Transform rootTransform = root.transform;
  467. rotationAxis.Normalize();
  468. Quaternion rotation = Quaternion.AngleAxis(rotationInDegrees, rotationAxis);
  469. Vector3 fromPivotToCenter = rotation * (hierarchyWorldOrientedBox.Center - pivotPoint);
  470. Vector3 newCenter = pivotPoint + fromPivotToCenter;
  471. Vector3 fromCenterToPosition = rotation * (rootTransform.position - hierarchyWorldOrientedBox.Center);
  472. rootTransform.rotation = rotation * rootTransform.rotation;
  473. rootTransform.position = newCenter + fromCenterToPosition;
  474. }
  475. public static void SetHierarchyWorldRotationAndPreserveHierarchyCenter(this GameObject root, Quaternion rotation)
  476. {
  477. OrientedBox hierarchyWorldOrientedBox = root.GetHierarchyWorldOrientedBox();
  478. Transform rootTransform = root.transform;
  479. Vector3 fromCenterToPosition = rootTransform.position - hierarchyWorldOrientedBox.Center;
  480. Quaternion oldRotation = rootTransform.rotation;
  481. rootTransform.rotation = rotation;
  482. fromCenterToPosition = oldRotation.GetRelativeRotation(rootTransform.rotation) * fromCenterToPosition;
  483. rootTransform.position = hierarchyWorldOrientedBox.Center + fromCenterToPosition;
  484. }
  485. public static void SetHierarchyWorldScaleByPivotPoint(this GameObject root, float scale, Vector3 pivotPoint)
  486. {
  487. root.SetHierarchyWorldScaleByPivotPoint(new Vector3(scale, scale, scale), pivotPoint);
  488. }
  489. public static void SetHierarchyWorldScaleByPivotPoint(this GameObject root, Vector3 scale, Vector3 pivotPoint)
  490. {
  491. Transform rootTransform = root.transform;
  492. Vector3 fromPivotToPosition = rootTransform.position - pivotPoint;
  493. Vector3 oldScale = rootTransform.lossyScale;
  494. root.SetWorldScale(scale);
  495. Vector3 invOldScaleVector = new Vector3(1.0f / oldScale.x, 1.0f / oldScale.y, 1.0f / oldScale.z);
  496. Vector3 relativeScale = Vector3.Scale(scale, invOldScaleVector);
  497. fromPivotToPosition = Vector3.Scale(relativeScale, fromPivotToPosition);
  498. rootTransform.position = pivotPoint + fromPivotToPosition;
  499. }
  500. public static void PlaceHierarchyOnPlane(this GameObject root, Plane placementPlane)
  501. {
  502. OrientedBox hierarchyWorldOrientedBox = root.GetHierarchyWorldOrientedBox();
  503. List<Vector3> boxPts = hierarchyWorldOrientedBox.GetCornerPoints();
  504. int ptIndex = placementPlane.GetIndexOfFurthestPointBehind(boxPts);
  505. if (ptIndex < 0) ptIndex = placementPlane.GetIndexOfClosestPointInFrontOrOnPlane(boxPts);
  506. if(ptIndex >= 0)
  507. {
  508. float distToPt = placementPlane.GetDistanceToPoint(boxPts[ptIndex]);
  509. root.transform.position -= placementPlane.normal * distToPt;
  510. }
  511. }
  512. public static void PlaceObjectBoxOnPlane(OrientedBox oobb, Plane plane)
  513. {
  514. List<Vector3> boxPts = oobb.GetCornerPoints();
  515. int ptIndex = plane.GetIndexOfFurthestPointBehind(boxPts);
  516. if (ptIndex < 0) ptIndex = plane.GetIndexOfClosestPointInFrontOrOnPlane(boxPts);
  517. if (ptIndex >= 0)
  518. {
  519. float distToPt = plane.GetDistanceToPoint(boxPts[ptIndex]);
  520. oobb.Center -= plane.normal * distToPt;
  521. }
  522. }
  523. public static void SetSelectedHierarchyWireframeHidden(this GameObject hierarchyRoot, bool isWireframeHidden)
  524. {
  525. Renderer renderer = hierarchyRoot.GetComponent<Renderer>();
  526. if (renderer != null)
  527. {
  528. #if UNITY_2017_1_OR_NEWER
  529. EditorUtility.SetSelectedRenderState(renderer, isWireframeHidden ? EditorSelectedRenderState.Hidden : EditorSelectedRenderState.Highlight);
  530. #else
  531. EditorUtility.SetSelectedWireframeHidden(renderer, isWireframeHidden);
  532. #endif
  533. }
  534. Transform gameObjectTransform = hierarchyRoot.transform;
  535. for (int childIndex = 0; childIndex < gameObjectTransform.childCount; ++childIndex)
  536. {
  537. SetSelectedHierarchyWireframeHidden(gameObjectTransform.GetChild(childIndex).gameObject, isWireframeHidden);
  538. }
  539. }
  540. public static bool DoesHierarchyContainMesh(this GameObject root)
  541. {
  542. List<GameObject> allChildrenIncludingSelf = root.GetAllChildrenIncludingSelf();
  543. foreach(GameObject gameObject in allChildrenIncludingSelf)
  544. {
  545. if (gameObject.HasMesh()) return true;
  546. }
  547. return false;
  548. }
  549. public static List<GameObject> GetHierarchyObjectsWithMesh(this GameObject hierarchyRoot)
  550. {
  551. List<GameObject> allChildrenIncludingSelf = hierarchyRoot.GetAllChildrenIncludingSelf();
  552. allChildrenIncludingSelf.RemoveAll(item => !item.HasMesh());
  553. return allChildrenIncludingSelf;
  554. }
  555. public static List<GameObject> GetHierarchyObjectsWithSprites(this GameObject hierarchyRoot)
  556. {
  557. List<GameObject> allChildrenIncludingSelf = hierarchyRoot.GetAllChildrenIncludingSelf();
  558. allChildrenIncludingSelf.RemoveAll(item => !item.HasSpriteRendererWithSprite());
  559. return allChildrenIncludingSelf;
  560. }
  561. public static bool HasMesh(this GameObject gameObject)
  562. {
  563. return gameObject.HasMeshFilterWithValidMesh() || gameObject.HasSkinnedMeshRendererWithValidMesh();
  564. }
  565. public static bool HasMeshFilterWithValidMesh(this GameObject gameObject)
  566. {
  567. MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
  568. return meshFilter != null && meshFilter.sharedMesh != null;
  569. }
  570. public static bool HasSkinnedMeshRendererWithValidMesh(this GameObject gameObject)
  571. {
  572. SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
  573. return skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null;
  574. }
  575. public static bool HasTerrain(this GameObject gameObject)
  576. {
  577. return gameObject.GetComponent<Terrain>() != null;
  578. }
  579. public static bool HasLight(this GameObject gameObject)
  580. {
  581. return gameObject.GetComponent<Light>() != null;
  582. }
  583. public static bool HasParticleSystem(this GameObject gameObject)
  584. {
  585. return gameObject.GetComponent<ParticleSystem>() != null;
  586. }
  587. public static bool HasSpriteRenderer(this GameObject gameObject)
  588. {
  589. return gameObject.GetComponent<SpriteRenderer>() != null;
  590. }
  591. public static bool HasSpriteRendererWithSprite(this GameObject gameObject)
  592. {
  593. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  594. if (spriteRenderer == null) return false;
  595. return spriteRenderer.sprite != null;
  596. }
  597. public static void AttachChildren(this GameObject gameObject, List<GameObject> children, bool allowUndoRedo)
  598. {
  599. if(allowUndoRedo)
  600. {
  601. Transform objectTransform = gameObject.transform;
  602. UndoEx.RecordForToolAction(objectTransform);
  603. foreach (GameObject child in children)
  604. {
  605. Transform childTransform = child.transform;
  606. UndoEx.RecordForToolAction(childTransform);
  607. childTransform.parent = objectTransform;
  608. }
  609. }
  610. else
  611. {
  612. Transform objectTransform = gameObject.transform;
  613. foreach (GameObject child in children)
  614. {
  615. child.transform.parent = objectTransform;
  616. }
  617. }
  618. }
  619. public static List<GameObject> GetAllChildrenIncludingSelf(this GameObject gameObject)
  620. {
  621. var finalObjectList = new List<GameObject> { gameObject };
  622. List<GameObject> allChildren = gameObject.GetAllChildren();
  623. if (allChildren.Count != 0) finalObjectList.AddRange(allChildren);
  624. return finalObjectList;
  625. }
  626. public static List<GameObject> GetAllChildren(this GameObject gameObject)
  627. {
  628. Transform objectTransform = gameObject.transform;
  629. Transform[] allChildTransforms = gameObject.GetComponentsInChildren<Transform>(true);
  630. var allChildren = new List<GameObject>();
  631. foreach(Transform childTransform in allChildTransforms)
  632. {
  633. if (objectTransform != childTransform) allChildren.Add(childTransform.gameObject);
  634. }
  635. return allChildren;
  636. }
  637. public static List<GameObject> GetImmediateChildren(this GameObject gameObject)
  638. {
  639. Transform objectTransform = gameObject.transform;
  640. List<Transform> immediateChildTransforms = objectTransform.GetImmediateChildTransforms();
  641. if (immediateChildTransforms.Count != 0)
  642. {
  643. List<GameObject> immediateChildren = new List<GameObject>(immediateChildTransforms.Count);
  644. foreach (Transform childTransform in immediateChildTransforms)
  645. {
  646. immediateChildren.Add(childTransform.gameObject);
  647. }
  648. return immediateChildren;
  649. }
  650. else return new List<GameObject>();
  651. }
  652. public static void MoveImmediateChildrenUpOneLevel(this GameObject gameObject, bool allowUndoRedo)
  653. {
  654. Transform objectTransform = gameObject.transform;
  655. Transform objectParentTransform = objectTransform.parent;
  656. List<Transform> immediateChildTransforms = objectTransform.GetImmediateChildTransforms();
  657. if(allowUndoRedo)
  658. {
  659. foreach (Transform childTransform in immediateChildTransforms)
  660. {
  661. UndoEx.SetTransformParent(childTransform, objectParentTransform);
  662. }
  663. }
  664. else
  665. {
  666. foreach (Transform childTransform in immediateChildTransforms)
  667. {
  668. childTransform.parent = objectParentTransform;
  669. }
  670. }
  671. }
  672. public static GameObject GetParentWhichIsChildOf(this GameObject gameObject, GameObject targetParent)
  673. {
  674. // Store needed data for easy access
  675. Transform targetParentTransform = targetParent.transform;
  676. Transform currentTransform = gameObject.transform;
  677. // Keep moving up the hierarchy until we encounter the parent whose parent is 'targetParent'
  678. while (currentTransform != null && currentTransform.parent != targetParentTransform)
  679. {
  680. // Move up
  681. currentTransform = currentTransform.parent;
  682. }
  683. // If the current transform is not null, it means we found the parent which is a child of 'targetParent'.
  684. // Otherwise, it means that either 'gameObject' doesn't have any parents or its top parent is not a child
  685. // of 'targetParent'.
  686. return currentTransform != null ? currentTransform.gameObject : null;
  687. }
  688. public static GameObject GetParentWhichIsChildOf(this GameObject gameObject, List<Type> possibleParentTypes)
  689. {
  690. Transform currentTransform = gameObject.transform;
  691. while (currentTransform != null && currentTransform.parent != null)
  692. {
  693. GameObject currentParentObject = currentTransform.parent.gameObject;
  694. if (currentParentObject.HasComponentsOfAnyType(possibleParentTypes)) return currentTransform.gameObject;
  695. currentTransform = currentTransform.parent;
  696. }
  697. return null;
  698. }
  699. public static bool HasComponentsOfAnyType(this GameObject gameObject, List<Type> possibleTypes)
  700. {
  701. foreach (var type in possibleTypes)
  702. {
  703. if (gameObject.GetComponents(type).Length != 0) return true;
  704. }
  705. return false;
  706. }
  707. public static void SetWorldScale(this GameObject gameObject, float worldScale)
  708. {
  709. gameObject.SetWorldScale(new Vector3(worldScale, worldScale, worldScale));
  710. }
  711. public static void SetWorldScale(this GameObject gameObject, Vector3 worldScale)
  712. {
  713. Transform objectTransform = gameObject.transform;
  714. Transform objectParent = objectTransform.parent;
  715. objectTransform.parent = null;
  716. objectTransform.localScale = worldScale;
  717. float minScale = 1e-4f;
  718. if (Mathf.Abs(objectTransform.localScale.x) < minScale) objectTransform.localScale = new Vector3(minScale, objectTransform.localScale.y, objectTransform.localScale.z);
  719. if (Mathf.Abs(objectTransform.localScale.y) < minScale) objectTransform.localScale = new Vector3(objectTransform.localScale.x, minScale, objectTransform.localScale.z);
  720. if (Mathf.Abs(objectTransform.localScale.z) < minScale) objectTransform.localScale = new Vector3(objectTransform.localScale.x, objectTransform.localScale.y, minScale);
  721. objectTransform.parent = objectParent;
  722. }
  723. public static Rect GetScreenRectangle(this GameObject gameObject, Camera camera)
  724. {
  725. Box worldBox = gameObject.GetWorldBox();
  726. if (worldBox.IsValid()) return worldBox.GetScreenRectangle(camera);
  727. return new Rect();
  728. }
  729. public static OrientedBox GetHierarchyWorldOrientedBox(this GameObject hierarchyRoot)
  730. {
  731. OrientedBox hierarchyWorldOrientedBox = hierarchyRoot.GetHierarchyModelSpaceOrientedBox();
  732. hierarchyWorldOrientedBox.Transform(hierarchyRoot.transform);
  733. return hierarchyWorldOrientedBox;
  734. }
  735. public static OrientedBox GetHierarchyModelSpaceOrientedBox(this GameObject hierarchyRoot)
  736. {
  737. Box hierarchyModelSpaceBox = hierarchyRoot.GetHierarchyModelSpaceBox();
  738. return new OrientedBox(hierarchyModelSpaceBox);
  739. }
  740. public static Box GetHierarchyWorldBox(this GameObject hierarchyRoot)
  741. {
  742. Box hierarchyWorldBox = hierarchyRoot.GetHierarchyModelSpaceBox();
  743. hierarchyWorldBox = hierarchyWorldBox.Transform(hierarchyRoot.transform.GetWorldMatrix());
  744. return hierarchyWorldBox;
  745. }
  746. public static Box GetHierarchyModelSpaceBox(this GameObject hierarchyRoot)
  747. {
  748. Transform rootTransform = hierarchyRoot.transform;
  749. Transform[] allChildTransforms = hierarchyRoot.GetComponentsInChildren<Transform>();
  750. bool hierarchyContainsMesh = hierarchyRoot.DoesHierarchyContainMesh();
  751. Box hierarchyModelSpaceBox = hierarchyRoot.GetModelSpaceBox();
  752. foreach (Transform childTransform in allChildTransforms)
  753. {
  754. GameObject childObject = childTransform.gameObject;
  755. bool objectHasMesh = childObject.HasMesh();
  756. if(objectHasMesh)
  757. {
  758. Renderer renderer = childObject.GetRenderer();
  759. if (renderer == null || !renderer.enabled) continue;
  760. }
  761. // If the hierarchy contains mesh objects, we will only take mesh objects into account
  762. if (!objectHasMesh && hierarchyContainsMesh) continue;
  763. if (childObject != hierarchyRoot)
  764. {
  765. /*Octave3DMesh octave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(childObject.GetMeshFromFilterOrSkinnedMeshRenderer());
  766. if(octave3DMesh != null)
  767. {
  768. TransformMatrix rootRelativeTransformMatrix = childTransform.GetRelativeTransformMatrix(rootTransform);
  769. rootRelativeTransformMatrix.Scale = rootRelativeTransformMatrix.Scale.GetVectorWithPositiveComponents();
  770. List<Vector3> vertexPositions = new List<Vector3>(octave3DMesh.VertexPositions);
  771. vertexPositions = Vector3Extensions.GetTransformedPoints(vertexPositions, rootRelativeTransformMatrix.ToMatrix4x4x);
  772. Box vertexBox = Vector3Extensions.GetPointCloudBox(vertexPositions);
  773. if (hierarchyModelSpaceBox.IsValid()) hierarchyModelSpaceBox.Encapsulate(vertexBox);
  774. else hierarchyModelSpaceBox = new Box(vertexBox);
  775. }
  776. else*/
  777. {
  778. Box childModelSpaceBox = childObject.GetModelSpaceBox();
  779. if (childModelSpaceBox.IsValid())
  780. {
  781. // Note: Negative scale values are a pain to work with, so we will set the scale to a positive value.
  782. // Negative scale causes problems inside 'Box.Transform' because it modifies the translation
  783. // in an undesirable manner. However, is it a good idea to ignore negative scale ???!!!
  784. TransformMatrix rootRelativeTransformMatrix = childTransform.GetRelativeTransformMatrix(rootTransform);
  785. rootRelativeTransformMatrix.Scale = rootRelativeTransformMatrix.Scale.GetVectorWithPositiveComponents();
  786. childModelSpaceBox = childModelSpaceBox.Transform(rootRelativeTransformMatrix);
  787. if (hierarchyModelSpaceBox.IsValid()) hierarchyModelSpaceBox.Encapsulate(childModelSpaceBox);
  788. else hierarchyModelSpaceBox = new Box(childModelSpaceBox);
  789. }
  790. }
  791. }
  792. }
  793. return hierarchyModelSpaceBox;
  794. }
  795. /*public static OrientedBox GetHierarchyModelSpaceOrientedBox(this GameObject hierarchyRoot)
  796. {
  797. Transform rootTransform = hierarchyRoot.transform;
  798. Transform[] allChildTransforms = hierarchyRoot.GetComponentsInChildren<Transform>();
  799. bool hierarchyContainsMesh = hierarchyRoot.DoesHierarchyContainMesh();
  800. OrientedBox hierarchyModelSpaceBox = hierarchyRoot.GetModelSpaceOrientedBox();
  801. foreach (Transform childTransform in allChildTransforms)
  802. {
  803. GameObject childObject = childTransform.gameObject;
  804. // If the hierarchy contains mesh objects, we will only take mesh objects into account
  805. if (!childObject.HasMesh() && hierarchyContainsMesh) continue;
  806. if (childObject != hierarchyRoot)
  807. {
  808. OrientedBox childModelSpaceBox = childObject.GetModelSpaceOrientedBox();
  809. if (childModelSpaceBox.IsValid())
  810. {
  811. // Note: Negative scale values are a pain to work with, so we will set the scale to a positive value.
  812. // Negative scale causes problems inside 'Box.Transform' because it modifies the translation
  813. // in an undesirable manner. However, is it a good idea to ignore negative scale ???!!!
  814. TransformMatrix rootRelativeTransformMatrix = childTransform.GetRelativeTransformMatrix(rootTransform);
  815. rootRelativeTransformMatrix.Scale = rootRelativeTransformMatrix.Scale.GetVectorWithPositiveComponents();
  816. childModelSpaceBox.Transform(rootRelativeTransformMatrix);
  817. if (hierarchyModelSpaceBox.IsValid()) hierarchyModelSpaceBox.Encapsulate(childModelSpaceBox);
  818. else hierarchyModelSpaceBox = new OrientedBox(childModelSpaceBox);
  819. }
  820. }
  821. }
  822. return hierarchyModelSpaceBox;
  823. }*/
  824. public static OrientedBox GetWorldOrientedBox(this GameObject gameObject)
  825. {
  826. OrientedBox worldOrientedBox = gameObject.GetMeshWorldOrientedBox();
  827. if (worldOrientedBox.IsValid()) return worldOrientedBox;
  828. return gameObject.GetNonMeshWorldOrientedBox();
  829. }
  830. public static Box GetWorldBox(this GameObject gameObject)
  831. {
  832. Box worldBox = gameObject.GetMeshWorldBox();
  833. if (worldBox.IsValid()) return worldBox;
  834. return gameObject.GetNonMeshWorldBox();
  835. }
  836. public static OrientedBox GetModelSpaceOrientedBox(this GameObject gameObject)
  837. {
  838. OrientedBox modelSpaceOrientedBox = gameObject.GetMeshModelSpaceOrientedBox();
  839. if (modelSpaceOrientedBox.IsValid()) return modelSpaceOrientedBox;
  840. return gameObject.GetNonMeshModelSpaceOrientedBox();
  841. }
  842. public static Box GetModelSpaceBox(this GameObject gameObject)
  843. {
  844. Box modelSpaceBox = gameObject.GetMeshModelSpaceBox();
  845. if (modelSpaceBox.IsValid()) return modelSpaceBox;
  846. return gameObject.GetNonMeshModelSpaceBox();
  847. }
  848. public static OrientedBox GetMeshWorldOrientedBox(this GameObject gameObject)
  849. {
  850. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  851. if (mesh != null) return new OrientedBox(new Box(mesh.bounds), gameObject.transform);
  852. mesh = gameObject.GetMeshFromSkinnedMeshRenderer();
  853. if (mesh != null) return new OrientedBox(new Box(gameObject.GetComponent<SkinnedMeshRenderer>().localBounds), gameObject.transform);
  854. return OrientedBox.GetInvalid();
  855. }
  856. public static Box GetMeshWorldBox(this GameObject gameObject)
  857. {
  858. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  859. if (mesh != null) return new Box(mesh.bounds).Transform(gameObject.transform.GetWorldMatrix());
  860. mesh = gameObject.GetMeshFromSkinnedMeshRenderer();
  861. if (mesh != null) return new Box(gameObject.GetComponent<SkinnedMeshRenderer>().localBounds).Transform(gameObject.transform.GetWorldMatrix());
  862. return Box.GetInvalid();
  863. }
  864. public static OrientedBox GetNonMeshWorldOrientedBox(this GameObject gameObject)
  865. {
  866. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  867. if(spriteRenderer != null)
  868. {
  869. return new OrientedBox(spriteRenderer.GetModelSpaceBox(), gameObject.transform);
  870. }
  871. else
  872. {
  873. OrientedBox modelSpaceOrientedBox = gameObject.GetNonMeshModelSpaceOrientedBox();
  874. if (!modelSpaceOrientedBox.IsValid()) return modelSpaceOrientedBox;
  875. OrientedBox worldOrientedBox = new OrientedBox(modelSpaceOrientedBox);
  876. Transform objectTransform = gameObject.transform;
  877. worldOrientedBox.Center = objectTransform.position;
  878. worldOrientedBox.Rotation = objectTransform.rotation;
  879. worldOrientedBox.Scale = objectTransform.lossyScale;
  880. return worldOrientedBox;
  881. }
  882. }
  883. public static Box GetNonMeshWorldBox(this GameObject gameObject)
  884. {
  885. Box modelSpaceBox = gameObject.GetNonMeshModelSpaceBox();
  886. if (!modelSpaceBox.IsValid()) return modelSpaceBox;
  887. Box worldBox = modelSpaceBox.Transform(gameObject.transform.GetWorldMatrix());
  888. return worldBox;
  889. }
  890. public static OrientedBox GetMeshModelSpaceOrientedBox(this GameObject gameObject)
  891. {
  892. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  893. if (mesh != null) return new OrientedBox(new Box(mesh.bounds), Quaternion.identity);
  894. mesh = gameObject.GetMeshFromSkinnedMeshRenderer();
  895. if (mesh != null) return new OrientedBox(new Box(gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh.bounds), Quaternion.identity);
  896. return OrientedBox.GetInvalid();
  897. }
  898. public static Box GetMeshModelSpaceBox(this GameObject gameObject)
  899. {
  900. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  901. if (mesh != null) return new Box(mesh.bounds);
  902. mesh = gameObject.GetMeshFromSkinnedMeshRenderer();
  903. if (mesh != null) return new Box(gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh.bounds);
  904. return Box.GetInvalid();
  905. }
  906. public static OrientedBox GetNonMeshModelSpaceOrientedBox(this GameObject gameObject)
  907. {
  908. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  909. if (spriteRenderer != null && spriteRenderer.sprite != null) return new OrientedBox(spriteRenderer.GetModelSpaceBox());
  910. if (!gameObject.HasLight() && !gameObject.HasParticleSystem()) return OrientedBox.GetInvalid();
  911. return new OrientedBox(gameObject.GetNonMeshModelSpaceBox());
  912. }
  913. public static Box GetNonMeshModelSpaceBox(this GameObject gameObject)
  914. {
  915. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  916. if (spriteRenderer != null && spriteRenderer.sprite != null) return spriteRenderer.GetModelSpaceBox();
  917. if (!gameObject.HasLight() && !gameObject.HasParticleSystem()) return Box.GetInvalid();
  918. return new Box(Vector3.zero, Octave3DScene.VolumeSizeForNonMeshObjects);
  919. }
  920. public static Renderer GetRenderer(this GameObject gameObject)
  921. {
  922. return gameObject.GetComponent<Renderer>();
  923. }
  924. public static bool IsSprite(this GameObject gameObject)
  925. {
  926. if (gameObject.HasMesh()) return false;
  927. SpriteRenderer spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
  928. return spriteRenderer != null && spriteRenderer.sprite != null;
  929. }
  930. public static Mesh GetMeshFromFilterOrSkinnedMeshRenderer(this GameObject gameObject)
  931. {
  932. Mesh mesh = gameObject.GetMeshFromMeshFilter();
  933. if (mesh == null) mesh = gameObject.GetMeshFromSkinnedMeshRenderer();
  934. return mesh;
  935. }
  936. public static Mesh GetMeshFromMeshFilter(this GameObject gameObject)
  937. {
  938. MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
  939. if (meshFilter != null && meshFilter.sharedMesh != null) return meshFilter.sharedMesh;
  940. return null;
  941. }
  942. public static Mesh GetMeshFromSkinnedMeshRenderer(this GameObject gameObject)
  943. {
  944. SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
  945. if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) return skinnedMeshRenderer.sharedMesh;
  946. return null;
  947. }
  948. #endregion
  949. #region Utilities
  950. public static List<GameObject> GetParents(IEnumerable<GameObject> gameObjects)
  951. {
  952. List<GameObject> topParents = new List<GameObject>();
  953. foreach (GameObject gameObject in gameObjects)
  954. {
  955. bool foundParentForThisObject = false;
  956. Transform gameObjectTransform = gameObject.transform;
  957. foreach (GameObject potentialParent in gameObjects)
  958. {
  959. if (gameObject != potentialParent &&
  960. gameObjectTransform.IsChildOf(potentialParent.transform))
  961. {
  962. foundParentForThisObject = true;
  963. break;
  964. }
  965. }
  966. if (!foundParentForThisObject) topParents.Add(gameObject);
  967. }
  968. return topParents;
  969. }
  970. public static List<GameObject> GetAllObjectsInHierarchyCollection(List<GameObject> hierarchyRoots)
  971. {
  972. var allGameObjects = new List<GameObject>(hierarchyRoots.Count);
  973. foreach(GameObject root in hierarchyRoots)
  974. {
  975. allGameObjects.AddRange(root.GetAllChildrenIncludingSelf());
  976. }
  977. return allGameObjects;
  978. }
  979. public static void RecordObjectTransformsForUndo(IEnumerable<GameObject> gameObjects)
  980. {
  981. List<Transform> objectTransforms = GetObjectTransforms(gameObjects);
  982. UndoEx.RecordForToolAction(objectTransforms);
  983. }
  984. public static List<Transform> GetObjectTransforms(IEnumerable<GameObject> gameObjects)
  985. {
  986. var objectTransforms = new List<Transform>();
  987. foreach(GameObject gameObject in gameObjects)
  988. {
  989. objectTransforms.Add(gameObject.transform);
  990. }
  991. return objectTransforms;
  992. }
  993. public static List<OrientedBox> GetHierarchyWorldOrientedBoxes(List<GameObject> hierarchyRoots)
  994. {
  995. if (hierarchyRoots.Count == 0) return new List<OrientedBox>();
  996. var orientedBoxes = new List<OrientedBox>(hierarchyRoots.Count);
  997. foreach (GameObject selectedObject in hierarchyRoots)
  998. {
  999. OrientedBox orientedBox = selectedObject.GetHierarchyWorldOrientedBox();
  1000. if (orientedBox.IsValid()) orientedBoxes.Add(orientedBox);
  1001. }
  1002. return orientedBoxes;
  1003. }
  1004. public static void SetSelectedHierarchyWireframeHidden(List<GameObject> hierarchyRoots, bool isWireframeHidden)
  1005. {
  1006. foreach(GameObject root in hierarchyRoots)
  1007. {
  1008. root.SetSelectedHierarchyWireframeHidden(isWireframeHidden);
  1009. }
  1010. }
  1011. public static void SetHierarchyLayer(this GameObject root, int layer, bool allowUndoRedo)
  1012. {
  1013. var allObjects = root.GetAllChildrenIncludingSelf();
  1014. AssignGameObjectsToLayer(allObjects, layer, allowUndoRedo);
  1015. }
  1016. public static void AssignGameObjectsToLayer(List<GameObject> gameObjects, int objectLayer, bool allowUndoRedo)
  1017. {
  1018. if(allowUndoRedo)
  1019. {
  1020. foreach (GameObject gameObject in gameObjects)
  1021. {
  1022. UndoEx.RecordForToolAction(gameObject);
  1023. gameObject.layer = objectLayer;
  1024. }
  1025. }
  1026. else
  1027. {
  1028. foreach (GameObject gameObject in gameObjects)
  1029. {
  1030. gameObject.layer = objectLayer;
  1031. }
  1032. }
  1033. }
  1034. public static List<GameObject> GetObjectsWithMesh(List<GameObject> gameObjects)
  1035. {
  1036. if (gameObjects.Count == 0) return new List<GameObject>();
  1037. var objectsWithMesh = new List<GameObject>(gameObjects.Count);
  1038. foreach(var gameObject in gameObjects)
  1039. {
  1040. if (gameObject.HasMesh()) objectsWithMesh.Add(gameObject);
  1041. }
  1042. return objectsWithMesh;
  1043. }
  1044. #endregion
  1045. }
  1046. }
  1047. #endif