예제 #1
0
        /************************************************************************************************************************/

        private void DoNameGUI()
        {
            GUILayout.BeginHorizontal();
            var enabled = GUI.enabled;

            if (_Name.hasMultipleDifferentValues)
            {
                GUI.enabled = false;
            }

            EditorGUILayout.PropertyField(_Name, AnimancerGUI.TempContent("Name", NameTooltip), true);

            GUI.enabled = true;

            var changed = EditorGUI.EndChangeCheck();// Exclude the Rename button from the main change check.

            if (GUILayout.Button("Rename Tool", EditorStyles.miniButton, AnimancerGUI.DontExpandWidth))
            {
                AnimancerToolsWindow.Open(typeof(AnimancerToolsWindow.RenameSprites));
            }

            EditorGUI.BeginChangeCheck();
            if (changed)
            {
                GUI.changed = true;
            }

            GUI.enabled = enabled;
            GUILayout.EndHorizontal();
        }
예제 #2
0
        /************************************************************************************************************************/

        /// <summary>
        /// Draws the name and other details of the <see cref="Target"/> in the GUI.
        /// </summary>
        protected virtual void DoHeaderGUI()
        {
            var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before);

            DoLabelGUI(area);
            DoFoldoutGUI(area);
        }
예제 #3
0
        /************************************************************************************************************************/

        /// <summary>
        /// Draws controls for <see cref="AnimancerLayer.IsAdditive"/> and <see cref="AnimancerLayer._Mask"/>.
        /// </summary>
        private void DoLayerDetailsGUI()
        {
            var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before);

            area = EditorGUI.IndentedRect(area);

            var labelWidth  = EditorGUIUtility.labelWidth;
            var indentLevel = EditorGUI.indentLevel;

            EditorGUI.indentLevel = 0;

            var additiveLabel = AnimancerGUI.GetNarrowText("Is Additive");

            var additiveWidth = GUI.skin.toggle.CalculateWidth(additiveLabel);
            var maskRect      = AnimancerGUI.StealFromRight(ref area, area.width - additiveWidth);

            // Additive.
            EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(additiveLabel);
            Target.IsAdditive           = EditorGUI.Toggle(area, additiveLabel, Target.IsAdditive);

            // Mask.
            using (ObjectPool.Disposable.AcquireContent(out var label, "Mask"))
            {
                EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(label.text);
                EditorGUI.BeginChangeCheck();
                Target._Mask = (AvatarMask)EditorGUI.ObjectField(maskRect, label, Target._Mask, typeof(AvatarMask), false);
                if (EditorGUI.EndChangeCheck())
                {
                    Target.SetMask(Target._Mask);
                }
            }

            EditorGUI.indentLevel       = indentLevel;
            EditorGUIUtility.labelWidth = labelWidth;
        }
예제 #4
0
        private void DoLoopCounterGUI(ref Rect area, float length)
        {
            if (_LoopCounterCache == null)
            {
                _LoopCounterCache = new ConversionCache <int, string>((x) => "x" + x);
            }

            string label;
            var    normalizedTime = Target.Time / length;

            if (float.IsNaN(normalizedTime))
            {
                label = "NaN";
            }
            else
            {
                var loops = (int)Math.Abs(Target.Time / length);
                label = _LoopCounterCache.Convert(loops);
            }

            var width = AnimancerGUI.CalculateLabelWidth(label);

            var labelArea = AnimancerGUI.StealFromRight(ref area, width);

            GUI.Label(labelArea, label);
        }
예제 #5
0
        /************************************************************************************************************************/
        #region Context Menu
        /************************************************************************************************************************/

        /// <summary>
        /// Checks if the current event is a context menu click within the `clickArea` and opens a context menu with various
        /// functions for the `playable`.
        /// </summary>
        private void CheckContextMenu(Rect clickArea, AnimancerPlayable playable)
        {
            if (!AnimancerGUI.TryUseClickEvent(clickArea, 1))
            {
                return;
            }

            var menu = new GenericMenu();

            menu.AddDisabledItem(new GUIContent(playable.Graph.GetEditorName() ?? "Unnamed Graph"), false);
            menu.AddDisabledItem(new GUIContent("Command Count: " + playable.CommandCount), false);
            menu.AddDisabledItem(new GUIContent("Frame ID: " + playable.FrameID), false);
            AddDisposablesFunctions(menu, playable.Disposables);

            AddUpdateModeFunctions(menu, playable);
            AnimancerEditorUtilities.AddContextMenuIK(menu, playable);
            AddRootFunctions(menu, playable);

            menu.AddSeparator("");

            AddDisplayOptions(menu);

            menu.AddItem(new GUIContent("Log Details Of Everything"), false,
                         () => Debug.Log(playable.GetDescription(), playable.Component as Object));
            AddPlayableGraphVisualizerFunction(menu, "", playable._Graph);

            AnimancerEditorUtilities.AddDocumentationLink(menu, "Inspector Documentation", Strings.DocsURLs.Inspector);

            menu.ShowAsContext();
        }
