示例#1
0
            /************************************************************************************************************************/

            /// <inheritdoc/>
            public override void OnEnable(int index)
            {
                base.OnEnable(index);

                AnimancerUtilities.NewIfNull(ref _NewBindingPaths);

                if (Animation == null)
                {
                    _NewBindingPaths.Clear();
                }

                _OldBindingPathsDisplay = CreateReorderableStringList(OldBindingPaths, "Old Binding Paths");
                _NewBindingPathsDisplay = CreateReorderableStringList(_NewBindingPaths, "New Binding Paths", (area, i) =>
                {
                    var color = GUI.color;

                    var path = _NewBindingPaths[i];
                    if (path != OldBindingPaths[i])
                    {
                        GUI.color = new Color(0.15f, 0.7f, 0.15f, 1);
                    }

                    path      = EditorGUI.TextField(area, path);
                    GUI.color = color;
                    return(path);
                });
            }
示例#2
0
        /************************************************************************************************************************/

        /// <summary>Snaps the `seconds` value to the nearest multiple of the <see cref="AnimationClip.frameRate"/>.</summary>
        public void SnapToFrameRate(SerializableEventSequenceDrawer.Context context, ref float seconds)
        {
            if (AnimancerUtilities.TryGetFrameRate(context.TransitionContext.Transition, out var frameRate))
            {
                seconds = AnimancerUtilities.Round(seconds, 1f / frameRate);
            }
        }
        /************************************************************************************************************************/

        private void OnEnable()
        {
            titleContent = new GUIContent(Name);
            Instance     = this;

            AnimancerUtilities.NewIfNull(ref _ModifySprites);
            AnimancerUtilities.NewIfNull(ref _RenameSprites);
            AnimancerUtilities.NewIfNull(ref _GenerateSpriteAnimations);
            AnimancerUtilities.NewIfNull(ref _RemapSpriteAnimation);
            AnimancerUtilities.NewIfNull(ref _RemapAnimationBindings);

            _Panels = new Panel[]
            {
                _ModifySprites,
                _RenameSprites,
                _GenerateSpriteAnimations,
                _RemapSpriteAnimation,
                _RemapAnimationBindings,
            };
            _PanelNames = new string[_Panels.Length];

            for (int i = 0; i < _Panels.Length; i++)
            {
                var panel = _Panels[i];
                panel.OnEnable(i);
                _PanelNames[i] = panel.Name;
            }

            Undo.undoRedoPerformed += Repaint;

            OnSelectionChange();
        }
        /************************************************************************************************************************/
#if UNITY_EDITOR
        /************************************************************************************************************************/

        /// <summary>[Editor-Only]
        /// Sets the character's starting sprite in Edit Mode so you can see it while working in the scene.
        /// </summary>
        /// <remarks>
        /// Called by the Unity Editor in Edit Mode whenever an instance of this script is loaded or a value is changed
        /// in the Inspector.
        /// </remarks>
        private void OnValidate()
        {
            if (_Idles == null)
            {
                return;
            }

            AnimancerUtilities.EditModePlay(_Animancer, _Idles.GetClip(_Facing), true);
        }
示例#5
0
        /// <summary>
        /// Returns a <see cref="GUIContent"/> with the specified parameters. The same instance is returned by
        /// every subsequent call.
        /// </summary>
        public static GUIContent TempContent(string text = null, string tooltip = null, bool narrowText = true)
        {
            AnimancerUtilities.NewIfNull(ref _TempContent);

            if (narrowText)
            {
                text = GetNarrowText(text);
            }

            _TempContent.text    = text;
            _TempContent.tooltip = tooltip;
            return(_TempContent);
        }
示例#6
0
            /************************************************************************************************************************/

            /// <inheritdoc/>
            public override void OnEnable(int index)
            {
                base.OnEnable(index);

                AnimancerUtilities.NewIfNull(ref _NewSprites);

                if (Animation == null)
                {
                    _NewSprites.Clear();
                }

                _OldSpriteDisplay = CreateReorderableObjectList(OldSprites, "Old Sprites");
                _NewSpriteDisplay = CreateReorderableObjectList(_NewSprites, "New Sprites");
            }
