/************************************************************************************************************************/ 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(); }
/************************************************************************************************************************/ /// <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); }
/************************************************************************************************************************/ /// <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; }
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); }
/************************************************************************************************************************/ #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(); }
/************************************************************************************************************************/ 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; }
/************************************************************************************************************************/ 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); } }
/************************************************************************************************************************/ /// <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); }
/************************************************************************************************************************/ 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); } }
/************************************************************************************************************************/ /// <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 }
/************************************************************************************************************************/ 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--; }
/************************************************************************************************************************/ /// <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); }
/************************************************************************************************************************/ 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(); }
/// <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); }
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); } } }
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; } }
/************************************************************************************************************************/ /// <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"); } } }; } }
/************************************************************************************************************************/ 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); }
/// <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); }
/************************************************************************************************************************/ /// <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; } }
/// <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); }); }
/************************************************************************************************************************/ /// <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)); }
/// <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); }
/************************************************************************************************************************/ /// <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); } } }
/// <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)); }
/// <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(); }); }
/************************************************************************************************************************/ 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(); }
/************************************************************************************************************************/ 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); } } }
/************************************************************************************************************************/ /// <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 }