CinemachineClearShotEditor.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #if !UNITY_2019_3_OR_NEWER
  2. #define CINEMACHINE_PHYSICS
  3. #define CINEMACHINE_PHYSICS_2D
  4. #endif
  5. using UnityEditor;
  6. using UnityEngine;
  7. namespace Cinemachine.Editor
  8. {
  9. #if CINEMACHINE_PHYSICS
  10. [CustomEditor(typeof(CinemachineClearShot))]
  11. [CanEditMultipleObjects]
  12. internal sealed class CinemachineClearShotEditor
  13. : CinemachineVirtualCameraBaseEditor<CinemachineClearShot>
  14. {
  15. EmbeddeAssetEditor<CinemachineBlenderSettings> m_BlendsEditor;
  16. ColliderState m_ColliderState;
  17. private UnityEditorInternal.ReorderableList mChildList;
  18. protected override void OnEnable()
  19. {
  20. base.OnEnable();
  21. m_BlendsEditor = new EmbeddeAssetEditor<CinemachineBlenderSettings>(
  22. FieldPath(x => x.m_CustomBlends), this);
  23. m_BlendsEditor.OnChanged = (CinemachineBlenderSettings b) =>
  24. {
  25. InspectorUtility.RepaintGameView();
  26. };
  27. m_BlendsEditor.OnCreateEditor = (UnityEditor.Editor ed) =>
  28. {
  29. CinemachineBlenderSettingsEditor editor = ed as CinemachineBlenderSettingsEditor;
  30. if (editor != null)
  31. editor.GetAllVirtualCameras = () => { return Target.ChildCameras; };
  32. };
  33. mChildList = null;
  34. }
  35. protected override void OnDisable()
  36. {
  37. base.OnDisable();
  38. if (m_BlendsEditor != null)
  39. m_BlendsEditor.OnDisable();
  40. }
  41. public override void OnInspectorGUI()
  42. {
  43. BeginInspector();
  44. if (mChildList == null)
  45. SetupChildList();
  46. m_ColliderState = GetColliderState();
  47. switch (m_ColliderState)
  48. {
  49. case ColliderState.ColliderOnParent:
  50. case ColliderState.ColliderOnAllChildren:
  51. break;
  52. case ColliderState.NoCollider:
  53. EditorGUILayout.HelpBox(
  54. "ClearShot requires a Collider extension to rank the shots. Either add one to the ClearShot itself, or to each of the child cameras.",
  55. MessageType.Warning);
  56. break;
  57. case ColliderState.ColliderOnSomeChildren:
  58. EditorGUILayout.HelpBox(
  59. "Some child cameras do not have a Collider extension. ClearShot requires a Collider on all the child cameras, or alternatively on the ClearShot iself.",
  60. MessageType.Warning);
  61. break;
  62. case ColliderState.ColliderOnChildrenAndParent:
  63. EditorGUILayout.HelpBox(
  64. "There is a Collider extension on the ClearShot camera, and also on some of its child cameras. You can't have both.",
  65. MessageType.Error);
  66. break;
  67. }
  68. DrawHeaderInInspector();
  69. DrawPropertyInInspector(FindProperty(x => x.m_Priority));
  70. DrawTargetsInInspector(FindProperty(x => x.m_Follow), FindProperty(x => x.m_LookAt));
  71. DrawRemainingPropertiesInInspector();
  72. // Blends
  73. m_BlendsEditor.DrawEditorCombo(
  74. "Create New Blender Asset",
  75. Target.gameObject.name + " Blends", "asset", string.Empty,
  76. "Custom Blends", false);
  77. // vcam children
  78. EditorGUILayout.Separator();
  79. if (Selection.objects.Length == 1)
  80. {
  81. EditorGUI.BeginChangeCheck();
  82. mChildList.DoLayoutList();
  83. if (EditorGUI.EndChangeCheck())
  84. serializedObject.ApplyModifiedProperties();
  85. }
  86. else
  87. {
  88. EditorGUILayout.HelpBox(Styles.virtualCameraChildrenInfoMsg.text, MessageType.Info);
  89. }
  90. // Extensions
  91. DrawExtensionsWidgetInInspector();
  92. }
  93. enum ColliderState
  94. {
  95. NoCollider,
  96. ColliderOnAllChildren,
  97. ColliderOnSomeChildren,
  98. ColliderOnParent,
  99. ColliderOnChildrenAndParent
  100. }
  101. ColliderState GetColliderState()
  102. {
  103. int numChildren = 0;
  104. int numColliderChildren = 0;
  105. bool colliderOnParent = ObjectHasCollider(Target);
  106. var children = Target.m_ChildCameras;
  107. numChildren = children == null ? 0 : children.Length;
  108. for (int i = 0; i < numChildren; ++i)
  109. if (ObjectHasCollider(children[i]))
  110. ++numColliderChildren;
  111. if (colliderOnParent)
  112. return (numColliderChildren > 0)
  113. ? ColliderState.ColliderOnChildrenAndParent : ColliderState.ColliderOnParent;
  114. if (numColliderChildren > 0)
  115. return (numColliderChildren == numChildren)
  116. ? ColliderState.ColliderOnAllChildren : ColliderState.ColliderOnSomeChildren;
  117. return ColliderState.NoCollider;
  118. }
  119. bool ObjectHasCollider(object obj)
  120. {
  121. CinemachineVirtualCameraBase vcam = obj as CinemachineVirtualCameraBase;
  122. var collider = (vcam == null) ? null : vcam.GetComponent<CinemachineCollider>();
  123. return (collider != null && collider.enabled);
  124. }
  125. void SetupChildList()
  126. {
  127. float vSpace = 2;
  128. float hSpace = 3;
  129. float floatFieldWidth = EditorGUIUtility.singleLineHeight * 2.5f;
  130. mChildList = new UnityEditorInternal.ReorderableList(
  131. serializedObject, FindProperty(x => x.m_ChildCameras), true, true, true, true);
  132. mChildList.drawHeaderCallback = (Rect rect) =>
  133. {
  134. EditorGUI.LabelField(rect, "Virtual Camera Children");
  135. GUIContent priorityText = new GUIContent("Priority");
  136. var textDimensions = GUI.skin.label.CalcSize(priorityText);
  137. rect.x += rect.width - textDimensions.x;
  138. rect.width = textDimensions.x;
  139. EditorGUI.LabelField(rect, priorityText);
  140. };
  141. mChildList.drawElementCallback
  142. = (Rect rect, int index, bool isActive, bool isFocused) =>
  143. {
  144. rect.y += vSpace;
  145. rect.width -= floatFieldWidth + hSpace;
  146. rect.height = EditorGUIUtility.singleLineHeight;
  147. SerializedProperty element = mChildList.serializedProperty.GetArrayElementAtIndex(index);
  148. if (m_ColliderState == ColliderState.ColliderOnSomeChildren
  149. || m_ColliderState == ColliderState.ColliderOnChildrenAndParent)
  150. {
  151. bool hasCollider = ObjectHasCollider(element.objectReferenceValue);
  152. if ((m_ColliderState == ColliderState.ColliderOnSomeChildren && !hasCollider)
  153. || (m_ColliderState == ColliderState.ColliderOnChildrenAndParent && hasCollider))
  154. {
  155. float width = rect.width;
  156. rect.width = rect.height;
  157. GUIContent label = new GUIContent("");
  158. label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
  159. EditorGUI.LabelField(rect, label);
  160. width -= rect.width; rect.x += rect.width; rect.width = width;
  161. }
  162. }
  163. EditorGUI.PropertyField(rect, element, GUIContent.none);
  164. SerializedObject obj = new SerializedObject(element.objectReferenceValue);
  165. rect.x += rect.width + hSpace; rect.width = floatFieldWidth;
  166. SerializedProperty priorityProp = obj.FindProperty(() => Target.m_Priority);
  167. float oldWidth = EditorGUIUtility.labelWidth;
  168. EditorGUIUtility.labelWidth = hSpace * 2;
  169. EditorGUI.PropertyField(rect, priorityProp, new GUIContent(" "));
  170. EditorGUIUtility.labelWidth = oldWidth;
  171. obj.ApplyModifiedProperties();
  172. };
  173. mChildList.onChangedCallback = (UnityEditorInternal.ReorderableList l) =>
  174. {
  175. if (l.index < 0 || l.index >= l.serializedProperty.arraySize)
  176. return;
  177. Object o = l.serializedProperty.GetArrayElementAtIndex(
  178. l.index).objectReferenceValue;
  179. CinemachineVirtualCameraBase vcam = (o != null)
  180. ? (o as CinemachineVirtualCameraBase) : null;
  181. if (vcam != null)
  182. vcam.transform.SetSiblingIndex(l.index);
  183. };
  184. mChildList.onAddCallback = (UnityEditorInternal.ReorderableList l) =>
  185. {
  186. var index = l.serializedProperty.arraySize;
  187. var vcam = CinemachineMenu.CreateDefaultVirtualCamera();
  188. Undo.SetTransformParent(vcam.transform, Target.transform, "");
  189. var collider = Undo.AddComponent<CinemachineCollider>(vcam.gameObject);
  190. collider.m_AvoidObstacles = false;
  191. Undo.RecordObject(collider, "create ClearShot child");
  192. vcam.transform.SetSiblingIndex(index);
  193. };
  194. mChildList.onRemoveCallback = (UnityEditorInternal.ReorderableList l) =>
  195. {
  196. Object o = l.serializedProperty.GetArrayElementAtIndex(
  197. l.index).objectReferenceValue;
  198. CinemachineVirtualCameraBase vcam = (o != null)
  199. ? (o as CinemachineVirtualCameraBase) : null;
  200. if (vcam != null)
  201. Undo.DestroyObjectImmediate(vcam.gameObject);
  202. };
  203. }
  204. }
  205. #endif
  206. }