示例#7
0
            /// <summary>Returns a disposable <see cref="DrawerContext"/> representing the specified parameters.</summary>
            /// <remarks>
            /// Instances are stored in a <see cref="LazyStack{T}"/> and the current one can be accessed via
            /// <see cref="Context"/>.
            /// </remarks>
            public static IDisposable Get(SerializedProperty transitionProperty)
            {
                var context = Stack.Increment();

                context.Property   = transitionProperty;
                context.Transition = transitionProperty.GetValue <ITransitionDetailed>();

                AnimancerUtilities.TryGetLength(context.Transition, out var length);
                context.MaximumDuration = length;

                EditorGUI.BeginChangeCheck();

                return(context);
            }
示例#8
0
        /************************************************************************************************************************/

        private void Awake()
        {
            AnimancerUtilities.Assert(Instance == null, $"The {nameof(GameManagerFSM)}.{nameof(Instance)} is already assigned.");
            Instance = this;

            StateMachine.ForceSetState(_Introduction);

            // Make sure both game managers aren't active at the same time.
            // This wouldn't normally be necessary because a real game won't have two managers for the same thing.
            if (FindObjectOfType <GameManagerEnum>() != null)// Won't find inactive objects.
            {
                Debug.LogError(
                    $"Both the {nameof(GameManagerEnum)} and {nameof(GameManagerFSM)} are active. Exit Play Mode and disable one of them.");
            }
        }
示例#9
0
        /************************************************************************************************************************/
        #region Initialisation
        /************************************************************************************************************************/

        public SimpleLean(AnimancerPlayable animancer, Vector3 axis, NativeArray <TransformStreamHandle> leanBones)
        {
            var animator = animancer.Component.Animator;

            _Job = new Job
            {
                root  = animator.BindStreamTransform(animator.transform),
                bones = leanBones,
                axis  = axis,
                angle = AnimancerUtilities.CreateNativeReference <float>(),
            };

            CreatePlayable(animancer);

            animancer.Disposables.Add(this);
        }
示例#10
0
            /// <summary>
            /// Returns a list of <see cref="Sprite"/>s which will be passed into
            /// <see cref="GenerateAnimationsBySpriteName(List{Sprite})"/> by <see cref="EditorApplication.delayCall"/>.
            /// </summary>
            private static List <Sprite> GetCachedSpritesToGenerateAnimations()
            {
                AnimancerUtilities.NewIfNull(ref _CachedSprites);

                // Delay the call in case multiple objects are selected.
                if (_CachedSprites.Count == 0)
                {
                    EditorApplication.delayCall += () =>
                    {
                        GenerateAnimationsBySpriteName(_CachedSprites);
                        _CachedSprites.Clear();
                    };
                }

                return(_CachedSprites);
            }
示例#11
0
        /************************************************************************************************************************/

        /// <summary>Initializes the `transition` based on the `state`.</summary>
        private static void GetDetailsFromState(AnimatorState state, ITransitionDetailed transition)
        {
            if (state == null ||
                transition == null)
            {
                return;
            }

            transition.Speed = state.speed;

            var isForwards     = state.speed >= 0;
            var defaultEndTime = AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(state.speed);
            var endTime        = defaultEndTime;

            var exitTransitions = state.transitions;

            for (int i = 0; i < exitTransitions.Length; i++)
            {
                var exitTransition = exitTransitions[i];
                if (exitTransition.hasExitTime)
                {
                    if (isForwards)
                    {
                        if (endTime > exitTransition.exitTime)
                        {
                            endTime = exitTransition.exitTime;
                        }
                    }
                    else
                    {
                        if (endTime < exitTransition.exitTime)
                        {
                            endTime = exitTransition.exitTime;
                        }
                    }
                }
            }

            if (endTime != defaultEndTime && AnimancerUtilities.TryGetWrappedObject(transition, out IHasEvents events))
            {
                if (events.SerializedEvents == null)
                {
                    events.SerializedEvents = new AnimancerEvent.Sequence.Serializable();
                }
                events.SerializedEvents.SetNormalizedEndTime(endTime);
            }
        }
