public CHR0EntryNode CreateEntry(string name)
        {
            CHR0EntryNode n = new CHR0EntryNode();

            n._name = this.FindName(name);
            AddChild(n);
            n.SetSize(_numFrames, Loop);
            return(n);
        }
        public void Reverse(bool appendReverse)
        {
            CHR0Node tempReversedCHR0 = new CHR0Node();

            tempReversedCHR0.Name       = this.Name + "_Reversed";
            tempReversedCHR0.Loop       = this.Loop;
            tempReversedCHR0.FrameCount = FrameCount;

            // Fixes non-looped animations being off by a frame
            int loopfix = 0;

            if (!Loop)
            {
                loopfix = 1;
            }

            KeyframeEntry kfe;

            foreach (CHR0EntryNode tempEntry in Children)
            {
                CHR0EntryNode newIntEntry = new CHR0EntryNode()
                {
                    Name = tempEntry.Name
                };
                newIntEntry.SetSize(tempEntry.FrameCount, Loop);
                for (int x = 0; x < tempEntry.FrameCount; x++)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        if ((kfe = tempEntry.GetKeyframe(i, x)) != null)
                        {
                            newIntEntry.Keyframes.SetFrameValue(i, FrameCount - (x + loopfix), kfe._value)._tangent = kfe._tangent;
                        }
                    }
                }
                tempReversedCHR0.AddChild(newIntEntry);
            }
            if (appendReverse)
            {
                Append(tempReversedCHR0, 1);
            }
            else
            {
                // Remove old keyframes
                while (HasChildren)
                {
                    RemoveChild(Children[0]);
                }
                // Add reversed keyframes
                foreach (CHR0EntryNode entryToAdd in tempReversedCHR0.Children)
                {
                    entryToAdd.SignalPropertyChange();
                    AddChild(entryToAdd);
                }
            }
        }
        /// <summary>
        /// Adds an animation to the end of this one
        /// </summary>
        public void Append(CHR0Node external, int timesToAppend)
        {
            KeyframeEntry kfe;
            int           extCount = external.FrameCount;

            for (int appendCount = 0; appendCount < timesToAppend; ++appendCount)
            {
                int origIntCount = FrameCount;
                FrameCount += extCount;

                foreach (CHR0EntryNode extEntry in external.Children)
                {
                    CHR0EntryNode intEntry = null;
                    if ((intEntry = (CHR0EntryNode)FindChild(extEntry.Name, false)) == null)
                    {
                        CHR0EntryNode newIntEntry = new CHR0EntryNode()
                        {
                            Name = extEntry.Name
                        };
                        newIntEntry.SetSize(extEntry.FrameCount + origIntCount, Loop);
                        for (int x = 0; x < extEntry.FrameCount; x++)
                        {
                            for (int i = 0; i < 9; i++)
                            {
                                if ((kfe = extEntry.GetKeyframe(i, x)) != null)
                                {
                                    newIntEntry.Keyframes.SetFrameValue(i, x + origIntCount, kfe._value)._tangent = kfe._tangent;
                                }
                            }
                        }
                        AddChild(newIntEntry);
                    }
                    else
                    {
                        for (int x = 0; x < extEntry.FrameCount; x++)
                        {
                            for (int i = 0; i < 9; i++)
                            {
                                if ((kfe = extEntry.GetKeyframe(i, x)) != null)
                                {
                                    intEntry.Keyframes.SetFrameValue(i, x + origIntCount, kfe._value)._tangent = kfe._tangent;
                                }
                            }
                        }
                    }
                }
            }
        }
        public CHR0EntryNode CreateEntryFromBone(MDL0BoneNode b, int framesToGenerate, bool generateOrigin)
        {
            CHR0EntryNode n = new CHR0EntryNode();

            if (!generateOrigin)
            {
                if (b.isOriginRot() && b.isOriginScale() && b.isOriginTrans())
                {
                    //Console.WriteLine("      " + b + " has all values equal to origin. Not generating keyframes.");
                    return(null);
                }
            }
            n._name = this.FindName(b.Name);
            AddChild(n);
            n.SetSize(_numFrames, Loop);
            //Console.WriteLine(_numFrames);
            for (int i = 0; i < framesToGenerate; ++i)
            {
                n.generateKeyframeFromBone(b, i, true, generateOrigin);
            }
            SignalPropertyChange();
            return(n);
        }
        public void MergeWith(CHR0Node external)
        {
            if (external.FrameCount != FrameCount && MessageBox.Show(null, "Frame counts are not equal; the shorter animation will end early. Do you still wish to continue?", "", MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }

            if (external.FrameCount > FrameCount)
            {
                FrameCount = external.FrameCount;
            }

            foreach (CHR0EntryNode _extTarget in external.Children)
            {
                CHR0EntryNode node = null;
                KeyframeEntry kfe  = null;

                CHR0EntryNode entry = new CHR0EntryNode()
                {
                    Name = _extTarget.Name
                };
                entry.SetSize(_extTarget.FrameCount, Loop);

                //Apply all external keyframes to current entry.
                for (int x = 0; x < _extTarget.FrameCount; x++)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        if ((kfe = _extTarget.GetKeyframe(i, x)) != null)
                        {
                            entry.Keyframes.SetFrameValue(i, x, kfe._value)._tangent = kfe._tangent;
                        }
                    }
                }

                if ((node = FindChild(_extTarget.Name, false) as CHR0EntryNode) == null)
                {
                    AddChild(entry, true);
                }
                else
                {
                    DialogResult result = MessageBox.Show(null, "A bone entry with the name " + _extTarget.Name + " already exists.\nDo you want to rename this entry?\nOtherwise, you will have the option to merge the keyframes.", "Rename Entry?", MessageBoxButtons.YesNoCancel);
                    if (result == DialogResult.Yes)
                    {
Top:
                        RenameDialog d = new RenameDialog();
                        if (d.ShowDialog(null, entry) == DialogResult.OK)
                        {
                            if (entry.Name != _extTarget.Name)
                            {
                                AddChild(entry, true);
                            }
                            else
                            {
                                MessageBox.Show("The name wasn't changed!");
                                goto Top;
                            }
                        }
                    }
                    else if (result == DialogResult.No)
                    {
                        result = MessageBox.Show(null, "Do you want to merge the keyframes of the entries?", "Merge Keyframes?", MessageBoxButtons.YesNoCancel);
                        if (result == DialogResult.Yes)
                        {
                            KeyframeEntry kfe2 = null;

                            if (_extTarget.FrameCount > node.FrameCount)
                            {
                                node.SetSize(_extTarget.FrameCount, Loop);
                            }

                            //Merge all external keyframes with the current entry.
                            for (int x = 0; x < _extTarget.FrameCount; x++)
                            {
                                for (int i = 0; i < 9; i++)
                                {
                                    if ((kfe = _extTarget.GetKeyframe(i, x)) != null)
                                    {
                                        if ((kfe2 = node.GetKeyframe(i, x)) == null)
                                        {
                                            node.SetKeyframe(i, x, kfe._value);
                                        }
                                        else
                                        {
                                            result = MessageBox.Show(null, "A keyframe at frame " + x + " already exists.\nOld value: " + kfe2._value + "\nNew value:" + kfe._value + "\nReplace the old value with the new one?", "Replace Keyframe?", MessageBoxButtons.YesNoCancel);
                                            if (result == DialogResult.Yes)
                                            {
                                                node.SetKeyframe(i, x, kfe._value);
                                            }
                                            else if (result == DialogResult.Cancel)
                                            {
                                                Restore();
                                                return;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else if (result == DialogResult.Cancel)
                        {
                            Restore();
                            return;
                        }
                    }
                    else if (result == DialogResult.Cancel)
                    {
                        Restore();
                        return;
                    }
                }
            }
        }