예제 #6
0
        /************************************************************************************************************************/

        private void DoPreviewButtonGUI(ref Rect area, SerializedProperty property, bool wasPreviewing)
        {
            if (property.serializedObject.targetObjects.Length != 1 ||
                !TransitionPreviewWindow.CanBePreviewed(property))
            {
                return;
            }

            var buttonArea = AnimancerGUI.StealFromRight(ref area,
                                                         area.height + AnimancerGUI.StandardSpacing * 2, AnimancerGUI.StandardSpacing);

            var content = AnimancerGUI.TempContent("", "Preview this transition");

            content.image = TransitionPreviewWindow.Icon;

            var style = ObjectPool.GetCachedResult(() => new GUIStyle(AnimancerGUI.MiniButton)
            {
#if UNITY_2019_3_OR_NEWER
                padding = new RectOffset(0, 0, 0, 1),
#else
                padding = new RectOffset(),
#endif
                fixedWidth  = 0,
                fixedHeight = 0,
            });

            var isPrevewing = GUI.Toggle(buttonArea, wasPreviewing, content, style);

            if (wasPreviewing != isPrevewing)
            {
                TransitionPreviewWindow.Open(property, isPrevewing);
            }

            content.image = null;
        }
예제 #7
0
            /************************************************************************************************************************/

            private static bool DoDropdownObjectField <T>(GUIContent label, bool showDropdown, ref T obj,
                                                          AnimancerGUI.SpacingMode spacingMode = AnimancerGUI.SpacingMode.None) where T : Object
            {
                var area = AnimancerGUI.LayoutSingleLineRect(spacingMode);

                var labelWidth = EditorGUIUtility.labelWidth;

#if UNITY_2019_3_OR_NEWER
                labelWidth += 2;
                area.xMin  -= 1;
#else
                area.xMin += 1;
                area.xMax -= 1;
#endif

                var spacing   = AnimancerGUI.StandardSpacing;
                var labelArea = AnimancerGUI.StealFromLeft(ref area, labelWidth - spacing, spacing);

                obj = (T)EditorGUI.ObjectField(area, obj, typeof(T), true);

                if (showDropdown)
                {
                    return(EditorGUI.DropdownButton(labelArea, label, FocusType.Passive));
                }
                else
                {
                    GUI.Label(labelArea, label);
                    return(false);
                }
            }
예제 #8
0
            /************************************************************************************************************************/

            /// <summary>Asks if the user wants to delete the `directory` and does so if they confirm.</summary>
            private void CheckDeleteDirectory(string directory)
            {
                if (!AnimancerGUI.TryUseClickEventInLastRect())
                {
                    return;
                }

                var name = _Target.ProductName;

                if (!AssetDatabase.IsValidFolder(directory))
                {
                    Debug.Log($"{directory} doesn't exist." +
                              $" You must have moved {name} somewhere else so you will need to delete it manually.", this);
                    return;
                }

                if (!EditorUtility.DisplayDialog($"Delete {name}? ",
                                                 $"Would you like to delete {directory}?\n\nYou will then need to reimport {name} manually.",
                                                 "Delete", "Cancel"))
                {
                    return;
                }

                AssetDatabase.DeleteAsset(directory);
            }