示例#12
0
            /// <inheritdoc/>
            protected override void PrepareToApply()
            {
                if (!AnimancerUtilities.NewIfNull(ref _SpriteToName))
                {
                    _SpriteToName.Clear();
                }

                var sprites = Sprites;

                for (int i = 0; i < sprites.Count; i++)
                {
                    _SpriteToName.Add(sprites[i], Names[i]);
                }

                // Renaming selected Sprites will lose the selection without triggering OnSelectionChanged.
                EditorApplication.delayCall += OnSelectionChanged;
            }
                /************************************************************************************************************************/

                public static List <ExampleGroup> Gather(DefaultAsset rootDirectoryAsset, out string examplesDirectory)
                {
                    if (rootDirectoryAsset == null)
                    {
                        examplesDirectory = null;
                        return(null);
                    }

                    examplesDirectory = AssetDatabase.GetAssetPath(rootDirectoryAsset);
                    if (string.IsNullOrEmpty(examplesDirectory))
                    {
                        return(null);
                    }

                    var directories = Directory.GetDirectories(examplesDirectory);
                    var examples    = new List <ExampleGroup>();

                    List <SceneAsset> scenes = null;

                    for (int i = 0; i < directories.Length; i++)
                    {
                        var directory = directories[i];
                        var files     = Directory.GetFiles(directory, "*.unity", SearchOption.AllDirectories);

                        for (int j = 0; j < files.Length; j++)
                        {
                            var scene = AssetDatabase.LoadAssetAtPath <SceneAsset>(files[j]);
                            if (scene != null)
                            {
                                AnimancerUtilities.NewIfNull(ref scenes);
                                scenes.Add(scene);
                            }
                        }

                        if (scenes != null)
                        {
                            examples.Add(new ExampleGroup(examplesDirectory, directory, scenes));
                            scenes = null;
                        }
                    }

                    examplesDirectory = Path.GetDirectoryName(examplesDirectory);

                    return(examples);
                }
示例#14
0
        /************************************************************************************************************************/

        /// <summary>Creates an <see cref="AnimancerTransition"/> from the `blendTree`.</summary>
        private static Object GenerateTransition(AnimatorState state, BlendTree blendTree)
        {
            var asset = CreateTransition(blendTree);

            if (asset == null)
            {
                return(null);
            }

            if (state != null)
            {
                asset.name = state.name;
            }

            AnimancerUtilities.TryGetWrappedObject(asset, out ITransitionDetailed detailed);
            GetDetailsFromState(state, detailed);
            SaveTransition(blendTree, asset);
            return(asset);
        }
        /************************************************************************************************************************/

        private static void WrapEventTime(Context context, ref float normalizedTime)
        {
            var transition = context.TransitionContext?.Transition;

            if (transition != null && transition.IsLooping)
            {
                if (normalizedTime == 0)
                {
                    return;
                }
                else if (normalizedTime % 1 == 0)
                {
                    normalizedTime = AnimancerEvent.AlmostOne;
                }
                else
                {
                    normalizedTime = AnimancerUtilities.Wrap01(normalizedTime);
                }
            }
        }
示例#16
0
        /// <summary>
        /// Fills the `clips` with any <see cref="AnimationClip"/>s referenced by components in the same hierarchy as
        /// the `gameObject`. See <see cref="ICharacterRoot"/> for details.
        /// </summary>
        public static void GatherFromGameObject(GameObject gameObject, ref AnimationClip[] clips, bool sort)
        {
            var gatherer = GatherFromGameObject(gameObject);

            if (gatherer == null)
            {
                return;
            }

            using (ObjectPool.Disposable.AcquireSet <AnimationClip>(out var clipSet))
            {
                gatherer.GatherAnimationClips(clipSet);
                AnimancerUtilities.SetLength(ref clips, clipSet.Count);
                clipSet.CopyTo(clips);
            }

            if (sort)
            {
                Array.Sort(clips, (a, b) => a.name.CompareTo(b.name));
            }
        }
示例#17
0
        /************************************************************************************************************************/

        /// <summary>[Editor-Only] Draws the GUI for this attribute.</summary>
        public void OnGUI(Rect area, GUIContent label, ref float value)
        {
            var context = TransitionDrawer.Context;

            if (context == null)
            {
                value = DoSpecialFloatField(area, label, value, DisplayConverters[UnitIndex]);
                goto Return;
            }

            var length = context.MaximumDuration;

            if (length <= 0)
            {
                length = float.NaN;
            }

            AnimancerUtilities.TryGetFrameRate(context.Transition, out var frameRate);

            var multipliers = CalculateMultipliers(length, frameRate);

            if (multipliers == null)
            {
                EditorGUI.LabelField(area, label.text, $"Invalid {nameof(Validate)}.{nameof(Validate.Value)}");
                goto Return;
            }

            DoPreviewTimeButton(ref area, ref value, context.Transition, multipliers);

            IsOptional   = !float.IsNaN(nextDefaultValue);
            DefaultValue = nextDefaultValue;
            DoFieldGUI(area, label, ref value);

Return:
            nextDefaultValue = float.NaN;
        }
