| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- using UnityEngine;
- using UnityEditor;
- using System;
- using System.Collections.Generic;
- using Cinemachine.Utility;
- using System.Reflection;
- using System.Linq;
- namespace Cinemachine.Editor
- {
- [CustomEditor(typeof(CinemachineVirtualCamera))]
- [CanEditMultipleObjects]
- internal class CinemachineVirtualCameraEditor
- : CinemachineVirtualCameraBaseEditor<CinemachineVirtualCamera>
- {
- VcamStageEditorPipeline m_PipelineSet = new VcamStageEditorPipeline();
- [MenuItem("CONTEXT/CinemachineVirtualCamera/Adopt Game View Camera Settings")]
- static void AdoptGameViewCameraSettings(MenuCommand command)
- {
- var vcam = command.context as CinemachineVirtualCamera;
- var brain = CinemachineCore.Instance.FindPotentialTargetBrain(vcam);
- if (brain != null)
- {
- vcam.m_Lens = brain.CurrentCameraState.Lens;
- vcam.transform.position = brain.transform.position;
- vcam.transform.rotation = brain.transform.rotation;
- }
- }
- [MenuItem("CONTEXT/CinemachineVirtualCamera/Adopt Scene View Camera Settings")]
- static void AdoptSceneViewCameraSettings(MenuCommand command)
- {
- var vcam = command.context as CinemachineVirtualCamera;
- vcam.m_Lens = CinemachineMenu.MatchSceneViewCamera(vcam.transform);
- }
-
- protected override void OnEnable()
- {
- base.OnEnable();
- Undo.undoRedoPerformed += ResetTargetOnUndo;
- m_PipelineSet.Initialize(
- // GetComponent
- (stage, result) =>
- {
- int numNullComponents = 0;
- foreach (var obj in targets)
- {
- var vcam = obj as CinemachineVirtualCamera;
- if (vcam != null)
- {
- var c = vcam.GetCinemachineComponent(stage);
- if (c != null)
- result.Add(c);
- else
- ++numNullComponents;
- }
- }
- return numNullComponents;
- },
- // SetComponent
- (stage, type) =>
- {
- Undo.SetCurrentGroupName("Cinemachine pipeline change");
- foreach (var obj in targets)
- {
- var vcam = obj as CinemachineVirtualCamera;
- Transform owner = vcam == null ? null : vcam.GetComponentOwner();
- if (owner == null)
- continue; // maybe it's a prefab
- var c = vcam.GetCinemachineComponent(stage);
- if (c != null && c.GetType() == type)
- continue;
- if (c != null)
- {
- Undo.DestroyObjectImmediate(c);
- vcam.InvalidateComponentPipeline();
- }
- if (type != null)
- {
- Undo.AddComponent(owner.gameObject, type);
- vcam.InvalidateComponentPipeline();
- }
- }
- });
- // We only look at the first target here, on purpose
- if (Target != null && Target.m_LockStageInInspector != null)
- foreach (var s in Target.m_LockStageInInspector)
- m_PipelineSet.SetStageIsLocked(s);
-
- #if UNITY_2021_2_OR_NEWER
- CinemachineSceneToolUtility.RegisterTool(typeof(FoVTool));
- CinemachineSceneToolUtility.RegisterTool(typeof(FarNearClipTool));
- #endif
- }
- protected override void OnDisable()
- {
- Undo.undoRedoPerformed -= ResetTargetOnUndo;
- m_PipelineSet.Shutdown();
- base.OnDisable();
-
- #if UNITY_2021_2_OR_NEWER
- CinemachineSceneToolUtility.UnregisterTool(typeof(FoVTool));
- CinemachineSceneToolUtility.UnregisterTool(typeof(FarNearClipTool));
- #endif
- }
- void OnSceneGUI()
- {
- m_PipelineSet.OnSceneGUI(); // call hidden editors' OnSceneGUI
-
- #if UNITY_2021_2_OR_NEWER
- DrawSceneTools();
- #endif
- }
- #if UNITY_2021_2_OR_NEWER
- void DrawSceneTools()
- {
- var vcam = Target;
- if (vcam == null || !vcam.IsValid || vcam.m_ExcludedPropertiesInInspector.Contains("m_Lens"))
- {
- return;
- }
- var originalColor = Handles.color;
- Handles.color = Handles.preselectionColor;
- if (CinemachineSceneToolUtility.IsToolActive(typeof(FoVTool)))
- {
- CinemachineSceneToolHelpers.FovToolHandle(vcam,
- new SerializedObject(vcam).FindProperty(() => vcam.m_Lens),
- vcam.m_Lens, IsHorizontalFOVUsed());
- }
- else if (CinemachineSceneToolUtility.IsToolActive(typeof(FarNearClipTool)))
- {
- CinemachineSceneToolHelpers.NearFarClipHandle(vcam,
- new SerializedObject(vcam).FindProperty(() => vcam.m_Lens));
- }
- Handles.color = originalColor;
- }
- #endif
- public override void OnInspectorGUI()
- {
- if (Target.GetComponentOwner() == null)
- {
- EditorGUILayout.HelpBox(
- "It's not possible to add this component to a prefab instance. "
- + "Instead, you can open the Prefab in Prefab Mode or unpack "
- + "the Prefab instance to remove the Prefab connection.",
- MessageType.Error);
- return;
- }
- BeginInspector();
- DrawHeaderInInspector();
- DrawPropertyInInspector(FindProperty(x => x.m_Priority));
- DrawTargetsInInspector(FindProperty(x => x.m_Follow), FindProperty(x => x.m_LookAt));
- DrawPropertyInInspector(FindProperty(x => x.m_StandbyUpdate));
- DrawLensSettingsInInspector(FindProperty(x => x.m_Lens));
- DrawRemainingPropertiesInInspector();
- m_PipelineSet.OnInspectorGUI(!IsPropertyExcluded("Header"));
- DrawExtensionsWidgetInInspector();
- }
- void ResetTargetOnUndo()
- {
- ResetTarget();
- for (int i = 0; i < targets.Length; ++i)
- (targets[i] as CinemachineVirtualCamera).InvalidateComponentPipeline();
- }
- /// <summary>
- /// Register with CinemachineVirtualCamera to create the pipeline in an undo-friendly manner
- /// </summary>
- [InitializeOnLoad]
- class CreatePipelineWithUndo
- {
- static CreatePipelineWithUndo()
- {
- CinemachineVirtualCamera.CreatePipelineOverride =
- (CinemachineVirtualCamera vcam, string name, CinemachineComponentBase[] copyFrom) =>
- {
- // Recycle existing pipeline child (if any)
- GameObject go = null;
- foreach (Transform child in vcam.transform)
- {
- if (child.GetComponent<CinemachinePipeline>() != null)
- {
- go = child.gameObject;
- break;
- }
- }
- if (go == null)
- {
- // Create a new pipeline - can't do it if prefab instance
- if (PrefabUtility.IsPartOfAnyPrefab(vcam.gameObject))
- return null;
- go = ObjectFactory.CreateGameObject(name);
- Undo.RegisterCreatedObjectUndo(go, "created pipeline");
- Undo.SetTransformParent(go.transform, vcam.transform, "parenting pipeline");
- Undo.AddComponent<CinemachinePipeline>(go);
- }
- var oldStuff = go.GetComponents<CinemachineComponentBase>();
- foreach (var c in oldStuff)
- Undo.DestroyObjectImmediate(c);
- // If copying, transfer the components
- if (copyFrom != null)
- {
- foreach (Component c in copyFrom)
- {
- Component copy = Undo.AddComponent(go, c.GetType());
- Undo.RecordObject(copy, "copying pipeline");
- ReflectionHelpers.CopyFields(c, copy);
- }
- }
- return go.transform;
- };
- CinemachineVirtualCamera.DestroyPipelineOverride = (GameObject pipeline) =>
- {
- var oldStuff = pipeline.GetComponents<CinemachineComponentBase>();
- foreach (var c in oldStuff)
- Undo.DestroyObjectImmediate(c);
- // Cannot create or destroy child objects if prefab.
- // Just leave it there in that case, it will get discovered and recycled.
- if (!PrefabUtility.IsPartOfAnyPrefab(pipeline))
- Undo.DestroyObjectImmediate(pipeline);
- };
- }
- }
- // Because the cinemachine components are attached to hidden objects, their
- // gizmos don't get drawn by default. We have to do it explicitly.
- [InitializeOnLoad]
- static class CollectGizmoDrawers
- {
- static CollectGizmoDrawers()
- {
- m_GizmoDrawers = new Dictionary<Type, MethodInfo>();
- string definedIn = typeof(CinemachineComponentBase).Assembly.GetName().Name;
- Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
- foreach (Assembly assembly in assemblies)
- {
- // Note that we have to call GetName().Name. Just GetName() will not work.
- if ((!assembly.GlobalAssemblyCache)
- && ((assembly.GetName().Name == definedIn)
- || assembly.GetReferencedAssemblies().Any(a => a.Name == definedIn)))
- {
- try
- {
- foreach (var type in assembly.GetTypes())
- {
- try
- {
- bool added = false;
- foreach (var method in type.GetMethods(
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
- {
- if (added)
- break;
- if (!method.IsStatic)
- continue;
- var attributes = method.GetCustomAttributes(typeof(DrawGizmo), true) as DrawGizmo[];
- foreach (var a in attributes)
- {
- if (typeof(CinemachineComponentBase).IsAssignableFrom(a.drawnType) && !a.drawnType.IsAbstract)
- {
- m_GizmoDrawers.Add(a.drawnType, method);
- added = true;
- break;
- }
- }
- }
- }
- catch (Exception) {} // Just skip uncooperative types
- }
- }
- catch (Exception) {} // Just skip uncooperative assemblies
- }
- }
- }
- public static Dictionary<Type, MethodInfo> m_GizmoDrawers;
- }
- [DrawGizmo(GizmoType.Active | GizmoType.InSelectionHierarchy, typeof(CinemachineVirtualCamera))]
- internal static void DrawVirtualCameraGizmos(CinemachineVirtualCamera vcam, GizmoType selectionType)
- {
- var pipeline = vcam.GetComponentPipeline();
- if (pipeline != null)
- {
- foreach (var c in pipeline)
- {
- if (c == null)
- continue;
- MethodInfo method;
- if (CollectGizmoDrawers.m_GizmoDrawers.TryGetValue(c.GetType(), out method))
- {
- if (method != null)
- method.Invoke(null, new object[] {c, selectionType});
- }
- }
- }
- }
- }
- }
|