예제 #9
0
            /************************************************************************************************************************/

            protected Rect DoLinkButton(string text, string url, GUIStyle style, int fontSize = 22)
            {
                using (ObjectPool.Disposable.AcquireContent(out var label, text, url, false))
                {
                    style.fontSize = fontSize;

                    var size = style.CalcSize(label);
                    var area = GUILayoutUtility.GetRect(0, size.y);

                    var linkArea = AnimancerGUI.StealFromLeft(ref area, size.x);

                    if (url == null)
                    {
                        GUI.Label(linkArea, label, style);
                    }
                    else
                    {
                        if (GUI.Button(linkArea, label, style))
                        {
                            Application.OpenURL(url);
                        }

                        EditorGUIUtility.AddCursorRect(linkArea, MouseCursor.Link);

                        DrawLine(
                            new Vector2(linkArea.xMin, linkArea.yMax),
                            new Vector2(linkArea.xMax, linkArea.yMax),
                            style.normal.textColor);
                    }

                    return(area);
                }
            }
예제 #10
0
        /************************************************************************************************************************/

        /// <summary>
        /// 从 <see cref="Animator.keepAnimatorControllerStateOnDisable"/> 字段中反向绘制一个切换.
        /// </summary>
        private void DoStopOnDisableGUI()
        {
#if UNITY_2018_1_OR_NEWER
            var area = AnimancerGUI.LayoutSingleLineRect();

            var label = AnimancerGUI.TempContent("Stop On Disable",
                                                 " 如果为真,禁用此对象将停止并回滚所有动画." +
                                                 " 否则,它们将被暂停,并在重新启用时从当前状态继续.");

            if (_KeepStateOnDisable != null)
            {
                _KeepStateOnDisable.serializedObject.Update();

                label = UnityEditor.EditorGUI.BeginProperty(area, label, _KeepStateOnDisable);

                _KeepStateOnDisable.boolValue = !UnityEditor.EditorGUI.Toggle(area, label, !_KeepStateOnDisable.boolValue);

                UnityEditor.EditorGUI.EndProperty();

                _KeepStateOnDisable.serializedObject.ApplyModifiedProperties();
            }
            else
            {
                var enabled = GUI.enabled;
                GUI.enabled = false;
                UnityEditor.EditorGUI.Toggle(area, label, false);
                GUI.enabled = enabled;
            }
#endif
        }
예제 #11
0
        /************************************************************************************************************************/

        private void DoChildPropertiesGUI(Rect area, float headerHeight, SerializedProperty property)
        {
            if (!property.isExpanded && _Mode != Mode.AlwaysExpanded)
            {
                return;
            }

            area.y += headerHeight + AnimancerGUI.StandardSpacing;

            EditorGUI.indentLevel++;

            var rootProperty = property;

            property = property.Copy();

            SerializedProperty eventsProperty = null;

            var depth = property.depth;

            property.NextVisible(true);
            while (property.depth > depth)
            {
                // Grab the Events property and draw it last.
                if (eventsProperty == null && property.propertyPath.EndsWith("._Events"))
                {
                    eventsProperty = property.Copy();
                }
                else if (MainPropertyPathSuffix == null || !property.propertyPath.EndsWith(MainPropertyPathSuffix))
                {
                    if (eventsProperty != null)
                    {
                        var accessor = property.GetAccessor();
                        if (accessor.Field.IsDefined(typeof(DrawAfterEventsAttribute), false))
                        {
                            var eventsLabel = AnimancerGUI.TempContent(eventsProperty);
                            DoPropertyGUI(ref area, rootProperty, eventsProperty, eventsLabel);
                            AnimancerGUI.NextVerticalArea(ref area);
                            eventsProperty = null;
                        }
                    }

                    var label = AnimancerGUI.TempContent(property);
                    DoPropertyGUI(ref area, rootProperty, property, label);
                    AnimancerGUI.NextVerticalArea(ref area);
                }

                if (!property.NextVisible(false))
                {
                    break;
                }
            }

            if (eventsProperty != null)
            {
                var label = AnimancerGUI.TempContent(eventsProperty);
                DoPropertyGUI(ref area, rootProperty, eventsProperty, label);
            }

            EditorGUI.indentLevel--;
        }
