// This code dynamically discovers eligible classes and builds the menu
        // data for the various component pipeline stages.
        static void UpdateStaticData()
        {
            if (sStageData != null)
            {
                return;
            }
            sStageData = new StageData[Enum.GetValues(typeof(CinemachineCore.Stage)).Length];

            var stageTypes = new List <Type> [Enum.GetValues(typeof(CinemachineCore.Stage)).Length];

            for (int i = 0; i < stageTypes.Length; ++i)
            {
                sStageData[i].Name = ((CinemachineCore.Stage)i).ToString();
                stageTypes[i]      = new List <Type>();
            }

            // Get all ICinemachineComponents
            var allTypes
                = ReflectionHelpers.GetTypesInAllDependentAssemblies(
                      (Type t) => typeof(CinemachineComponentBase).IsAssignableFrom(t) && !t.IsAbstract);

            // Create a temp game object so we can instance behaviours
            GameObject go = new GameObject("Cinemachine Temp Object");

            go.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
            foreach (Type t in allTypes)
            {
                MonoBehaviour            b = go.AddComponent(t) as MonoBehaviour;
                CinemachineComponentBase c = b != null ? (CinemachineComponentBase)b : null;
                if (c != null)
                {
                    CinemachineCore.Stage stage = c.Stage;
                    stageTypes[(int)stage].Add(t);
                }
            }
            GameObject.DestroyImmediate(go);

            // Create the static lists
            for (int i = 0; i < stageTypes.Length; ++i)
            {
                stageTypes[i].Insert(0, null);  // first item is "none"
                sStageData[i].types = stageTypes[i].ToArray();
                GUIContent[] names = new GUIContent[sStageData[i].types.Length];
                for (int n = 0; n < names.Length; ++n)
                {
                    if (n == 0)
                    {
                        bool useSimple
                            = (i == (int)CinemachineCore.Stage.Aim) ||
                              (i == (int)CinemachineCore.Stage.Body);
                        names[n] = new GUIContent((useSimple) ? "Do nothing" : "none");
                    }
                    else
                    {
                        names[n] = new GUIContent(InspectorUtility.NicifyClassName(sStageData[i].types[n].Name));
                    }
                }
                sStageData[i].PopupOptions = names;
            }
        }
Exemple #2
0
        PopupLists GetPopupLists(GameObject obj)
        {
            PopupLists lists = null;

            if (!mPopupCache.TryGetValue(obj, out lists))
            {
                List <string> events = ReflectionHelpers.GetAllFieldOfType(typeof(UnityEvent), obj);
                events.Insert(0, string.Empty);
                List <string> displayNames = new List <string>();
                displayNames.InsertRange(0, events);
                for (int i = 1; i < displayNames.Count; ++i)
                {
                    string[] parts = displayNames[i].Split('.');
                    for (int j = 0; j < parts.Length; ++j)
                    {
                        parts[j] = InspectorUtility.NicifyClassName(parts[j]);
                    }
                    displayNames[i] = string.Join("/", parts);
                }
                displayNames[0] = "(none)";
                lists           = new PopupLists {
                    eventNames = events, displayNames = displayNames
                };
            }
            return(lists);
        }
        protected void DrawPipelineInInspector()
        {
            UpdateInstanceData();
            foreach (CinemachineCore.Stage stage in Enum.GetValues(typeof(CinemachineCore.Stage)))
            {
                int index = (int)stage;

                // Skip pipeline stages that have no implementations
                if (index < 0 || sStageData[index].PopupOptions.Length <= 1)
                {
                    continue;
                }

                const float indentOffset = 4;

                GUIStyle stageBoxStyle = GUI.skin.box;
                EditorGUILayout.BeginVertical(stageBoxStyle);
                Rect rect = EditorGUILayout.GetControlRect(true);

                // Don't use PrefixLabel() because it will link the enabled status of field and label
                GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(stage.ToString()));
                if (m_stageError[index])
                {
                    label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
                }
                float labelWidth = EditorGUIUtility.labelWidth - (indentOffset + EditorGUI.indentLevel * 15);
                Rect  r          = rect; r.width = labelWidth;
                EditorGUI.LabelField(r, label);
                r = rect; r.width -= labelWidth; r.x += labelWidth;

                EditorGUI.BeginChangeCheck();
                GUI.enabled = !StageIsLocked(stage);
                EditorGUI.showMixedValue = !m_hasSameStageDataTypes[index];
                int newSelection = EditorGUI.Popup(r, m_stageState[index], sStageData[index].PopupOptions);
                EditorGUI.showMixedValue = false;
                GUI.enabled = true;
                Type type = sStageData[index].types[newSelection];
                if (EditorGUI.EndChangeCheck())
                {
                    SetPipelineStage(stage, type);
                    if (newSelection != 0)
                    {
                        sStageData[index].IsExpanded = true;
                    }
                    UpdateInstanceData(); // because we changed it
                    ResetTarget();        // to allow multi-selection correctly adjust every target

                    return;
                }
                if (type != null)
                {
                    Rect stageRect = new Rect(
                        rect.x - indentOffset, rect.y, rect.width + indentOffset, rect.height);
                    sStageData[index].IsExpanded = EditorGUI.Foldout(
                        stageRect, sStageData[index].IsExpanded, GUIContent.none, true);
                    if (sStageData[index].IsExpanded)
                    {
                        // Make the editor for that stage
                        UnityEditor.Editor e = GetEditorForPipelineStage(stage);
                        if (e != null)
                        {
                            ++EditorGUI.indentLevel;
                            EditorGUILayout.Separator();
                            e.OnInspectorGUI();

                            EditorGUILayout.Separator();
                            --EditorGUI.indentLevel;
                        }
                    }
                }
                EditorGUILayout.EndVertical();
            }
        }
