Is there an example of AudioCurveRendering?

Hello,

I am trying to use the AudioCurveRendering class.

Scripting API

I do not yet fully understand using a delegate as an argument ( as AudioCurveRendering.DrawCurve requires ), but I have been able to get it to run without errors by creating my own function that has the same signature as the required delegate and passing it as the argument by its name. Maybe that’s all there is to it?

Anyway, it runs but not correctly. I cannot find an example of how to use AudioCurveRendering.DrawCurve. Does anyone know how to use it / provide a quick example?

Thanks

First of all they are supposed to be used inside editor code using IMGUI (which should be obvious since it’s located in the UnityEditor namespace).

Yes, the method just draws the data that your callback is providing. The parameter “x” of your callback is just the normalized position along the x axis and directly belongs to the position of your Rect. Your method should return a value between -1 and 1. In other words the normalized “y” value of your Rect with “0” being the center line.

Note that this method is ment to be used in a seperate GUIClip area. So the easiest way is to use BeginGroup / EndGroup. If you want to use GUILayout just do something like this:

Rect r = GUILayoutUtility.GetRect(1, 10000, 100, 10000);
GUI.BeginGroup(r);
AudioCurveRendering.DrawCurve(new Rect(0, 0, r.width, r.height), (t) => Mathf.Sin(t * Mathf.PI * 2), Color.black);
GUI.EndGroup();

This will reserve a rectangular space in the layout system of at least 1 pixel width and 100 pixel high but will try to reserve as much space possible (up to 10k).

Now we start a new GUIGroup to get a new GUIClip area so the local coordinates start again at 0,0. The actual rect we pass to DrawCurve is the same rect but using local coordinates. The callback used will draw a single sine wave period.

DrawCurve will simply “sample” your callback once for each pixel along the width of the rect. That means if the rect has a width of 300 pixels DrawCurve will call your callback 300 times to get the corresponding y value for each position. Finally it will draw straight lines between those points.

Instead of BeginGroup / EndGroup you can use AudioCurveRendering.BeginCurveFrame() and EndCurveFrame. It’s actually just a wrapper for this:

public static Rect BeginCurveFrame(Rect r)
{
    AudioCurveRendering.DrawCurveBackground(r);
    r = AudioCurveRendering.DrawCurveFrame(r);
    GUI.BeginGroup(r);
    return new Rect(0f, 0f, r.width, r.height);
}

So it basically does the same thing but in addition it draws a background rectangle and a frame around that rectangle before starting the group. So it’s ment to be used like this:

Rect r = AudioCurveRendering.BeginCurveFrame(GUILayoutUtility.GetRect(1, 10000, 100, 10000));
AudioCurveRendering.DrawCurve(r, (t) => Mathf.Sin(t * Mathf.PI * 2), Color.black);
AudioCurveRendering.EndCurveFrame();

Note that EndCurveFrame just does this:

public static void EndCurveFrame()
{
    GUI.EndGroup();
}

Also the other two methods are just:

public static void DrawCurveBackground(Rect r)
{
    EditorGUI.DrawRect(r, new Color(0.3f, 0.3f, 0.3f));
}
public static Rect DrawCurveFrame(Rect r)
{
    Rect result;
    if (Event.current.type != EventType.Repaint)
    {
        result = r;
    }
    else
    {
        EditorStyles.colorPickerBox.Draw(r, false, false, false, false);
        r.x += 1f;
        r.y += 1f;
        r.width -= 2f;
        r.height -= 2f;
        result = r;
    }
    return result;
}

So “DrawCurveBackground” just draws a solid background and “DrawCurveFrame” draws on internal editor GUIStyle that has a 1 pixel border rectangle. It also returns an inset rectangle which is supposed to be used as drawing area for the curve so it’s not overdrawing the frame.