예제 #12
0
            /************************************************************************************************************************/

            /// <inheritdoc/>
            public override void DoBodyGUI()
            {
                var sprites = Sprites;

                if (_NamesAreDirty)
                {
                    _NamesAreDirty = false;
                    GatherNameToSprites(sprites, NameToSprites);
                    Names.AddRange(NameToSprites.Keys);
                }

                GUI.enabled = false;
                _Display.DoLayoutList();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();

                    GUI.enabled = sprites.Count > 0;

                    if (GUILayout.Button("Generate"))
                    {
                        AnimancerGUI.Deselect();
                        GenerateAnimationsBySpriteName(sprites);
                    }
                }
                GUILayout.EndHorizontal();

                GUI.enabled = true;
                EditorGUILayout.HelpBox("This function is also available via:" +
                                        "\n - The 'Assets/Create/Animancer' menu." +
                                        "\n - The Cog icon in the top right of the Inspector for Sprite and Texture assets",
                                        MessageType.Info);
            }
예제 #13
0
        /************************************************************************************************************************/

        private void Apply()
        {
            AnimancerGUI.Deselect();
            _HasBeenModified = false;
            var targets = this.targets;

            var hasError = false;

            for (int i = 0; i < _Targets.Length; i++)
            {
                var target      = _Targets[i];
                var spriteSheet = target.Importer.spritesheet;
                Apply(target.Sprite, spriteSheet, ref hasError);

                if (!hasError)
                {
                    target.Importer.spritesheet = spriteSheet;
                    EditorUtility.SetDirty(target.Importer);
                    target.Importer.SaveAndReimport();
                }
            }

            for (int i = 0; i < targets.Length; i++)
            {
                if (targets[i] == null)
                {
                    return;
                }
            }

            serializedObject.Update();
        }
예제 #14
0
            /// <summary>Draws two float fields.</summary>
            public static float DoTwinFloatFieldGUI(Rect area, GUIContent label, float value, float normalizeMultiplier, bool isNormalized)
            {
                if (_PixelSuffixCache == null)
                {
                    _PixelSuffixCache      = new ConversionCache <float, string>((s) => s + "px");
                    _NormalizedSuffixCache = new ConversionCache <float, string>((x) => x + "x");
                }

                var split          = (area.width - EditorGUIUtility.labelWidth - AnimancerGUI.StandardSpacing) * 0.5f;
                var normalizedArea = AnimancerGUI.StealFromRight(ref area, Mathf.Floor(split), AnimancerGUI.StandardSpacing);

                var pixels     = isNormalized ? value / normalizeMultiplier : value;
                var normalized = isNormalized ? value : value * normalizeMultiplier;

                EditorGUI.BeginChangeCheck();
                pixels = AnimancerGUI.DoSpecialFloatField(area, label, pixels, _PixelSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    value = isNormalized ? pixels * normalizeMultiplier : pixels;
                }

                EditorGUI.BeginChangeCheck();
                normalized = AnimancerGUI.DoSpecialFloatField(normalizedArea, null, normalized, _NormalizedSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    value = isNormalized ? normalized : normalized / normalizeMultiplier;
                }

                return(value);
            }
예제 #15
0
        private void DoRootMotionGUI()
        {
            if (_RootMotion == null)
            {
                return;
            }

            var text = AnimancerGUI.GetNarrowText("Apply Root Motion");

            var animator = _Animators[0];

            if (_Animators.Length == 1 && (bool)AnimancerEditorUtilities.Invoke(animator, "get_supportsOnAnimatorMove"))
            {
                EditorGUILayout.LabelField(text, "Handled by Script");
            }
            else
            {
                EditorGUILayout.PropertyField(_RootMotion, AnimancerGUI.TempContent(text,
                                                                                    "If enabled, the Animator will automatically move the object using the root motion from the animations"));

                if (Event.current.type == EventType.Layout)
                {
                    _IsRootPositionOrRotationControlledByCurves =
                        (bool)AnimancerEditorUtilities.Invoke(animator, "get_isRootPositionOrRotationControlledByCurves");
                }

                if (_IsRootPositionOrRotationControlledByCurves && !_RootMotion.boolValue)
                {
                    EditorGUILayout.HelpBox("Root position or rotation are controlled by curves", MessageType.Info, true);
                }
            }
        }