Exemple #4
0
        private void DrawComponentInspector()
        {
            const float kBoxMargin = 4;  // GML wtf get rid of this
            const float indentSize = 15; // GML wtf get rid of this

            int index = (int)mStage;

            EditorGUILayout.BeginVertical(GUI.skin.box);
            EditorGUIUtility.labelWidth -= kBoxMargin;

            Rect rect = EditorGUILayout.GetControlRect(true);

            // Don't use PrefixLabel() because it will link the enabled status of field and label
            GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(mStage.ToString()));

            if (mStageError)
            {
                label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
            }
            float labelWidth = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * indentSize;
            Rect  r          = rect; r.width = labelWidth; r.x -= kBoxMargin;

            EditorGUI.LabelField(r, label);

            r = rect; r.width -= labelWidth; r.x += labelWidth;
            bool wasEnabled = GUI.enabled;

            if (TypeIsLocked)
            {
                GUI.enabled = false;
            }
            int newSelection = EditorGUI.Popup(r, mStageSelection, sStageData[index].PopupOptions);

            GUI.enabled = wasEnabled;

            Type type = sStageData[index].types[newSelection];

            if (newSelection != mStageSelection)
            {
                if (mComponent != null)
                {
                    if (DestroyComponent != null)
                    {
                        DestroyComponent(mComponent);
                    }
                }
                if (newSelection != 0)
                {
                    sStageData[index].IsExpanded = true;
                    if (SetComponent != null)
                    {
                        SetComponent(type);
                    }
                }
                mComponent = null;
                GUIUtility.ExitGUI();
                return; // let the component editor be recreated
            }

            // Draw the embedded editor
            if (type != null)
            {
                r = new Rect(rect.x - kBoxMargin, rect.y, labelWidth, rect.height);
                sStageData[index].IsExpanded = EditorGUI.Foldout(
                    r, sStageData[index].IsExpanded, GUIContent.none, true);
                if (sStageData[index].IsExpanded)
                {
                    // Make the editor for that stage
                    if (mComponentEditor != null)
                    {
                        ++EditorGUI.indentLevel;
                        EditorGUILayout.Separator();
                        mComponentEditor.OnInspectorGUI();
                        EditorGUILayout.Separator();
                        --EditorGUI.indentLevel;
                    }
                }
            }
            EditorGUILayout.EndVertical();
            EditorGUIUtility.labelWidth += kBoxMargin;
        }