示例#18
0
        /************************************************************************************************************************/

        private static Delegate[] GetInvocationListIfMulticast(MulticastDelegate del)
        => AnimancerUtilities.TryGetInvocationListNonAlloc(del, out var delegates) ? delegates : del.GetInvocationList();
示例#19
0
        /************************************************************************************************************************/

        /// <summary>[Editor-Only] Draws this attribute's fields.</summary>
        protected void DoFieldGUI(Rect area, GUIContent label, ref float value)
        {
            var isMultiLine = area.height > LineHeight;

            area.height = LineHeight;

            DoOptionalBeforeGUI(IsOptional, area, out var toggleArea, out var guiWasEnabled, out var previousLabelWidth);

            Rect allFieldArea;

            if (isMultiLine)
            {
                EditorGUI.LabelField(area, label);
                label = null;
                AnimancerGUI.NextVerticalArea(ref area);

                EditorGUI.indentLevel++;
                allFieldArea = EditorGUI.IndentedRect(area);
                EditorGUI.indentLevel--;
            }
            else
            {
                var labelXMax = area.x + EditorGUIUtility.labelWidth;
                allFieldArea = new Rect(labelXMax, area.y, area.xMax - labelXMax, area.height);
            }

            // Count the number of active fields.
            var count = 0;
            var last  = 0;

            for (int i = 0; i < Multipliers.Length; i++)
            {
                if (!float.IsNaN(Multipliers[i]))
                {
                    count++;
                    last = i;
                }
            }

            var width     = (allFieldArea.width - StandardSpacing * (count - 1)) / count;
            var fieldArea = new Rect(allFieldArea.x, allFieldArea.y, width, allFieldArea.height);

            var displayValue = GetDisplayValue(value, DefaultValue);

            // Draw the active fields.
            for (int i = 0; i < Multipliers.Length; i++)
            {
                var multiplier = Multipliers[i];
                if (float.IsNaN(multiplier))
                {
                    continue;
                }

                if (label != null)
                {
                    fieldArea.xMin = area.xMin;
                }
                else if (i < last)
                {
                    fieldArea.width = width;
                    fieldArea.xMax  = AnimancerUtilities.Round(fieldArea.xMax);
                }
                else
                {
                    fieldArea.xMax = area.xMax;
                }

                EditorGUI.BeginChangeCheck();

                var fieldValue = displayValue * multiplier;
                fieldValue = DoSpecialFloatField(fieldArea, label, fieldValue, DisplayConverters[i]);
                label      = null;

                if (EditorGUI.EndChangeCheck())
                {
                    value = fieldValue / multiplier;
                }

                fieldArea.x += fieldArea.width + StandardSpacing;
            }

            DoOptionalAfterGUI(IsOptional, toggleArea, ref value, DefaultValue, guiWasEnabled, previousLabelWidth);

            Validate.ValueRule(ref value, Rule);
        }
        /************************************************************************************************************************/

        /// <summary>
        /// 如果您将此类型派生的第二个脚本添加到相同的对象,它将更改现有组件的类型,从而允许您轻松地在 <see cref="IdleAndWalk"/>
        /// 和 <see cref="IdleAndWalkAndRun"/>之间进行交换.
        /// </summary>
        protected virtual void Reset()
        {
            AnimancerUtilities.IfMultiComponentThenChangeType(this); //如果有多个组件,则改变类型.
        }
示例#21
0
 /// <summary>[Internal] Sets the prefix for <see cref="GetSerializedProperty"/>.</summary>
 internal static void SetBasePropertyPath <T>(ref T group, string propertyPath) where T : Group, new()
 {
     AnimancerUtilities.NewIfNull(ref group);
     group._BasePropertyPath = propertyPath + ".";
 }