예제 #16
0
        private static void GetEventLabels(int index, Context context, out GUIContent timeLabel, out string callbackLabel,
                                           out float defaultTime, out bool isEndEvent)
        {
            if (index >= context.TimeCount - 1)
            {
                timeLabel = AnimancerGUI.TempContent("End Time",
                                                     Strings.ProOnlyTag + "The time when the end callback will be triggered");

                callbackLabel = "End Callback";

                defaultTime = AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(
                    context.TransitionContext.Transition.Speed);
                isEndEvent = true;
            }
            else
            {
                if (_CallbackLabelCache == null)
                {
                    _CallbackLabelCache = new ConversionCache <int, string>((i) => "Event " + i + " Callback");
                    _TimeLabelCache     = new ConversionCache <int, string>((i) => "Event " + i + " Time");
                }

                timeLabel = AnimancerGUI.TempContent(_TimeLabelCache.Convert(index),
                                                     Strings.ProOnlyTag + "The time when the callback will be triggered");

                callbackLabel = _CallbackLabelCache.Convert(index);

                defaultTime = 0;
                isEndEvent  = false;
            }
        }
예제 #17
0
        /************************************************************************************************************************/

        /// <summary>
        /// Draws the <see cref="Animator.cullingMode"/> field.
        /// </summary>
        private void DoCullingModeGUI()
        {
            if (_CullingMode == null)
            {
                return;
            }

            var label = AnimancerGUI.TempContent("Culling Mode",
                                                 "Controls what is updated when the object has been culled (when it is not being rendered by a Camera)");

            EditorGUI.BeginChangeCheck();

            EditorGUILayout.PropertyField(_CullingMode, label);

            if (EditorGUI.EndChangeCheck())
            {
                _OnEndGUI += () =>
                {
                    for (int i = 0; i < Targets.Length; i++)
                    {
                        var animator = _Animators[i];
                        if (animator != null)
                        {
                            AnimancerEditorUtilities.Invoke(animator, "OnCullingModeChanged");
                        }
                    }
                };
            }
        }
예제 #18
0
            /************************************************************************************************************************/

            private bool DoHeadingLink(string heading, string description, string url, string displayURL = null)
            {
                if (DoLinkLabel(heading, description))
                {
                    Application.OpenURL(url);
                }

                bool clicked;

                if (displayURL == null)
                {
                    displayURL = url;
                }

                var content = AnimancerGUI.TempContent(displayURL,
                                                       "Click to copy this link to the clipboard", false);

                var area = AnimancerGUI.LayoutSingleLineRect();

                if (GUI.Button(area, content, GUIStyles.URL))
                {
                    GUIUtility.systemCopyBuffer = displayURL;
                    Debug.Log("Copied '" + displayURL + "' to the clipboard.");
                    clicked = true;
                }
                else
                {
                    clicked = false;
                }

                EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Text);

                return(clicked);
            }
예제 #19
0
        /// <summary>Draws a box describing the internal details of the `playable`.</summary>
        internal void DoInternalDetailsGUI(AnimancerPlayable playable)
        {
            if (Event.current.type == EventType.Layout)
            {
                var text = ObjectPool.AcquireStringBuilder();
                playable.AppendInternalDetails(text, "", " - ");
                _UpdateListLabel = text.ReleaseToString();
            }

            if (_UpdateListLabel == null)
            {
                return;
            }

            var style = ObjectPool.GetCachedResult(() => new GUIStyle(GUI.skin.box)
            {
                alignment    = TextAnchor.MiddleLeft,
                wordWrap     = false,
                stretchWidth = true,
            });

            var content = AnimancerGUI.TempContent(_UpdateListLabel, null, false);
            var height  = style.CalcHeight(content, 0);
            var area    = GUILayoutUtility.GetRect(0, height, style);

            GUI.Box(area, content, style);

            CheckContextMenu(area, playable);
        }
