Files
FlaxEngine/Source/Editor/GUI/CurveEditor.Base.cs

317 lines
12 KiB
C#

// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI
{
/// <summary>
/// The base class for <see cref="CurveBase{T}"/> editors. Allows to use generic curve editor without type information at compile-time.
/// </summary>
[HideInEditor]
public abstract class CurveEditorBase : ContainerControl, IKeyframesEditor
{
/// <summary>
/// The UI use mode flags.
/// </summary>
[Flags]
public enum UseMode
{
/// <summary>
/// Disable usage.
/// </summary>
Off = 0,
/// <summary>
/// Allow only vertical usage.
/// </summary>
Vertical = 1,
/// <summary>
/// Allow only horizontal usage.
/// </summary>
Horizontal = 2,
/// <summary>
/// Allow both vertical and horizontal usage.
/// </summary>
On = Vertical | Horizontal,
}
/// <summary>
/// Occurs when curve gets edited.
/// </summary>
public event Action Edited;
/// <summary>
/// Occurs when curve data editing starts (via UI).
/// </summary>
public event Action EditingStart;
/// <summary>
/// Occurs when curve data editing ends (via UI).
/// </summary>
public event Action EditingEnd;
/// <summary>
/// The function for custom view panning. Gets input movement delta (in curve control space) and returns the renaming input delta to process by curve editor itself.
/// </summary>
public Func<Float2, Float2> CustomViewPanning;
/// <summary>
/// The maximum amount of keyframes to use in a single curve.
/// </summary>
public int MaxKeyframes = ushort.MaxValue;
/// <summary>
/// True if enable view zooming. Otherwise user won't be able to zoom in or out.
/// </summary>
public UseMode EnableZoom = UseMode.On;
/// <summary>
/// True if enable view panning. Otherwise user won't be able to move the view area.
/// </summary>
public UseMode EnablePanning = UseMode.On;
/// <summary>
/// Gets or sets the scroll bars usage.
/// </summary>
public abstract ScrollBars ScrollBars { get; set; }
/// <summary>
/// Enables drawing start/end values continuous lines.
/// </summary>
public bool ShowStartEndLines;
/// <summary>
/// Enables drawing background.
/// </summary>
public bool ShowBackground = true;
/// <summary>
/// Enables drawing time and values axes (lines and labels).
/// </summary>
public UseMode ShowAxes = UseMode.On;
/// <summary>
/// Gets the type of the curves keyframes value.
/// </summary>
public abstract Type ValueType { get; }
/// <summary>
/// The amount of frames per second of the curve animation (optional). Can be used to restrict the keyframes time values to the given time quantization rate.
/// </summary>
public abstract float? FPS { get; set; }
/// <summary>
/// Gets or sets a value indicating whether show curve collapsed as a list of keyframe points rather than a full curve.
/// </summary>
public abstract bool ShowCollapsed { get; set; }
/// <summary>
/// Gets or sets the view offset (via scroll bars).
/// </summary>
public abstract Float2 ViewOffset { get; set; }
/// <summary>
/// Gets or sets the view scale.
/// </summary>
public abstract Float2 ViewScale { get; set; }
/// <summary>
/// Gets the amount of keyframes added to the curve.
/// </summary>
public abstract int KeyframesCount { get; }
/// <summary>
/// Clears the selection.
/// </summary>
public abstract void ClearSelection();
/// <summary>
/// Called when curve gets edited.
/// </summary>
public void OnEdited()
{
Edited?.Invoke();
}
/// <summary>
/// Called when curve data editing starts (via UI).
/// </summary>
public void OnEditingStart()
{
EditingStart?.Invoke();
}
/// <summary>
/// Called when curve data editing ends (via UI).
/// </summary>
public void OnEditingEnd()
{
EditingEnd?.Invoke();
}
/// <summary>
/// Updates the keyframes positioning.
/// </summary>
public abstract void UpdateKeyframes();
/// <summary>
/// Updates the tangents positioning.
/// </summary>
public abstract void UpdateTangents();
/// <summary>
/// Shows the whole curve.
/// </summary>
public abstract void ShowWholeCurve();
/// <summary>
/// Resets the view.
/// </summary>
public void ResetView()
{
ViewScale = ApplyUseModeMask(EnableZoom, Float2.One, ViewScale);
ViewOffset = ApplyUseModeMask(EnablePanning, Float2.Zero, ViewOffset);
UpdateKeyframes();
}
/// <summary>
/// Evaluates the animation curve value at the specified time.
/// </summary>
/// <param name="result">The interpolated value from the curve at provided time.</param>
/// <param name="time">The time to evaluate the curve at.</param>
/// <param name="loop">If true the curve will loop when it goes past the end or beginning. Otherwise the curve value will be clamped.</param>
public abstract void Evaluate(out object result, float time, bool loop = false);
/// <summary>
/// Gets the keyframes collection (as boxed objects).
/// </summary>
/// <returns>The array of boxed keyframe values of type <see cref="BezierCurve{T}.Keyframe"/> or <see cref="LinearCurve{T}.Keyframe"/>.</returns>
public abstract object[] GetKeyframes();
/// <summary>
/// Sets the keyframes collection (as boxed objects).
/// </summary>
/// <param name="keyframes">The array of boxed keyframe values of type <see cref="BezierCurve{T}.Keyframe"/> or <see cref="LinearCurve{T}.Keyframe"/>.</param>
public abstract void SetKeyframes(object[] keyframes);
/// <summary>
/// Adds the new keyframe (as boxed object).
/// </summary>
/// <param name="time">The keyframe time.</param>
/// <param name="value">The keyframe value (boxed).</param>
/// <returns>The index of the keyframe.</returns>
public abstract int AddKeyframe(float time, object value);
/// <summary>
/// Adds the new keyframe (as boxed object).
/// </summary>
/// <param name="time">The keyframe time.</param>
/// <param name="value">The keyframe value (boxed).</param>
/// <param name="tangentIn">The keyframe 'In' tangent value (boxed).</param>
/// <param name="tangentOut">The keyframe 'Out' tangent value (boxed).</param>
/// <returns>The index of the keyframe.</returns>
public abstract int AddKeyframe(float time, object value, object tangentIn, object tangentOut);
/// <summary>
/// Gets the keyframe data (as boxed objects).
/// </summary>
/// <param name="index">The keyframe index.</param>
/// <param name="time">The keyframe time.</param>
/// <param name="value">The keyframe value (boxed).</param>
/// <param name="tangentIn">The keyframe 'In' tangent value (boxed).</param>
/// <param name="tangentOut">The keyframe 'Out' tangent value (boxed).</param>
public abstract void GetKeyframe(int index, out float time, out object value, out object tangentIn, out object tangentOut);
/// <summary>
/// Gets the existing keyframe value (as boxed object).
/// </summary>
/// <param name="index">The keyframe index.</param>
/// <returns>The keyframe value.</returns>
public abstract object GetKeyframe(int index);
/// <summary>
/// Sets the existing keyframe value (as boxed object).
/// </summary>
/// <param name="index">The keyframe index.</param>
/// <param name="value">The keyframe value.</param>
public abstract void SetKeyframeValue(int index, object value);
/// <summary>
/// Sets the existing keyframe value (as boxed object).
/// </summary>
/// <param name="index">The keyframe index.</param>
/// <param name="value">The keyframe value.</param>
/// <param name="tangentIn">The keyframe 'In' tangent value (boxed).</param>
/// <param name="tangentOut">The keyframe 'Out' tangent value (boxed).</param>
public abstract void SetKeyframeValue(int index, object value, object tangentIn, object tangentOut);
/// <summary>
/// Gets the keyframe point (in keyframes space).
/// </summary>
/// <param name="index">The keyframe index.</param>
/// <param name="component">The keyframe value component index.</param>
/// <returns>The point in time/value space.</returns>
public abstract Float2 GetKeyframePoint(int index, int component);
/// <summary>
/// Converts the <see cref="UseMode"/> into the <see cref="Float2"/> mask.
/// </summary>
/// <param name="mode">The mode.</param>
/// <returns>The mask.</returns>
protected static Float2 GetUseModeMask(UseMode mode)
{
return new Float2((mode & UseMode.Horizontal) == UseMode.Horizontal ? 1.0f : 0.0f, (mode & UseMode.Vertical) == UseMode.Vertical ? 1.0f : 0.0f);
}
/// <summary>
/// Filters the given value using the <see cref="UseMode"/>.
/// </summary>
/// <param name="mode">The mode.</param>
/// <param name="value">The value to process.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>The combined value.</returns>
protected static Float2 ApplyUseModeMask(UseMode mode, Float2 value, Float2 defaultValue)
{
return new Float2(
(mode & UseMode.Horizontal) == UseMode.Horizontal ? value.X : defaultValue.X,
(mode & UseMode.Vertical) == UseMode.Vertical ? value.Y : defaultValue.Y
);
}
/// <inheritdoc />
public IKeyframesEditorContext KeyframesEditorContext { get; set; }
/// <inheritdoc />
public abstract void OnKeyframesDeselect(IKeyframesEditor editor);
/// <inheritdoc />
public abstract void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection);
/// <inheritdoc />
public abstract int OnKeyframesSelectionCount();
/// <inheritdoc />
public abstract void OnKeyframesDelete(IKeyframesEditor editor);
/// <inheritdoc />
public abstract void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Float2 location, bool start, bool end);
/// <inheritdoc />
public abstract void OnKeyframesCopy(IKeyframesEditor editor, float? timeOffset, System.Text.StringBuilder data);
/// <inheritdoc />
public abstract void OnKeyframesPaste(IKeyframesEditor editor, float? timeOffset, string[] datas, ref int index);
/// <inheritdoc />
public abstract void OnKeyframesGet(string trackName, Action<string, float, object> get);
/// <inheritdoc />
public abstract void OnKeyframesSet(List<KeyValuePair<float, object>> keyframes);
}
}