示例#22
0
            /************************************************************************************************************************/

            /// <inheritdoc/>
            public override void OnEnable(int index)
            {
                base.OnEnable(index);
                AnimancerUtilities.NewIfNull(ref _Textures);
                _TexturesDisplay = CreateReorderableObjectList(_Textures, "Textures", true);
            }
示例#23
0
        /************************************************************************************************************************/

        /// <summary>Draws the ruler GUI and handles input events for the specified `context`.</summary>
        private void DoGUI(SerializableEventSequenceDrawer.Context context, out float addEventNormalizedTime)
        {
            if (context.Property.hasMultipleDifferentValues)
            {
                GUI.Label(_Area, "Multi-editing is not supported");
                addEventNormalizedTime = float.NaN;
                return;
            }

            var transition = context.TransitionContext.Transition;

            _Speed = transition.Speed;
            if (float.IsNaN(_Speed))
            {
                _Speed = 1;
            }

            _Duration = context.TransitionContext.MaximumDuration;
            if (_Duration <= 0)
            {
                _Duration = 1;
            }

            GatherEventTimes(context);

            _StartTime = GetStartTime(transition.NormalizedStartTime, _Speed, _Duration);

            _FadeInEnd = _StartTime + transition.FadeDuration * _Speed;

            _FadeOutEnd = GetFadeOutEnd(_Speed, _EndTime, _Duration);

            _MinTime = Mathf.Min(0, _StartTime);
            _MinTime = Mathf.Min(_MinTime, _FadeOutEnd);
            _MinTime = Mathf.Min(_MinTime, EventTimes[0]);

            _MaxTime = Mathf.Max(_StartTime, _FadeOutEnd);
            if (EventTimes.Count >= 2)
            {
                _MaxTime = Mathf.Max(_MaxTime, EventTimes[EventTimes.Count - 2]);
            }

            if (_MaxTime < _Duration)
            {
                _MaxTime = _Duration;
            }

            _SecondsToPixels = _Area.width / (_MaxTime - _MinTime);

            DoFadeHighlightGUI();

            if (AnimancerUtilities.TryGetWrappedObject(transition, out ITransitionGUI gui))
            {
                gui.OnTimelineBackgroundGUI();
            }

            DoEventsGUI(context, out addEventNormalizedTime);
            DoRulerGUI();

            if (_Speed > 0)
            {
                if (_StartTime >= _EndTime)
                {
                    GUI.Label(_Area, "Start Time is not before End Time");
                }
            }
            else if (_Speed < 0)
            {
                if (_StartTime <= _EndTime)
                {
                    GUI.Label(_Area, "Start Time is not after End Time");
                }
            }

            if (gui != null)
            {
                gui.OnTimelineForegroundGUI();
            }
        }
示例#24
0
        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #region Conversions
        /************************************************************************************************************************/

        /// <summary>Converts a number of seconds to a horizontal pixel position along the ruler.</summary>
        /// <remarks>The value is rounded to the nearest integer.</remarks>
        public float SecondsToPixels(float seconds) => AnimancerUtilities.Round((seconds - _MinTime) * _SecondsToPixels);