예제 #20
0
        /************************************************************************************************************************/

        /// <summary>Draws the GUI the the target transition's main property.</summary>
        protected virtual void DoMainPropertyGUI(Rect area, out Rect labelArea,
                                                 SerializedProperty rootProperty, SerializedProperty mainProperty)
        {
            labelArea = area;
            if (mainProperty == null)
            {
                return;
            }

            var fullArea = area;

            labelArea = AnimancerGUI.StealFromLeft(ref area, EditorGUIUtility.labelWidth, AnimancerGUI.StandardSpacing);

            var mainPropertyReferenceIsMissing =
                mainProperty.propertyType == SerializedPropertyType.ObjectReference &&
                mainProperty.objectReferenceValue == null;

            var hierarchyMode = EditorGUIUtility.hierarchyMode;

            EditorGUIUtility.hierarchyMode = true;

            if (rootProperty.propertyType == SerializedPropertyType.ManagedReference)
            {
                if (rootProperty.isExpanded || _Mode == Mode.AlwaysExpanded)
                {
                    EditorGUI.indentLevel++;

                    AnimancerGUI.NextVerticalArea(ref fullArea);
                    using (ObjectPool.Disposable.AcquireContent(out var label, mainProperty))
                        EditorGUI.PropertyField(fullArea, mainProperty, label, true);

                    EditorGUI.indentLevel--;
                }
            }
            else
            {
                var indentLevel = EditorGUI.indentLevel;
                EditorGUI.indentLevel = 0;

                EditorGUI.PropertyField(area, mainProperty, GUIContent.none, true);

                EditorGUI.indentLevel = indentLevel;
            }

            EditorGUIUtility.hierarchyMode = hierarchyMode;

            // If the main Object reference was just assigned and all fields were at their type default,
            // reset the value to run its default constructor and field initializers then reassign the reference.
            var reference = mainProperty.objectReferenceValue;

            if (mainPropertyReferenceIsMissing && reference != null)
            {
                mainProperty.objectReferenceValue = null;
                if (Serialization.IsDefaultValueByType(rootProperty))
                {
                    rootProperty.GetAccessor().ResetValue(rootProperty);
                }
                mainProperty.objectReferenceValue = reference;
            }
        }
예제 #21
0
 /// <summary>
 /// If <see cref="AnimationClip"/>s or <see cref="IAnimationClipSource"/>s are dropped inside the `dropArea`,
 /// this method creates a new state in the `target` for each animation.
 /// </summary>
 public static void HandleDragAndDropAnimations(Rect dropArea, IAnimancerComponent target, int layerIndex)
 {
     AnimancerGUI.HandleDragAndDropAnimations(dropArea, (clip) =>
     {
         target.Playable.Layers[layerIndex].GetOrCreateState(clip);
     });
 }
예제 #22
0
        /************************************************************************************************************************/

        /// <summary>Draws the rest of the Inspector fields after the Animator field.</summary>
        protected void DoOtherFieldsGUI()
        {
            var property = serializedObject.GetIterator();

            if (!property.NextVisible(true))
            {
                return;
            }

            do
            {
                using (ObjectPool.Disposable.Acquire <GUIContent>(out var label))
                {
                    var path = property.propertyPath;
                    if (path == "m_Script")
                    {
                        continue;
                    }

                    label.text    = AnimancerGUI.GetNarrowText(property.displayName);
                    label.tooltip = property.tooltip;

                    // Let the target try to override.
                    if (DoOverridePropertyGUI(property.propertyPath, property, label))
                    {
                        continue;
                    }

                    // Otherwise draw the property normally.
                    EditorGUILayout.PropertyField(property, label, true);
                }
            }while (property.NextVisible(false));
        }
예제 #23
0
        /// <summary>
        /// If the `property` is a "Start Time" field, this method draws it as well as the "End Time" below it and
        /// returns true.
        /// </summary>
        public static bool TryDoStartTimeField(ref Rect area, SerializedProperty rootProperty,
                                               SerializedProperty property, GUIContent label)
        {
            if (!property.propertyPath.EndsWith("." + NormalizedStartTimeFieldName))
            {
                return(false);
            }

            // Start Time.
            label.text = AnimancerGUI.GetNarrowText("Start Time");
            var length           = Context.MaximumDuration;
            var defaultStartTime = AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(Context.Transition.Speed);

            AnimancerGUI.DoOptionalTimeField(ref area, label, property, true, length, defaultStartTime);

            AnimancerGUI.NextVerticalArea(ref area);

            // End Time.
            var events = rootProperty.FindPropertyRelative("_Events");

            using (var context = EventSequenceDrawer.Context.Get(events))
            {
                var    areaCopy = area;
                var    index    = Mathf.Max(0, context.TimeCount - 1);
                string callbackLabel;
                EventSequenceDrawer.DoEventTimeGUI(ref areaCopy, context, index, true, out callbackLabel);
            }

            return(true);
        }
