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