示例#25
0
        /************************************************************************************************************************/

        /// <summary>
        /// If you add a second script derived from this type to the same object, it will instead change the type of
        /// the existing component, allowing you to easily swap between any components that inherit from
        /// <see cref="GolfHitController"/> without losing the values of their serialized fields.
        /// </summary>
        protected void Reset()
        {
            AnimancerUtilities.IfMultiComponentThenChangeType(this);
        }
        /// <summary>Draws the time field for the event at the specified `index`.</summary>
        public static void DoTimeGUI(ref Rect area, Context context, int index, bool autoSort,
                                     string timeLabel, float defaultTime, bool isEndEvent)
        {
            EditorGUI.BeginChangeCheck();

            area.height = EventTimeAttribute.GetPropertyHeight(null, null);
            var timeArea = area;

            AnimancerGUI.NextVerticalArea(ref area);

            float normalizedTime;

            using (ObjectPool.Disposable.AcquireContent(out var label, timeLabel,
                                                        isEndEvent ? Strings.Tooltips.EndTime : Strings.Tooltips.CallbackTime))
            {
                var length = context.TransitionContext?.MaximumDuration ?? float.NaN;

                if (index < context.Times.Count)
                {
                    var timeProperty = context.Times.GetElement(index);
                    if (timeProperty == null)// Multi-selection screwed up the property retrieval.
                    {
                        EditorGUI.BeginChangeCheck();

                        label = EditorGUI.BeginProperty(timeArea, label, context.Times.Property);
                        if (isEndEvent)
                        {
                            AnimationTimeAttribute.nextDefaultValue = defaultTime;
                        }
                        normalizedTime = float.NaN;
                        EventTimeAttribute.OnGUI(timeArea, label, ref normalizedTime);

                        EditorGUI.EndProperty();

                        if (EditorGUI.EndChangeCheck())
                        {
                            context.Times.Count     = context.Times.Count;
                            timeProperty            = context.Times.GetElement(index);
                            timeProperty.floatValue = normalizedTime;
                            SyncEventTimeChange(context, index, normalizedTime);
                        }
                    }
                    else// Event time property was correctly retrieved.
                    {
                        var wasEditingTextField = EditorGUIUtility.editingTextField;
                        if (!wasEditingTextField)
                        {
                            _PreviousTime = float.NaN;
                        }

                        EditorGUI.BeginChangeCheck();

                        label = EditorGUI.BeginProperty(timeArea, label, timeProperty);

                        if (isEndEvent)
                        {
                            AnimationTimeAttribute.nextDefaultValue = defaultTime;
                        }
                        normalizedTime = timeProperty.floatValue;
                        EventTimeAttribute.OnGUI(timeArea, label, ref normalizedTime);

                        EditorGUI.EndProperty();

                        if (AnimancerGUI.TryUseClickEvent(timeArea, 2))
                        {
                            normalizedTime = float.NaN;
                        }

                        var isEditingTextField = EditorGUIUtility.editingTextField;
                        if (EditorGUI.EndChangeCheck() || (wasEditingTextField && !isEditingTextField))
                        {
                            if (float.IsNaN(normalizedTime))
                            {
                                RemoveEvent(context, index);
                                AnimancerGUI.Deselect();
                            }
                            else if (isEndEvent)
                            {
                                timeProperty.floatValue = normalizedTime;
                                SyncEventTimeChange(context, index, normalizedTime);
                            }
                            else if (!autoSort && isEditingTextField)
                            {
                                _PreviousTime = normalizedTime;
                            }
                            else
                            {
                                if (!float.IsNaN(_PreviousTime))
                                {
                                    if (Event.current.keyCode != KeyCode.Escape)
                                    {
                                        normalizedTime = _PreviousTime;
                                        AnimancerGUI.Deselect();
                                    }

                                    _PreviousTime = float.NaN;
                                }

                                WrapEventTime(context, ref normalizedTime);

                                timeProperty.floatValue = normalizedTime;
                                SyncEventTimeChange(context, index, normalizedTime);

                                if (autoSort)
                                {
                                    SortEvents(context);
                                }
                            }

                            GUI.changed = true;
                        }
                    }
                }
                else// Dummy End Event (when there are no event times).
                {
                    AnimancerUtilities.Assert(index == 0, "Dummy end event index != 0");
                    EditorGUI.BeginChangeCheck();

                    EditorGUI.BeginProperty(timeArea, GUIContent.none, context.Times.Property);

                    AnimationTimeAttribute.nextDefaultValue = defaultTime;
                    normalizedTime = float.NaN;
                    EventTimeAttribute.OnGUI(timeArea, label, ref normalizedTime);

                    EditorGUI.EndProperty();

                    if (EditorGUI.EndChangeCheck() && !float.IsNaN(normalizedTime))
                    {
                        context.Times.Count = 1;
                        var timeProperty = context.Times.GetElement(0);
                        timeProperty.floatValue = normalizedTime;
                        SyncEventTimeChange(context, 0, normalizedTime);
                    }
                }
            }

            if (EditorGUI.EndChangeCheck())
            {
                var eventType = Event.current.type;
                if (eventType == EventType.Layout)
                {
                    return;
                }

                if (eventType == EventType.Used)
                {
                    normalizedTime = UnitsAttribute.GetDisplayValue(normalizedTime, defaultTime);
                    TransitionPreviewWindow.PreviewNormalizedTime = normalizedTime;
                }

                GUIUtility.ExitGUI();
            }
        }