예제 #24
0
        /************************************************************************************************************************/

        /// <summary>Draws the root property of a transition with an optional main property on the same line.</summary>
        public void DoHeaderGUI(ref Rect area, SerializedProperty rootProperty, SerializedProperty mainProperty,
                                GUIContent label, bool isPreviewing)
        {
            area.height = AnimancerGUI.LineHeight;
            var labelArea = area;

            AnimancerGUI.NextVerticalArea(ref area);

            if (rootProperty.propertyType != SerializedPropertyType.ManagedReference)
            {
                DoPreviewButtonGUI(ref labelArea, rootProperty, isPreviewing);
            }

            // Draw the Root Property after the Main Property to give better spacing between the label and field.

            // Drawing the main property might assign its details to the label so we keep our own copy.
            using (ObjectPool.Disposable.AcquireContent(out var rootLabel, label.text, label.tooltip))
            {
                // Main Property.

                DoMainPropertyGUI(labelArea, out labelArea, rootProperty, mainProperty);

                // Root Property.

                rootLabel = EditorGUI.BeginProperty(labelArea, rootLabel, rootProperty);
                EditorGUI.LabelField(labelArea, rootLabel);
                EditorGUI.EndProperty();

                if (_Mode != Mode.AlwaysExpanded)
                {
                    rootProperty.isExpanded = EditorGUI.Foldout(labelArea, rootProperty.isExpanded, GUIContent.none, true);
                }
            }
        }
예제 #25
0
        /// <summary>[Editor-Only]
        /// Draws any custom GUI for the `property`.
        /// The return value indicates whether the GUI should replace the regular call to
        /// <see cref="EditorGUILayout.PropertyField(SerializedProperty, GUIContent, bool, GUILayoutOption[])"/> or
        /// not. True = GUI was drawn, so don't draw the regular GUI. False = Draw the regular GUI.
        /// </summary>
        protected override bool DoOverridePropertyGUI(string path, SerializedProperty property, GUIContent label)
        {
            if (path == Targets[0].ActionOnDisableFieldName)
            {
                EditorGUILayout.PropertyField(property, label, true);
                if (property.enumValueIndex == (int)AnimancerComponent.DisableAction.Reset)
                {
                    // Since getting all the components creates garbage, only do it during layout events.
                    if (Event.current.type == EventType.Layout)
                    {
                        _ShowResetOnDisableWarning = !AreAllResettingTargetsAboveTheirAnimator();
                    }

                    if (_ShowResetOnDisableWarning)
                    {
                        EditorGUILayout.HelpBox("Reset only works if this component is above the Animator" +
                                                " so OnDisable can perform the Reset before the Animator actually gets disabled." +
                                                " Click here to fix." +
                                                "\n\nOtherwise you can use Stop and call Animator.Rebind before disabling this GameObject.",
                                                MessageType.Error);

                        if (AnimancerGUI.TryUseClickEventInLastRect())
                        {
                            MoveResettingTargetsAboveTheirAnimator();
                        }
                    }
                }
                return(true);
            }

            return(base.DoOverridePropertyGUI(path, property, label));
        }
예제 #26
0
        /// <summary>
        /// If the `property` is a "Start Time" field, this method draws it as well as the "End Time" below it and
        /// returns true.
        /// </summary>
        public static bool TryDoStartTimeField(ref Rect area, SerializedProperty rootProperty,
                                               SerializedProperty property, GUIContent label)
        {
            if (!property.propertyPath.EndsWith("." + NormalizedStartTimeFieldName))
            {
                return(false);
            }

            // Start Time.
            label.text = AnimancerGUI.GetNarrowText("Start Time");
            AnimationTimeAttribute.nextDefaultValue = AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(Context.Transition.Speed);
            EditorGUI.PropertyField(area, property, label, false);

            AnimancerGUI.NextVerticalArea(ref area);

            // End Time.
            var events = rootProperty.FindPropertyRelative("_Events");

            using (var context = SerializableEventSequenceDrawer.Context.Get(events))
            {
                var areaCopy = area;
                var index    = Mathf.Max(0, context.Times.Count - 1);
                SerializableEventSequenceDrawer.DoTimeGUI(ref areaCopy, context, index, true);
            }

            return(true);
        }
        private void DoAnimationsField(SerializedProperty property)
        {
            GUILayout.Space(AnimancerGUI.StandardSpacing - 1);

            if (_Animations == null)
            {
                _Animations = new ReorderableList(property.serializedObject, property.Copy())
                {
                    drawHeaderCallback  = DrawAnimationsHeader,
                    drawElementCallback = DrawAnimationElement,
                    elementHeight       = AnimancerGUI.LineHeight,
                    onRemoveCallback    = RemoveSelectedElement,
                };
            }

            _RemoveAnimationIndex = -1;

            GUILayout.BeginVertical();
            _Animations.DoLayoutList();
            GUILayout.EndVertical();

            if (_RemoveAnimationIndex >= 0)
            {
                property.DeleteArrayElementAtIndex(_RemoveAnimationIndex);
            }

            AnimancerGUI.HandleDragAndDropAnimations(GUILayoutUtility.GetLastRect(), (clip) =>
            {
                var index                    = property.arraySize;
                property.arraySize           = index + 1;
                var element                  = property.GetArrayElementAtIndex(index);
                element.objectReferenceValue = clip;
                property.serializedObject.ApplyModifiedProperties();
            });
        }
