Search Unity

Can I clamp an AnimationCurve editor window to specific bounds ?

Discussion in 'Animation' started by mslinklater, Nov 28, 2014.

  1. mslinklater

    mslinklater

    Joined:
    Mar 1, 2013
    Posts:
    44
    Hi - We use AnimationCurve values for a lot of our gameplay tweak values. Whenever our designers click on an AnimationCurve to edit it the window which appears is clamped to the extents of the values in the curve. Is there a way to clamp to range to a different value ? Our designers are going bonkers having to constantly reset the zoom levels on the axes.

    Thanks.
     
  2. OllyNicholson

    OllyNicholson

    Unity Technologies

    Joined:
    Jun 17, 2011
    Posts:
    142
    Hi - you can use the middle mouse to zoom in and out and F to re-frame the curves, but at the moment there is no range value that can be set, to the best of my knowlegde - have it put on feedback and try and get it voted on as much as possible ;-)

    http://feedback.unity3d.com/
     
  3. RealSoftGames

    RealSoftGames

    Joined:
    Jun 8, 2014
    Posts:
    220
    sorry to open an old thread but has this been achieved yet. i am after something very similar i would like to clamp the values of an animation curve.
     
  4. Sycoforge

    Sycoforge

    Joined:
    Oct 6, 2013
    Posts:
    751
    You can create a custom editor and clamp the curve there. The example below clamps the curve to a normalized range ([0, 1]) in x- and y-direction.

    Code (CSharp):
    1. data.Mask.Curve = EditorGUILayout.CurveField(data.Mask.Curve, Color.red, new Rect(0, 0, 1, 1));
     
    oshoham and migueltuliompg like this.
  5. lgarczyn

    lgarczyn

    Joined:
    Nov 23, 2014
    Posts:
    68
    Hello, I found this and decided to show the full code


    BoundedCurveAttribute.cs

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class BoundedCurveAttribute : PropertyAttribute
    6. {
    7.   public Rect bounds;
    8.   public int height;
    9.  
    10.   public BoundedCurveAttribute(Rect bounds, int height = 1)
    11.   {
    12.     this.bounds = bounds;
    13.     this.height = height;
    14.   }
    15.  
    16.   public BoundedCurveAttribute(int height = 1)
    17.   {
    18.     this.bounds = new Rect(0, 0, 1, 1);
    19.     this.height = height;
    20.   }
    21. }
    22.  

    Editor/BoundedCurveDrawer.cs

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. [CustomPropertyDrawer(typeof(BoundedCurveAttribute))]
    5. public class BoundedCurveDrawer : PropertyDrawer
    6. {
    7.   public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    8.   {
    9.     BoundedCurveAttribute boundedCurve = (BoundedCurveAttribute)attribute;
    10.     return EditorGUIUtility.singleLineHeight * boundedCurve.height;
    11.   }
    12.  
    13.   public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    14.   {
    15.     BoundedCurveAttribute boundedCurve = (BoundedCurveAttribute)attribute;
    16.  
    17.     EditorGUI.BeginProperty(position, label, property);
    18.     property.animationCurveValue = EditorGUI.CurveField(
    19.       position,
    20.       label,
    21.       property.animationCurveValue,
    22.       Color.white,
    23.       boundedCurve.bounds
    24.      );
    25.     EditorGUI.EndProperty();
    26.   }
    27. }
     
    OhiraKyou likes this.
  6. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    Thank you very much! Although, I'm having trouble using it. The code below gives the error: Attribute constructor parameter 'bounds' has type 'Rect', which is not a valid attribute parameter type.

    Code (CSharp):
    1. [BoundedCurve(new Rect(0, 0, 1, 1), 2)][SerializeField] AnimationCurve pinWeightCurve;
     
    Last edited: Oct 20, 2022
  7. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    I replaced the faulty constructor in BoundedAttributes.cs with the following code:

    Code (CSharp):
    1. public BoundedCurveAttribute(float xMin, float yMin, float xMax, float yMax, int height = 1) {
    2.         this.bounds = new Rect(xMin, yMin, xMax, yMax);
    3.         this.guiHeight = height;
    4.     }
    5.  
    Edit: Added a new constructor where we only need the max size
    Code (CSharp):
    1. public BoundedCurveAttribute(float xMax, float yMax, int height = 1) {
    2.         this.bounds = new Rect(0, 0, xMax, yMax);
    3.         this.guiHeight = height;
    4.     }
     
    Last edited: Oct 20, 2022
    OhiraKyou likes this.
  8. lgarczyn

    lgarczyn

    Joined:
    Nov 23, 2014
    Posts:
    68
    Good catch, I've somehow only used the other constructor this whole time
     
  9. Lancaster_Gaming-ind

    Lancaster_Gaming-ind

    Joined:
    Jul 24, 2020
    Posts:
    3
    This code works really well, although I've noticed an issue that I cannot, for the life of me, find out how to fix.
    When opening the curve in a custom Inspector using "EditorGUILayout.PropertyField();" full-screening another window, like the game window returns an error reading:
    "Invalid editor window of type: UnityEditor.CurveEditorWindow, title: Curve"
    "UnityEditor.EditorApplication:Internal_CallDelayFunctions ()"
    I'm not sure how the other windows effect the curve window that I already closed, but I'd imagine it's just how Unity manages editor window calls.

    If anyone could help it would be a life-saver!
     
  10. lgarczyn

    lgarczyn

    Joined:
    Nov 23, 2014
    Posts:
    68
    Oh, I've also noticed that error, but didn't know it was caused by my code.

    This is probably a bug in CurveField, but I wouldn't know where to begin.

    Maybe adding some check in OnGUI that the window is actually displayed? Or checking the value of `position` in situation where errors are thrown ?