Exemple #5
0
        void AssetFieldWithCreateButton(
            Rect r, SerializedProperty property, bool warnIfNull, string defaultName)
        {
            // Collect all the eligible asset types
            Type type = EmbeddedAssetType(property);

            if (mAssetTypes == null)
            {
                mAssetTypes = ReflectionHelpers.GetTypesInAllLoadedAssemblies(
                    (Type t) => t.IsSubclassOf(type)).ToArray();
            }

            float iconSize = r.height + 4;

            r.width -= iconSize;

            GUIContent label = new GUIContent(property.displayName, property.tooltip);

            if (warnIfNull && property.objectReferenceValue == null)
            {
                label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
            }
            EditorGUI.PropertyField(r, property, label);

            r.x += r.width; r.width = iconSize; r.height = iconSize;
            if (GUI.Button(r, EditorGUIUtility.IconContent("_Popup"), GUI.skin.label))
            {
                GenericMenu menu = new GenericMenu();
                if (property.objectReferenceValue != null)
                {
                    menu.AddItem(new GUIContent("Edit"), false, ()
                                 => Selection.activeObject = property.objectReferenceValue);
                    menu.AddItem(new GUIContent("Clone"), false, () =>
                    {
                        ScriptableObject copyFrom = property.objectReferenceValue as ScriptableObject;
                        if (copyFrom != null)
                        {
                            string title           = "Create New " + copyFrom.GetType().Name + " asset";
                            ScriptableObject asset = CreateAsset(
                                copyFrom.GetType(), copyFrom, defaultName, title);
                            if (asset != null)
                            {
                                property.objectReferenceValue = asset;
                                property.serializedObject.ApplyModifiedProperties();
                            }
                        }
                    });
                    menu.AddItem(new GUIContent("Locate"), false, ()
                                 => EditorGUIUtility.PingObject(property.objectReferenceValue));
                }

                RebuildPresetList();
                int i = 0;
                foreach (var a in mAssetPresets)
                {
                    menu.AddItem(mAssetPresetNames[i++], false, () =>
                    {
                        property.objectReferenceValue = a;
                        property.serializedObject.ApplyModifiedProperties();
                    });
                }

                foreach (var t in mAssetTypes)
                {
                    menu.AddItem(new GUIContent("New " + InspectorUtility.NicifyClassName(t.Name)), false, () =>
                    {
                        string title           = "Create New " + t.Name + " asset";
                        ScriptableObject asset = CreateAsset(t, null, defaultName, title);
                        if (asset != null)
                        {
                            property.objectReferenceValue = asset;
                            property.serializedObject.ApplyModifiedProperties();
                        }
                    });
                }
                menu.ShowAsContext();
            }
        }
        private void DrawComponentInspector()
        {
            const float indentSize = 15; // GML wtf get rid of this
            int         index      = (int)m_Stage;
            Rect        rect       = EditorGUILayout.GetControlRect(true);

            // Don't use PrefixLabel() because it will link the enabled status of field and label
            GUIContent label = new GUIContent(InspectorUtility.NicifyClassName(m_Stage.ToString()));

            if (m_StageError)
            {
                label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
            }
            float labelWidth = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * indentSize;
            Rect  r          = rect; r.width = labelWidth;

            EditorGUI.LabelField(r, label);

            r = rect; r.width -= labelWidth; r.x += labelWidth;

            EditorGUI.BeginChangeCheck();
            bool wasEnabled = GUI.enabled;

            if (TypeIsLocked)
            {
                GUI.enabled = false;
            }
            EditorGUI.showMixedValue = m_IsMixedType;
            m_StageSelection         = EditorGUI.Popup(r, m_StageSelection, sStageData[index].PopupOptions);
            EditorGUI.showMixedValue = false;
            GUI.enabled = wasEnabled;
            Type type = sStageData[index].types[m_StageSelection];

            if (EditorGUI.EndChangeCheck())
            {
                SetComponent(m_Stage, type);
                if (m_StageSelection != 0)
                {
                    sStageData[index].IsExpanded = true;
                }
                Shutdown();
                GUIUtility.ExitGUI();
                return; // let the component editor be recreated
            }

            // Draw the embedded editor
            if (type != null)
            {
                r = new Rect(rect.x, rect.y, labelWidth, rect.height);
                var isExpanded = m_IsMixedType ? false : EditorGUI.Foldout(
                    r, sStageData[index].IsExpanded, GUIContent.none, true);
                if (isExpanded || isExpanded != sStageData[index].IsExpanded)
                {
                    // Make the editor for that stage
                    ActiveEditorRegistry.SetActiveEditor(m_ComponentEditor, isExpanded);
                    if (isExpanded && m_ComponentEditor != null)
                    {
                        ++EditorGUI.indentLevel;
                        m_ComponentEditor.OnInspectorGUI();
                        --EditorGUI.indentLevel;
                    }
                }
                sStageData[index].IsExpanded = isExpanded;
            }
        }