예제 #28
0
파일: SpriteEditor.cs 프로젝트: malering/ET
        /************************************************************************************************************************/

        private void Apply()
        {
            AnimancerGUI.Deselect();
            _HasBeenModified = false;
            var targets = this.targets;

            var path        = AssetDatabase.GetAssetPath(targets[0]);
            var importer    = (TextureImporter)AssetImporter.GetAtPath(path);
            var spriteSheet = importer.spritesheet;
            var hasError    = false;

            for (int i = 0; i < targets.Length; i++)
            {
                Apply((Sprite)targets[i], spriteSheet, ref hasError);
            }

            if (!hasError)
            {
                importer.spritesheet = spriteSheet;
                EditorUtility.SetDirty(importer);
                importer.SaveAndReimport();
            }

            for (int i = 0; i < targets.Length; i++)
            {
                if (targets[i] == null)
                {
                    return;
                }
            }

            serializedObject.Update();
        }
예제 #29
0
        /************************************************************************************************************************/

        private void DoStatesGUI()
        {
            if (AnimancerPlayableDrawer.HideInactiveStates)
            {
                DoStatesGUI("Active States", ActiveStates);
            }
            else if (AnimancerPlayableDrawer.SeparateActiveFromInactiveStates)
            {
                DoStatesGUI("Active States", ActiveStates);
                DoStatesGUI("Inactive States", InactiveStates);
            }
            else
            {
                DoStatesGUI("States", ActiveStates);
            }

            if (Target.Index == 0 &&
                Target.Weight != 0 &&
                !Target.IsAdditive &&
                !Mathf.Approximately(Target.GetTotalWeight(), 1))
            {
                EditorGUILayout.HelpBox(
                    "The total Weight of all states in this layer does not equal 1, which will likely give undesirable results." +
                    " Click here for more information.",
                    MessageType.Warning);

                if (AnimancerGUI.TryUseClickEventInLastRect())
                {
                    EditorUtility.OpenWithDefaultApp(Strings.DocsURLs.Fading);
                }
            }
        }
예제 #30
0
        /************************************************************************************************************************/

        /// <summary>
        /// Draws a toggle inverted from the <see cref="Animator.keepAnimatorControllerStateOnDisable"/> field.
        /// </summary>
        private void DoStopOnDisableGUI()
        {
#if UNITY_2018_1_OR_NEWER
            var area = AnimancerGUI.LayoutSingleLineRect();

            var label = AnimancerGUI.TempContent("Stop On Disable",
                                                 "If true, disabling this object will stop and rewind all animations." +
                                                 " Otherwise they will simply be paused and will resume from their current states when it is re-enabled.");

            if (_KeepStateOnDisable != null)
            {
                _KeepStateOnDisable.serializedObject.Update();

                label = UnityEditor.EditorGUI.BeginProperty(area, label, _KeepStateOnDisable);

                _KeepStateOnDisable.boolValue = !UnityEditor.EditorGUI.Toggle(area, label, !_KeepStateOnDisable.boolValue);

                UnityEditor.EditorGUI.EndProperty();

                _KeepStateOnDisable.serializedObject.ApplyModifiedProperties();
            }
            else
            {
                var enabled = GUI.enabled;
                GUI.enabled = false;
                UnityEditor.EditorGUI.Toggle(area, label, false);
                GUI.enabled = enabled;
            }
#endif
        }