internal void RemovePropertiesByIds(IEnumerable <int> ids, bool removeCompleteGroup = true)
        {
            List <EditorCurveBinding> bindingsToRemove = new List <EditorCurveBinding>();

            foreach (int selectedId in ids)
            {
                BindingTreeViewDataSource bindingTree = m_BindingHierarchy.treeViewController.data as BindingTreeViewDataSource;
                CurveTreeViewNode         node        = bindingTree.FindItem(selectedId) as CurveTreeViewNode;
                if (node == null)
                {
                    continue;
                }
                foreach (EditorCurveBinding editorCurveBinding in node.bindings)
                {
                    if (bindingsToRemove.Contains(editorCurveBinding))
                    {
                        continue;
                    }
                    CurveTreeViewNode currentNode = node;
                    do
                    {
                        //check if property is part of a group
                        bool isRoot  = currentNode.depth == 0;
                        bool isGroup = currentNode.displayName == BindingTreeViewDataSource.GroupName(editorCurveBinding);
                        if (!isRoot && !isGroup && removeCompleteGroup)
                        {
                            currentNode = currentNode.parent as CurveTreeViewNode;
                        }
                        else
                        {
                            if (!AnimationWindowUtility.ForceGrouping(editorCurveBinding))
                            {
                                bindingsToRemove.Add(editorCurveBinding);
                            }
                            else //Group to remove
                            {
                                bindingsToRemove.AddRange(currentNode.bindings);
                            }
                            break;
                        }
                    }while (currentNode != null);
                }
            }

            RemoveProperty(bindingsToRemove);
            m_BindingHierarchy.RefreshTree();
            TimelineWindow.instance.state.CalculateRowRects();
        }
        private void RemoveCurvesFromNodes(List <AnimationWindowHierarchyNode> nodes)
        {
            string undoLabel = "Remove Curve";

            state.SaveKeySelection(undoLabel);

            foreach (var node in nodes)
            {
                AnimationWindowHierarchyNode hierarchyNode = (AnimationWindowHierarchyNode)node;

                if (hierarchyNode.parent is AnimationWindowHierarchyPropertyGroupNode && hierarchyNode.binding != null && AnimationWindowUtility.ForceGrouping((EditorCurveBinding)hierarchyNode.binding))
                {
                    hierarchyNode = (AnimationWindowHierarchyNode)hierarchyNode.parent;
                }

                if (hierarchyNode.curves == null)
                {
                    continue;
                }

                List <AnimationWindowCurve> curves = null;

                // Property or propertygroup
                if (hierarchyNode is AnimationWindowHierarchyPropertyGroupNode || hierarchyNode is AnimationWindowHierarchyPropertyNode)
                {
                    curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType, hierarchyNode.propertyName);
                }
                else
                {
                    curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType);
                }

                foreach (AnimationWindowCurve animationWindowCurve in curves)
                {
                    state.RemoveCurve(animationWindowCurve, undoLabel);
                }
            }

            m_TreeView.ReloadData();

            state.controlInterface.ResampleAnimation();
        }
        private GenericMenu GenerateMenu(List <AnimationWindowHierarchyNode> interactedNodes, bool enabled)
        {
            List <AnimationWindowCurve> curves = GetCurvesAffectedByNodes(interactedNodes, false);
            // Linked curves are like regular affected curves but always include transform siblings
            List <AnimationWindowCurve> linkedCurves = GetCurvesAffectedByNodes(interactedNodes, true);

            bool forceGroupRemove = curves.Count == 1 ? AnimationWindowUtility.ForceGrouping(curves[0].binding) : false;

            GenericMenu menu = new GenericMenu();

            // Remove curves
            GUIContent removePropertyContent = new GUIContent(curves.Count > 1 || forceGroupRemove ? "Remove Properties" : "Remove Property");

            if (!enabled)
            {
                menu.AddDisabledItem(removePropertyContent);
            }
            else
            {
                menu.AddItem(removePropertyContent, false, RemoveCurvesFromSelectedNodes);
            }

            // Change rotation interpolation
            bool showInterpolation = true;

            EditorCurveBinding[] curveBindings = new EditorCurveBinding[linkedCurves.Count];
            for (int i = 0; i < linkedCurves.Count; i++)
            {
                curveBindings[i] = linkedCurves[i].binding;
            }
            RotationCurveInterpolation.Mode rotationInterpolation = GetRotationInterpolationMode(curveBindings);
            if (rotationInterpolation == RotationCurveInterpolation.Mode.Undefined)
            {
                showInterpolation = false;
            }
            else
            {
                foreach (var node in interactedNodes)
                {
                    if (!(node is AnimationWindowHierarchyPropertyGroupNode))
                    {
                        showInterpolation = false;
                    }
                }
            }
            if (showInterpolation)
            {
                string legacyWarning = state.activeAnimationClip.legacy ? " (Not fully supported in Legacy)" : "";
                GenericMenu.MenuFunction2 nullMenuFunction2 = null;
                menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles" + legacyWarning), rotationInterpolation == RotationCurveInterpolation.Mode.RawEuler, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.RawEuler);
                menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles (Quaternion)"), rotationInterpolation == RotationCurveInterpolation.Mode.Baked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.Baked);
                menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Quaternion"), rotationInterpolation == RotationCurveInterpolation.Mode.NonBaked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.NonBaked);
            }

            // Menu items that are only applicaple when in animation mode:
            if (state.previewing)
            {
                menu.AddSeparator("");

                bool allHaveKeys  = true;
                bool noneHaveKeys = true;
                foreach (AnimationWindowCurve curve in curves)
                {
                    bool curveHasKey = curve.HasKeyframe(state.time);
                    if (!curveHasKey)
                    {
                        allHaveKeys = false;
                    }
                    else
                    {
                        noneHaveKeys = false;
                    }
                }

                string str;

                str = "Add Key";
                if (allHaveKeys || !enabled)
                {
                    menu.AddDisabledItem(new GUIContent(str));
                }
                else
                {
                    menu.AddItem(new GUIContent(str), false, AddKeysAtCurrentTime, curves);
                }

                str = "Delete Key";
                if (noneHaveKeys || !enabled)
                {
                    menu.AddDisabledItem(new GUIContent(str));
                }
                else
                {
                    menu.AddItem(new GUIContent(str), false, DeleteKeysAtCurrentTime, curves);
                }
            }

            return(menu);
        }
 static CurveTreeViewNode CreateLeafNode(EditorCurveBinding binding, TreeViewItem parent, string displayName)
 {
     return(new CurveTreeViewNode(binding.GetHashCode(), parent, displayName, new[] { binding }, AnimationWindowUtility.ForceGrouping(binding)));
 }